Source code for ota.pupil.pupil

import numpy as np
import cv2, pdb, os
from matplotlib import pyplot as plt

import scipy as sp
from scipy import ndimage
from math import *

[docs]class EmptyAreas(Exception): def __init__(self):
Exception.__init__(self,'No distinct pupil area detected following thresholding, frame may be overexposed or eye might be closed.')
[docs]class Pupil: """ Object to represent a pupil within a specific frame of the video. """ def __init__(self, frame, threshold=10, skip_init=False): """ Initialize pupil object and find it's center, and radius within frame Parameters ------------------------ frame : array_like Grayscale video frame containing pupil to be detected threshold: Uint8 Integer representing the value to use for image binary thresholding. Attributes ------------------------ center : Dictionary A dictionary object containing the column and row indexes of the pupil center within the frame 'c' : Center column index 'r' : Center row index radius : float Value representing the radius of the pupil in frame (distance measured in pixels) pupil_cnt : array_like Vector type object containing a list of points contained in the contour of the pupil. 0-index of point corresponds to column index 1-index of point corresponds to row index """ if skip_init is False: self.center_col, self.center_row, self.radius, self.contour = self.calc_pupil_properties_fit_ellipse(frame, threshold=threshold) else: self.center_col = None self.center_row = None self.radius = None self.contour = None
[docs] def calc_pupil_properties_fit_ellipse(self, frame, threshold=10): """ Find the location of the pupil center and the radius of the pupil within frame using a best fit ellipse. Parameters ----------------------- frame : array_like Grayscale video frame containing pupil to be detected threshold: Uint8 Integer representing the value to use for image binary thresholding. Returns ----------------------- center : Dictionary A dictionary object containing the column and row indexes of the pupil center within the frame 'c' : Center column index 'r' : Center row index radius : float Value representing the radius of the pupil in frame (distance measured in pixels) pupil_cnt : array_like Vector type object containing a list of points contained in the contour of the pupil. 0-index of point corresponds to column index 1-index of point corresponds to row index """ # Threshold the image ret, I = cv2.threshold(frame, threshold, 255, cv2.THRESH_BINARY_INV) # Get a list of contours within the image img, contours, heighrarchy = cv2.findContours(I, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # Get the index corresponding to the contour with the maximum enclosed area areas = [] if len(contours) == 1: areas.append(cv2.contourArea(contours[0])) else: for i in range(0, len(contours)): areas.append(cv2.contourArea(contours[i])) if not areas: raise EmptyAreas max_area_ind = areas.index(max(areas)) # Get the list of contour points that enclose the max area pupil_cnt = contours[max_area_ind] # Fit an ellipse to the pupil contour in a least squares sense ellipse = cv2.fitEllipse(pupil_cnt) # Obtain the relevant pupil information from the best fit ellipse col = ellipse[0][0] row = ellipse[0][1] minor_axis_length = ellipse[1][0] major_axis_length = ellipse[1][1] # Obtain a rough estimate of the radius by averaging the major and minor axis lengths radius = (major_axis_length + minor_axis_length)/4
return col, row, radius, pupil_cnt
[docs] def calc_pupil_properties_min_enclosing_circle(self, frame, threshold=10): """ Find the location of the pupil center and the radius of the pupil within frame using min enclosing circle. Parameters ----------------------- frame : array_like Grayscale video frame containing pupil to be detected threshold: Uint8 Integer representing the value to use for image binary thresholding. Returns ----------------------- center : Dictionary A dictionary object containing the column and row indexes of the pupil center within the frame 'c' : Center column index 'r' : Center row index radius : float Value representing the radius of the pupil in frame (distance measured in pixels) pupil_cnt : array_like Vector type object containing a list of points contained in the contour of the pupil. 0-index of point corresponds to column index 1-index of point corresponds to row index """ # Threshold the image ret, I = cv2.threshold(frame, threshold, 255, cv2.THRESH_BINARY_INV) # Get a list of contours within the image img, contours, heighrarchy = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # Get the index corresponding to the contour with the maximum enclosed area areas = [] if len(contours) == 1: areas.append(cv2.contourArea(contours[0])) else: for i in range(0, len(contours)): areas.append(cv2.contourArea(contours[i])) if not areas: raise EmptyAreas max_area_ind = areas.index(max(areas)) # Get the list of contour points that enclose the max area pupil_cnt = contours[max_area_ind] # Fit a circle to the contour and find the center and radius (col, row), radius = cv2.minEnclosingCircle(pupil_cnt)
return col, row, radius, pupil_cnt