def __init__(self): # self.backend = VanillaBackend() self.backend = WovenBackend() # self.backend = OpenCLBackend() self.target_kpixels = 80.0 # 8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1. self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0126 # 1./2000. self.max_radius_fraction = 0.12 # 1./8. self.min_fraction = 1. / 1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.return_sobel = 0 self.albino_mode = False self.albino_threshold = 10. self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u'sepfir', u'spline', u'fft', u'convolve2d'] self.result = None self.restrict_top = 0 self.restrict_bottom = 123 self.restrict_left = 0 self.restrict_right = 164
def __init__(self): self.backend = WovenBackend() #self.backend = OpenCLBackend() self.target_kpixels = 80.0 #8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1.0 self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0226 #1./2000. self.max_radius_fraction = 0.0956 #1./8. self.min_fraction = 1. / 1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.shortcut_at_sobel = 0 self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u"sepfir", u"spline", u"fft", u"convolve2d"] self.result = None
def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() self.shortcut_sobel = kwargs.get('shortcut_sobel', None) # following values in pixels self.cr_ray_length = kwargs.get('cr_ray_length', 10) self.pupil_ray_length = kwargs.get('pupil_ray_length', 25) self.cr_min_radius = kwargs.get('cr_min_radius', 2) self.pupil_min_radius = kwargs.get('pupil_min_radius', 3) # 14 # how many rays to shoot in the CR self.cr_n_rays = kwargs.get('cr_n_rays', 20) # how many rays to shoot in the pupil self.pupil_n_rays = kwargs.get('pupil_n_rays', 40) # how many pixels per sample along the ray self.cr_ray_sample_spacing = kwargs.get('cr_ray_sample_spacing', 0.5) self.pupil_ray_sample_spacing = kwargs.get('pupil_ray_sample_spacing', 1) self.cr_threshold = kwargs.get('cr_threshold', 1.) self.pupil_threshold = kwargs.get('pupil_threshold', 2.5) self.ray_sampling_method = kwargs.get('ray_sampling_method', 'interp') self.fitting_algorithm = kwargs.get('fitting_algorithm', 'ellipse_least_squares') self.pupil_rays = None self.cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters()
def __init__(self): self.backend = WovenBackend() #self.backend = OpenCLBackend() self.target_kpixels = 80.0 #8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1.0 self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0226 #1./2000. self.max_radius_fraction = 0.0956 #1./8. self.min_fraction = 1./1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.shortcut_at_sobel = 0 self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u"sepfir", u"spline", u"fft", u"convolve2d"] self.result = None
from numpy.random import rand import numpy from pylab import * test_im = (rand(2250,2250)).astype(numpy.float32) #test_im = (rand(768,1024)).astype(numpy.float32) row = array([0.25, 0.3, 0.4]).astype(numpy.float32) #row = array([0.25, 0.3, 0.4, 0.6, 0.7, 0.6, 0.4, 0.3, 0.25]).astype(numpy.float32) #row = array([0.25, 0.4, 0.6, 0.4, 0.25]).astype(numpy.float32) row = row / sum(row) col = row cl_backend = OpenCLBackend() vanilla_backend = VanillaBackend() woven_backend = WovenBackend() woven_backend.autotune(test_im) cl_backend.autotune(test_im) print("CL Filtering...") #row_dev = cl.Buffer(cl_backend.ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, 0, row.astype(float32)) #col_dev = cl.Buffer(cl_backend.ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, 0, col.astype(float32)) row_dev = DeviceBuffer(cl_backend.ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, row.astype(float32)) col_dev = DeviceBuffer(cl_backend.ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, col.astype(float32)) #print cl_backend.device.name cl_filtered = cl_backend.separable_convolution2d(test_im.astype(float32), row_dev, col_dev, readback_from_device=False, im_shape=test_im.shape, row_shape=row.shape, col_shape=col.shape) for i in range(0,8): cl_filtered = cl_backend.separable_convolution2d(cl_filtered, row_dev, col_dev, readback_from_device=False, im_shape=test_im.shape, row_shape=row.shape, col_shape=col.shape)
class FastRadialFeatureFinder(EyeFeatureFinder): def __init__(self): self.backend = WovenBackend() #self.backend = OpenCLBackend() self.target_kpixels = 80.0 #8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1.0 self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0226 #1./2000. self.max_radius_fraction = 0.0956 #1./8. self.min_fraction = 1. / 1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.shortcut_at_sobel = 0 self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u"sepfir", u"spline", u"fft", u"convolve2d"] self.result = None # analyze the image and return dictionary of features gleaned # from it ##@clockit def analyze_image(self, image, guess=None, **kwargs): #print "fr" im_array = image #im_array = image.astype(double) im_array = im_array[::self.ds_factor, ::self.ds_factor] if (guess != None): features = guess else: features = {'pupil_size': None, 'cr_size': None} if (self.parameters_updated or self.backend.cached_shape != im_array.shape): print "Recaching..." print "Target kPixels: ", self.target_kpixels print "Max Radius Fraction: ", self.max_radius_fraction print "Radius steps: ", self.radius_steps im_pixels = image.shape[0] * image.shape[1] self.ds_factor = int( sqrt(im_pixels / int(self.target_kpixels * 1000))) if (self.ds_factor <= 0): self.ds_factor = 1 im_array = image[::self.ds_factor, ::self.ds_factor] self.backend.autotune(im_array) self.parameters_updated = 0 self.radiuses_to_try = linspace( ceil(self.min_radius_fraction * im_array.shape[0]), ceil(self.max_radius_fraction * im_array.shape[0]), self.radius_steps) self.radiuses_to_try = unique(self.radiuses_to_try.astype(int)) print "Radiuses to try: ", self.radiuses_to_try print "Downsampling factor: ", self.ds_factor ds = self.ds_factor S = self.backend.fast_radial_transform(im_array, self.radiuses_to_try, self.alpha) (min_coords, max_coords) = self.backend.find_minmax(S) if (self.correct_downsampling): features['pupil_position'] = array([min_coords[0], min_coords[1] ]) * ds features['cr_position'] = array([max_coords[0], max_coords[1] ]) * ds features['dwnsmp_factor_coord'] = 1 else: features['pupil_position'] = array([min_coords[0], min_coords[1]]) features['cr_position'] = array([max_coords[0], max_coords[1]]) features['dwnsmp_factor_coord'] = ds features['transform'] = S features['im_array'] = im_array features['im_shape'] = im_array.shape self.result = features def update_parameters(self): self.parameters_updated = 1 def get_result(self): return self.result
class SubpixelStarburstEyeFeatureFinder(EyeFeatureFinder): def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() self.shortcut_sobel = kwargs.get('shortcut_sobel', None) # following values in pixels self.cr_ray_length = kwargs.get('cr_ray_length', 10) self.pupil_ray_length = kwargs.get('pupil_ray_length', 25) self.cr_min_radius = kwargs.get('cr_min_radius', 2) self.pupil_min_radius = kwargs.get('pupil_min_radius', 3) # 14 # how many rays to shoot in the CR self.cr_n_rays = kwargs.get('cr_n_rays', 20) # how many rays to shoot in the pupil self.pupil_n_rays = kwargs.get('pupil_n_rays', 40) # how many pixels per sample along the ray self.cr_ray_sample_spacing = kwargs.get('cr_ray_sample_spacing', 0.5) self.pupil_ray_sample_spacing = kwargs.get('pupil_ray_sample_spacing', 1) self.cr_threshold = kwargs.get('cr_threshold', 1.) self.pupil_threshold = kwargs.get('pupil_threshold', 2.5) self.ray_sampling_method = kwargs.get('ray_sampling_method', 'interp') self.fitting_algorithm = kwargs.get('fitting_algorithm', 'ellipse_least_squares') self.pupil_rays = None self.cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters() def set_param(self, param, value): new = (value != self.get_param(param)) EyeFeatureFinder.set_param(self, param, value) if new: self.update_parameters() def update_parameters(self): """ Reconstruct internal representations in response to new parameters being set Recache rays, set method pointers, and clear storage for returned starburst parameters """ if self.ray_sampling_method == 'interp': self._get_image_values = self._get_image_values_interp_faster else: self._get_image_values = self._get_image_values_nearest if self.fitting_algorithm == 'circle_least_squares': self._fit_points = self._fit_circle_to_points_lstsq elif self.fitting_algorithm == 'circle_least_squares_ransac': self._fit_points = self._fit_circle_to_points_lstsq_ransac elif self.fitting_algorithm == 'ellipse_least_squares': self._fit_points = self._fit_ellipse_to_points else: self._fit_points = self._fit_mean_to_points # how many samples per ray self.cr_ray_sampling = arange(0, self.cr_ray_length, self.cr_ray_sample_spacing) self.cr_ray_sampling = self.cr_ray_sampling[1:] # don't need the zero sample self.cr_min_radius_ray_index = round(self.cr_min_radius / self.cr_ray_sample_spacing) self.pupil_ray_sampling = arange(0, self.pupil_ray_length, self.pupil_ray_sample_spacing) self.pupil_ray_sampling = self.pupil_ray_sampling[1:] # don't need the zero sample self.pupil_min_radius_ray_index = round(self.pupil_min_radius / self.pupil_ray_sample_spacing) # ray BY ray samples BY x/y self.cr_rays = zeros((self.cr_n_rays, len(self.cr_ray_sampling), 2)) self.pupil_rays = zeros((self.pupil_n_rays, len(self.pupil_ray_sampling), 2)) # Choose ray angles in the range [0, 2pi) self.cr_ray_angles = linspace(0, 2 * pi, self.cr_n_rays + 1) self.cr_ray_angles = self.cr_ray_angles[0:-1] self.pupil_ray_angles = linspace(0, 2 * pi, self.pupil_n_rays + 1) self.pupil_ray_angles = self.pupil_ray_angles[0:-1] for r in range(0, self.cr_n_rays): ray_angle = self.cr_ray_angles[r] self.cr_rays[r, :, self.x_axis] = self.cr_ray_sampling \ * cos(ray_angle) self.cr_rays[r, :, self.y_axis] = self.cr_ray_sampling \ * sin(ray_angle) for r in range(0, self.pupil_n_rays): ray_angle = self.pupil_ray_angles[r] self.pupil_rays[r, :, self.x_axis] = self.pupil_ray_sampling \ * cos(ray_angle) self.pupil_rays[r, :, self.y_axis] = self.pupil_ray_sampling \ * sin(ray_angle) self.cr_boundary_points = None self.pupil_boundary_points = None self.cr_ray_starts = None self.cr_ray_ends = None self.pupil_ray_starts = None self.pupil_ray_ends = None self.parameters_updated = True # #@clockit def analyze_image(self, image, guess, **kwargs): """ Begin processing an image to find features """ # print "sb" use_weave = 0 if 'weave' in kwargs: use_weave = kwargs['weave'] # Clear the result self.result = None features = {} if guess is not None and 'frame_number' in guess: features['frame_number'] = guess['frame_number'] if guess is not None and 'restrict_top' in guess: features['restrict_top'] = guess['restrict_top'] features['restrict_bottom'] = guess['restrict_bottom'] features['restrict_left'] = guess['restrict_left'] features['restrict_right'] = guess['restrict_right'] # This is the starting seed-point from which we will start cr_guess = guess['cr_position'] pupil_guess = guess['pupil_position'] if 'cached_sobel' in guess: self.shortcut_sobel = guess['cached_sobel'] # image = double(image) # compute the image gradient if self.shortcut_sobel == None: (image_grad_mag, image_grad_x, image_grad_y) = \ self.backend.sobel3x3(image) else: image_grad_mag = self.shortcut_sobel # Do the heavy lifting # try: if use_weave: cr_boundaries = self._find_ray_boundaries_woven(image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) else: cr_boundaries = self._find_ray_boundaries(image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) (cr_position, cr_radius, cr_err) = self._fit_points(cr_boundaries) # do a two-stage starburst fit for the pupil # stage 1, rough cut # self.pupil_min_radius_ray_index pupil_boundaries = self._find_ray_boundaries( image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius=2 * cr_radius, ) (pupil_position, pupil_radius, pupil_err) = \ self._fit_points(pupil_boundaries) # stage 2: refine minimum_pupil_guess = round(0.5 * pupil_radius / self.pupil_ray_sample_spacing) pupil_boundaries = self._find_ray_boundaries( image_grad_mag, pupil_position, self.pupil_rays, minimum_pupil_guess, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius=2 * cr_radius, ) (pupil_position, pupil_radius, pupil_err) = \ self._fit_points(pupil_boundaries) # if(False and use_weave): # pupil_boundaries = self._find_ray_boundaries_woven(image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius= 1.2 * cr_radius) # else: # pupil_boundaries = self._find_ray_boundaries(image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius= 1.2 * cr_radius) # # pupil_position, pupil_radius, pupil_err = self._fit_points(pupil_boundaries) # except Exception, e: # print "Error analyzing image: %s" % e.message # formatted = formatted_exception() # print formatted[0], ": " # for f in formatted[2]: # print f # cr_position = cr_guess # cr_radius = 0.0 # pupil_position = pupil_guess # pupil_radius = 0.0 # Pack up the results try: features['transform'] = guess.get('transform', None) features['cr_position'] = cr_position features['pupil_position'] = pupil_position features['cr_radius'] = cr_radius features['pupil_radius'] = pupil_radius starburst = {} starburst['cr_boundary'] = cr_boundaries starburst['pupil_boundary'] = pupil_boundaries starburst['cr_rays_start'] = self.cr_rays[:, 0, :] + cr_guess starburst['cr_rays_end'] = self.cr_rays[:, -1, :] + cr_guess starburst['pupil_rays_start'] = self.pupil_rays[:, 0, :] \ + pupil_guess starburst['pupil_rays_end'] = self.pupil_rays[:, -1, :] \ + pupil_guess starburst['cr_err'] = cr_err starburst['pupil_err'] = pupil_err features['starburst'] = starburst except Exception, e: print 'Error packing up results of image analysis' print e.message formatted = formatted_exception() print formatted[0], ': ' for f in formatted[2]: print f # raise self.result = features
def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() if ('shortcut_sobel' in kwargs): self.shortcut_sobel = kwargs['shortcut_sobel'] else: self.shortcut_sobel = None # max cr ray length as pixels if ('cr_ray_length' in kwargs): self.cr_ray_length = kwargs['cr_ray_length'] else: self.cr_ray_length = 10 # max pupil ray length as pixels if ('pupil_ray_length' in kwargs): self.pupil_ray_length = kwargs['pupil_ray_length'] else: self.pupil_ray_length = 25 # max cr ray length as pixels if ('cr_min_radius' in kwargs): self.cr_min_radius = kwargs['cr_min_radius'] else: self.cr_min_radius = 2 # max cr ray length as pixels if ('pupil_min_radius' in kwargs): self.pupil_min_radius = kwargs['pupil_min_radius'] else: self.pupil_min_radius = 14 # how many rays to shoot in the CR if ('cr_n_rays' in kwargs): self.cr_n_rays = kwargs['cr_n_rays'] else: self.cr_n_rays = 20 # how many rays to shoot in the pupil if ('pupil_n_rays' in kwargs): self.pupil_n_rays = kwargs['pupil_n_rays'] else: self.pupil_n_rays = 40 # how many pixels per sample along the ray if ('cr_ray_sample_spacing' in kwargs): self.cr_ray_sample_spacing = kwargs['cr_ray_sample_spacing'] else: self.cr_ray_sample_spacing = 0.5 # how many pixels per sample along the ray if ('pupil_ray_sample_spacing' in kwargs): self.pupil_ray_sample_spacing = kwargs['pupil_ray_sample_spacing'] else: self.pupil_ray_sample_spacing = 1 if ('cr_threshold' in kwargs): self.cr_threshold = kwargs['cr_threshold'] else: self.cr_threshold = 1.0 if ('pupil_threshold' in kwargs): self.pupil_threshold = kwargs['pupil_threshold'] else: self.pupil_threshold = 1.0 if ('ray_sampling_method' in kwargs): self.ray_sampling_method = kwargs['ray_sampling_method'] else: self.ray_sampling_method = 'interp' if ('fitting_algorithm' in kwargs): self.fitting_algorithm = kwargs['fitting_algorithm'] else: self.fitting_algorithm = 'ellipse_least_squares' pupil_rays = None cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters()
class SubpixelStarburstEyeFeatureFinder(EyeFeatureFinder): def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() if ('shortcut_sobel' in kwargs): self.shortcut_sobel = kwargs['shortcut_sobel'] else: self.shortcut_sobel = None # max cr ray length as pixels if ('cr_ray_length' in kwargs): self.cr_ray_length = kwargs['cr_ray_length'] else: self.cr_ray_length = 10 # max pupil ray length as pixels if ('pupil_ray_length' in kwargs): self.pupil_ray_length = kwargs['pupil_ray_length'] else: self.pupil_ray_length = 25 # max cr ray length as pixels if ('cr_min_radius' in kwargs): self.cr_min_radius = kwargs['cr_min_radius'] else: self.cr_min_radius = 2 # max cr ray length as pixels if ('pupil_min_radius' in kwargs): self.pupil_min_radius = kwargs['pupil_min_radius'] else: self.pupil_min_radius = 14 # how many rays to shoot in the CR if ('cr_n_rays' in kwargs): self.cr_n_rays = kwargs['cr_n_rays'] else: self.cr_n_rays = 20 # how many rays to shoot in the pupil if ('pupil_n_rays' in kwargs): self.pupil_n_rays = kwargs['pupil_n_rays'] else: self.pupil_n_rays = 40 # how many pixels per sample along the ray if ('cr_ray_sample_spacing' in kwargs): self.cr_ray_sample_spacing = kwargs['cr_ray_sample_spacing'] else: self.cr_ray_sample_spacing = 0.5 # how many pixels per sample along the ray if ('pupil_ray_sample_spacing' in kwargs): self.pupil_ray_sample_spacing = kwargs['pupil_ray_sample_spacing'] else: self.pupil_ray_sample_spacing = 1 if ('cr_threshold' in kwargs): self.cr_threshold = kwargs['cr_threshold'] else: self.cr_threshold = 1.0 if ('pupil_threshold' in kwargs): self.pupil_threshold = kwargs['pupil_threshold'] else: self.pupil_threshold = 1.0 if ('ray_sampling_method' in kwargs): self.ray_sampling_method = kwargs['ray_sampling_method'] else: self.ray_sampling_method = 'interp' if ('fitting_algorithm' in kwargs): self.fitting_algorithm = kwargs['fitting_algorithm'] else: self.fitting_algorithm = 'ellipse_least_squares' pupil_rays = None cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters() def update_parameters(self): """ Reconstruct internal representations in response to new parameters being set Recache rays, set method pointers, and clear storage for returned starburst parameters """ if (self.ray_sampling_method == "interp"): self._get_image_values = self._get_image_values_interp_faster else: self._get_image_values = self._get_image_values_nearest if (self.fitting_algorithm == 'circle_least_squares'): self._fit_points = self._fit_circle_to_points_lstsq elif (self.fitting_algorithm == 'circle_least_squares_ransac'): self._fit_points = self._fit_circle_to_points_lstsq_ransac elif (self.fitting_algorithm == 'ellipse_least_squares'): self._fit_points = self._fit_ellipse_to_points else: self._fit_points = self._fit_mean_to_points # how many samples per ray self.cr_ray_sampling = arange(0, self.cr_ray_length, self.cr_ray_sample_spacing) self.cr_ray_sampling = self.cr_ray_sampling[ 1:] # don't need the zero sample self.cr_min_radius_ray_index = round(self.cr_min_radius / self.cr_ray_sample_spacing) self.pupil_ray_sampling = arange(0, self.pupil_ray_length, self.pupil_ray_sample_spacing) self.pupil_ray_sampling = self.pupil_ray_sampling[ 1:] # don't need the zero sample self.pupil_min_radius_ray_index = round(self.pupil_min_radius / self.pupil_ray_sample_spacing) # ray BY ray samples BY x/y self.cr_rays = zeros((self.cr_n_rays, len(self.cr_ray_sampling), 2)) self.pupil_rays = zeros( (self.pupil_n_rays, len(self.pupil_ray_sampling), 2)) # Choose ray angles in the range [0, 2pi) self.cr_ray_angles = linspace(0, 2 * pi, self.cr_n_rays + 1) self.cr_ray_angles = self.cr_ray_angles[0:-1] self.pupil_ray_angles = linspace(0, 2 * pi, self.pupil_n_rays + 1) self.pupil_ray_angles = self.pupil_ray_angles[0:-1] for r in range(0, self.cr_n_rays): ray_angle = self.cr_ray_angles[r] self.cr_rays[r, :, self.x_axis] = self.cr_ray_sampling * cos(ray_angle) self.cr_rays[r, :, self.y_axis] = self.cr_ray_sampling * sin(ray_angle) for r in range(0, self.pupil_n_rays): ray_angle = self.pupil_ray_angles[r] self.pupil_rays[ r, :, self.x_axis] = self.pupil_ray_sampling * cos(ray_angle) self.pupil_rays[ r, :, self.y_axis] = self.pupil_ray_sampling * sin(ray_angle) self.cr_boundary_points = None self.pupil_boundary_points = None self.cr_ray_starts = None self.cr_ray_ends = None self.pupil_ray_starts = None self.pupil_ray_ends = None self.parameters_updated = True ##@clockit def analyze_image(self, image, guess, **kwargs): """ Begin processing an image to find features """ #print "sb" use_weave = 0 if ("weave" in kwargs): use_weave = kwargs["weave"] # Clear the result self.result = None features = {} if guess is not None and "frame_number" in guess: features["frame_number"] = guess["frame_number"] # This is the starting seed-point from which we will start cr_guess = guess["cr_position"] pupil_guess = guess["pupil_position"] if ("cached_sobel" in guess): self.shortcut_sobel = guess["cached_sobel"] #image = double(image) # compute the image gradient if (self.shortcut_sobel == None): image_grad_mag, image_grad_x, image_grad_y = self.backend.sobel3x3( image) else: image_grad_mag = self.shortcut_sobel # Do the heavy lifting try: if (use_weave): cr_boundaries = self._find_ray_boundaries_woven( image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) else: cr_boundaries = self._find_ray_boundaries( image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) cr_position, cr_radius, cr_err = self._fit_points(cr_boundaries) if (use_weave): pupil_boundaries = self._find_ray_boundaries_woven( image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius=1.2 * cr_radius) else: pupil_boundaries = self._find_ray_boundaries( image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius=1.2 * cr_radius) pupil_position, pupil_radius, pupil_err = self._fit_points( pupil_boundaries) except Exception, e: print "Error analyzing image: %s" % e.message print cr_boundaries print pupil_boundaries formatted = formatted_exception() print formatted[0], ": " for f in formatted[2]: print f cr_position = cr_guess cr_radius = 0.0 pupil_position = pupil_guess pupil_radius = 0.0 # Pack up the results try: features["cr_position"] = cr_position features["pupil_position"] = pupil_position features["cr_radius"] = cr_radius features["pupil_radius"] = pupil_radius starburst = {} starburst["cr_boundary"] = cr_boundaries starburst["pupil_boundary"] = pupil_boundaries starburst["cr_rays_start"] = self.cr_rays[:, 0, :] + cr_guess starburst["cr_rays_end"] = self.cr_rays[:, -1, :] + cr_guess starburst["pupil_rays_start"] = self.pupil_rays[:, 0, :] + pupil_guess starburst["pupil_rays_end"] = self.pupil_rays[:, -1, :] + pupil_guess features["starburst"] = starburst except Exception, e: print "Error packing up results of image analysis" print e.message formatted = formatted_exception() print formatted[0], ": " for f in formatted[2]: print f
def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() if('shortcut_sobel' in kwargs): self.shortcut_sobel = kwargs['shortcut_sobel'] else: self.shortcut_sobel = None # max cr ray length as pixels if('cr_ray_length' in kwargs): self.cr_ray_length = kwargs['cr_ray_length'] else: self.cr_ray_length = 10 # max pupil ray length as pixels if('pupil_ray_length' in kwargs): self.pupil_ray_length = kwargs['pupil_ray_length'] else: self.pupil_ray_length = 25 # max cr ray length as pixels if('cr_min_radius' in kwargs): self.cr_min_radius = kwargs['cr_min_radius'] else: self.cr_min_radius = 2 # max cr ray length as pixels if('pupil_min_radius' in kwargs): self.pupil_min_radius = kwargs['pupil_min_radius'] else: self.pupil_min_radius = 14 # how many rays to shoot in the CR if('cr_n_rays' in kwargs): self.cr_n_rays = kwargs['cr_n_rays'] else: self.cr_n_rays = 20 # how many rays to shoot in the pupil if('pupil_n_rays' in kwargs): self.pupil_n_rays = kwargs['pupil_n_rays'] else: self.pupil_n_rays = 40 # how many pixels per sample along the ray if('cr_ray_sample_spacing' in kwargs): self.cr_ray_sample_spacing = kwargs['cr_ray_sample_spacing'] else: self.cr_ray_sample_spacing = 0.5 # how many pixels per sample along the ray if('pupil_ray_sample_spacing' in kwargs): self.pupil_ray_sample_spacing = kwargs['pupil_ray_sample_spacing'] else: self.pupil_ray_sample_spacing = 1 if('cr_threshold' in kwargs): self.cr_threshold = kwargs['cr_threshold'] else: self.cr_threshold = 1.0 if('pupil_threshold' in kwargs): self.pupil_threshold = kwargs['pupil_threshold'] else: self.pupil_threshold = 1.0 if('ray_sampling_method' in kwargs): self.ray_sampling_method = kwargs['ray_sampling_method'] else: self.ray_sampling_method = 'interp' if('fitting_algorithm' in kwargs): self.fitting_algorithm = kwargs['fitting_algorithm'] else: self.fitting_algorithm = 'ellipse_least_squares' pupil_rays = None cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters()
class SubpixelStarburstEyeFeatureFinder(EyeFeatureFinder): def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() if('shortcut_sobel' in kwargs): self.shortcut_sobel = kwargs['shortcut_sobel'] else: self.shortcut_sobel = None # max cr ray length as pixels if('cr_ray_length' in kwargs): self.cr_ray_length = kwargs['cr_ray_length'] else: self.cr_ray_length = 10 # max pupil ray length as pixels if('pupil_ray_length' in kwargs): self.pupil_ray_length = kwargs['pupil_ray_length'] else: self.pupil_ray_length = 25 # max cr ray length as pixels if('cr_min_radius' in kwargs): self.cr_min_radius = kwargs['cr_min_radius'] else: self.cr_min_radius = 2 # max cr ray length as pixels if('pupil_min_radius' in kwargs): self.pupil_min_radius = kwargs['pupil_min_radius'] else: self.pupil_min_radius = 14 # how many rays to shoot in the CR if('cr_n_rays' in kwargs): self.cr_n_rays = kwargs['cr_n_rays'] else: self.cr_n_rays = 20 # how many rays to shoot in the pupil if('pupil_n_rays' in kwargs): self.pupil_n_rays = kwargs['pupil_n_rays'] else: self.pupil_n_rays = 40 # how many pixels per sample along the ray if('cr_ray_sample_spacing' in kwargs): self.cr_ray_sample_spacing = kwargs['cr_ray_sample_spacing'] else: self.cr_ray_sample_spacing = 0.5 # how many pixels per sample along the ray if('pupil_ray_sample_spacing' in kwargs): self.pupil_ray_sample_spacing = kwargs['pupil_ray_sample_spacing'] else: self.pupil_ray_sample_spacing = 1 if('cr_threshold' in kwargs): self.cr_threshold = kwargs['cr_threshold'] else: self.cr_threshold = 1.0 if('pupil_threshold' in kwargs): self.pupil_threshold = kwargs['pupil_threshold'] else: self.pupil_threshold = 1.0 if('ray_sampling_method' in kwargs): self.ray_sampling_method = kwargs['ray_sampling_method'] else: self.ray_sampling_method = 'interp' if('fitting_algorithm' in kwargs): self.fitting_algorithm = kwargs['fitting_algorithm'] else: self.fitting_algorithm = 'ellipse_least_squares' pupil_rays = None cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters() def update_parameters(self): """ Reconstruct internal representations in response to new parameters being set Recache rays, set method pointers, and clear storage for returned starburst parameters """ if(self.ray_sampling_method == "interp"): self._get_image_values = self._get_image_values_interp_faster else: self._get_image_values = self._get_image_values_nearest if(self.fitting_algorithm == 'circle_least_squares'): self._fit_points = self._fit_circle_to_points_lstsq elif(self.fitting_algorithm == 'circle_least_squares_ransac'): self._fit_points = self._fit_circle_to_points_lstsq_ransac elif(self.fitting_algorithm == 'ellipse_least_squares'): self._fit_points = self._fit_ellipse_to_points else: self._fit_points = self._fit_mean_to_points # how many samples per ray self.cr_ray_sampling = arange(0, self.cr_ray_length, self.cr_ray_sample_spacing) self.cr_ray_sampling = self.cr_ray_sampling[1:] # don't need the zero sample self.cr_min_radius_ray_index = round(self.cr_min_radius / self.cr_ray_sample_spacing) self.pupil_ray_sampling = arange(0, self.pupil_ray_length, self.pupil_ray_sample_spacing) self.pupil_ray_sampling = self.pupil_ray_sampling[1:] # don't need the zero sample self.pupil_min_radius_ray_index = round(self.pupil_min_radius / self.pupil_ray_sample_spacing) # ray BY ray samples BY x/y self.cr_rays = zeros((self.cr_n_rays, len(self.cr_ray_sampling), 2)) self.pupil_rays = zeros((self.pupil_n_rays, len(self.pupil_ray_sampling), 2)) # Choose ray angles in the range [0, 2pi) self.cr_ray_angles = linspace(0, 2*pi, self.cr_n_rays+1) self.cr_ray_angles = self.cr_ray_angles[0:-1] self.pupil_ray_angles = linspace(0, 2*pi, self.pupil_n_rays+1) self.pupil_ray_angles = self.pupil_ray_angles[0:-1] for r in range(0, self.cr_n_rays): ray_angle = self.cr_ray_angles[r] self.cr_rays[r, :, self.x_axis] = self.cr_ray_sampling * cos(ray_angle) self.cr_rays[r, :, self.y_axis] = self.cr_ray_sampling * sin(ray_angle) for r in range(0, self.pupil_n_rays): ray_angle = self.pupil_ray_angles[r] self.pupil_rays[r, :, self.x_axis] = self.pupil_ray_sampling * cos(ray_angle) self.pupil_rays[r, :, self.y_axis] = self.pupil_ray_sampling * sin(ray_angle) self.cr_boundary_points = None self.pupil_boundary_points = None self.cr_ray_starts = None self.cr_ray_ends = None self.pupil_ray_starts = None self.pupil_ray_ends = None self.parameters_updated = True ##@clockit def analyze_image(self, image, guess, **kwargs): """ Begin processing an image to find features """ #print "sb" use_weave = 0 if("weave" in kwargs): use_weave = kwargs["weave"] # Clear the result self.result = None features ={} if guess is not None and "frame_number" in guess: features["frame_number"] = guess["frame_number"] # This is the starting seed-point from which we will start cr_guess = guess["cr_position"] pupil_guess = guess["pupil_position"] if("cached_sobel" in guess): self.shortcut_sobel = guess["cached_sobel"] #image = double(image) # compute the image gradient if(self.shortcut_sobel == None): image_grad_mag, image_grad_x, image_grad_y = self.backend.sobel3x3(image) else: image_grad_mag = self.shortcut_sobel # Do the heavy lifting try: if(use_weave): cr_boundaries = self._find_ray_boundaries_woven(image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) else: cr_boundaries = self._find_ray_boundaries(image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) cr_position, cr_radius, cr_err = self._fit_points(cr_boundaries) if(use_weave): pupil_boundaries = self._find_ray_boundaries_woven(image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius= 1.2 * cr_radius) else: pupil_boundaries = self._find_ray_boundaries(image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius= 1.2 * cr_radius) pupil_position, pupil_radius, pupil_err = self._fit_points(pupil_boundaries) except Exception, e: print "Error analyzing image: %s" % e.message print cr_boundaries print pupil_boundaries formatted = formatted_exception() print formatted[0], ": " for f in formatted[2]: print f cr_position = cr_guess cr_radius = 0.0 pupil_position = pupil_guess pupil_radius = 0.0 # Pack up the results try: features["cr_position"] = cr_position features["pupil_position"] = pupil_position features["cr_radius"] = cr_radius features["pupil_radius"] = pupil_radius starburst = {} starburst["cr_boundary"] = cr_boundaries starburst["pupil_boundary"] = pupil_boundaries starburst["cr_rays_start"] = self.cr_rays[:,0,:] + cr_guess starburst["cr_rays_end"] = self.cr_rays[:,-1,:] + cr_guess starburst["pupil_rays_start"] = self.pupil_rays[:,0,:] + pupil_guess starburst["pupil_rays_end"] = self.pupil_rays[:,-1,:] + pupil_guess features["starburst"] = starburst except Exception, e: print "Error packing up results of image analysis" print e.message formatted = formatted_exception() print formatted[0], ": " for f in formatted[2]: print f
class FastRadialFeatureFinder (EyeFeatureFinder): def __init__(self): self.backend = WovenBackend() #self.backend = OpenCLBackend() self.target_kpixels = 80.0 #8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1.0 self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0226 #1./2000. self.max_radius_fraction = 0.0956 #1./8. self.min_fraction = 1./1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.shortcut_at_sobel = 0 self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u"sepfir", u"spline", u"fft", u"convolve2d"] self.result = None # analyze the image and return dictionary of features gleaned # from it ##@clockit def analyze_image(self, image, guess = None, **kwargs): #print "fr" im_array = image #im_array = image.astype(double) im_array = im_array[::self.ds_factor, ::self.ds_factor] if(guess != None): features = guess else: features = {'pupil_size' : None, 'cr_size' : None } if(self.parameters_updated or self.backend.cached_shape != im_array.shape): print "Recaching..." print "Target kPixels: ", self.target_kpixels print "Max Radius Fraction: ", self.max_radius_fraction print "Radius steps: ", self.radius_steps im_pixels = image.shape[0] * image.shape[1] self.ds_factor = int(sqrt(im_pixels / int(self.target_kpixels*1000))) if(self.ds_factor <= 0): self.ds_factor = 1 im_array = image[::self.ds_factor, ::self.ds_factor] self.backend.autotune(im_array) self.parameters_updated = 0 self.radiuses_to_try = linspace(ceil(self.min_radius_fraction*im_array.shape[0]), ceil(self.max_radius_fraction*im_array.shape[0]), self.radius_steps) self.radiuses_to_try = unique(self.radiuses_to_try.astype(int)) print "Radiuses to try: ", self.radiuses_to_try print "Downsampling factor: ", self.ds_factor ds = self.ds_factor; S = self.backend.fast_radial_transform(im_array, self.radiuses_to_try, self.alpha) (min_coords, max_coords) = self.backend.find_minmax(S) if(self.correct_downsampling): features['pupil_position'] = array([min_coords[0], min_coords[1]]) * ds features['cr_position'] = array([max_coords[0], max_coords[1]]) * ds features['dwnsmp_factor_coord'] = 1 else: features['pupil_position'] = array([min_coords[0], min_coords[1]]) features['cr_position'] = array([max_coords[0], max_coords[1]]) features['dwnsmp_factor_coord'] = ds features['transform'] = S features['im_array'] = im_array features['im_shape'] = im_array.shape self.result = features def update_parameters(self): self.parameters_updated = 1 def get_result(self): return self.result
class FastRadialFeatureFinder(EyeFeatureFinder): def __init__(self): # self.backend = VanillaBackend() self.backend = WovenBackend() # self.backend = OpenCLBackend() self.target_kpixels = 80.0 # 8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1. self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0126 # 1./2000. self.max_radius_fraction = 0.12 # 1./8. self.min_fraction = 1. / 1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.return_sobel = 0 self.albino_mode = False self.albino_threshold = 10. self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u'sepfir', u'spline', u'fft', u'convolve2d'] self.result = None self.restrict_top = 0 self.restrict_bottom = 123 self.restrict_left = 0 self.restrict_right = 164 # analyze the image and return dictionary of features gleaned # from it # @clockit def analyze_image(self, image, guess=None, **kwargs): # print "fr" im_array = image # im_array = image.astype(double) im_array = im_array[::self.ds_factor, ::self.ds_factor] if guess != None: features = guess else: features = {'pupil_size': None, 'cr_size': None} if self.parameters_updated or self.backend.cached_shape \ != im_array.shape: print 'Recaching...' print 'Target kPixels: ', self.target_kpixels print 'Max Radius Fraction: ', self.max_radius_fraction print 'Radius steps: ', self.radius_steps im_pixels = image.shape[0] * image.shape[1] self.ds_factor = int(sqrt(im_pixels / int(self.target_kpixels * 1000))) if self.ds_factor <= 0: self.ds_factor = 1 im_array = image[::self.ds_factor, ::self.ds_factor] self.backend.autotune(im_array) self.parameters_updated = 0 self.radiuses_to_try = linspace(ceil(self.min_radius_fraction * im_array.shape[0]), ceil(self.max_radius_fraction * im_array.shape[0]), self.radius_steps) self.radiuses_to_try = unique(self.radiuses_to_try.astype(int)) print 'Radiuses to try: ', self.radiuses_to_try print 'Downsampling factor: ', self.ds_factor ds = self.ds_factor S = self.backend.fast_radial_transform(im_array, self.radiuses_to_try, self.alpha) S[:, 0:self.restrict_left] = -1. S[:, self.restrict_right:] = -1. S[0:self.restrict_top, :] = -1. S[self.restrict_bottom:, :] = -1. if self.albino_mode: (pupil_coords, cr_coords) = self.find_albino_features(S, im_array) else: (pupil_coords, cr_coords) = self.backend.find_minmax(S) if pupil_coords == None: pupil_coords = array([0., 0.]) if cr_coords == None: cr_coords = array([0., 0.]) if self.correct_downsampling: features['pupil_position'] = array([pupil_coords[0], pupil_coords[1]]) * ds features['cr_position'] = array([cr_coords[0], cr_coords[1]]) * ds features['dwnsmp_factor_coord'] = 1 else: features['pupil_position'] = array([pupil_coords[0], pupil_coords[1]]) features['cr_position'] = array([cr_coords[0], cr_coords[1]]) features['dwnsmp_factor_coord'] = ds features['transform'] = S features['im_array'] = im_array features['im_shape'] = im_array.shape features['restrict_top'] = self.restrict_top features['restrict_bottom'] = self.restrict_bottom features['restrict_left'] = self.restrict_left features['restrict_right'] = self.restrict_right if self.return_sobel: # this is very inefficient, and only for debugging (m, x, y) = self.backend.sobel3x3(im_array) features['sobel'] = m self.result = features def update_parameters(self): self.parameters_updated = 1 def get_result(self): return self.result def find_albino_features(self, T, im): import scipy.ndimage as ndi binarized = zeros_like(T) binarized[T > self.albino_threshold] = True (labels, nlabels) = ndi.label(binarized) slices = ndi.find_objects(labels) intensities = [] transform_means = [] if len(slices) < 2: return (None, None) for s in slices: transform_means.append(mean(T[s])) intensities.append(mean(im[s])) sorted_transform_means = argsort(transform_means) candidate1 = sorted_transform_means[-1] candidate2 = sorted_transform_means[-2] c1_center = array(ndi.center_of_mass(im, labels, candidate1 + 1)) c2_center = array(ndi.center_of_mass(im, labels, candidate2 + 1)) if intensities[candidate1] > intensities[candidate2]: return (c2_center, c1_center) else: return (c1_center, c2_center)
class FastRadialFeatureFinder(EyeFeatureFinder): def __init__(self): # self.backend = VanillaBackend() self.backend = WovenBackend() # self.backend = OpenCLBackend() self.target_kpixels = 80.0 # 8.0 self.max_target_kpixels = 50.0 self.min_target_kpixels = 1. self.parameters_updated = 1 self.alpha = 10. self.min_radius_fraction = 0.0126 # 1./2000. self.max_radius_fraction = 0.12 # 1./8. self.min_fraction = 1. / 1000. self.max_fraction = 0.35 self.radius_steps = 6 self.radiuses_to_try = [1] self.ds_factor = 1 self.correct_downsampling = False self.do_refinement_phase = 0 self.return_sobel = 0 self.albino_mode = False self.albino_threshold = 10. self.cache_sobel = True self.cached_sobel = None self.compute_sobel_avg = True # for autofocus self.sobel_avg = None # Voting self.outlier_cutoff = 1. self.maxmin_consensus_votes = 1 self.image_contribution = 1 self.last_positions = [] self.available_filters = [u'sepfir', u'spline', u'fft', u'convolve2d'] self.result = None self.restrict_top = 0 self.restrict_bottom = 123 self.restrict_left = 0 self.restrict_right = 164 # analyze the image and return dictionary of features gleaned # from it # @clockit def analyze_image(self, image, guess=None, **kwargs): # print "fr" im_array = image # im_array = image.astype(double) im_array = im_array[::self.ds_factor, ::self.ds_factor] if guess != None: features = guess else: features = {'pupil_size': None, 'cr_size': None} if self.parameters_updated or self.backend.cached_shape \ != im_array.shape: logging.debug('Recaching...') logging.debug('Target kPixels: %s' % self.target_kpixels) logging.debug('Max Radius Fraction: %s' % self.max_radius_fraction) logging.debug('Radius steps: %s' % self.radius_steps) im_pixels = image.shape[0] * image.shape[1] self.ds_factor = int( sqrt(im_pixels / int(self.target_kpixels * 1000))) if self.ds_factor <= 0: self.ds_factor = 1 im_array = image[::self.ds_factor, ::self.ds_factor] self.backend.autotune(im_array) self.parameters_updated = 0 self.radiuses_to_try = linspace( ceil(self.min_radius_fraction * im_array.shape[0]), ceil(self.max_radius_fraction * im_array.shape[0]), self.radius_steps) self.radiuses_to_try = unique(self.radiuses_to_try.astype(int)) logging.debug('Radiuses to try: %s' % self.radiuses_to_try) logging.debug('Downsampling factor: %s' % self.ds_factor) ds = self.ds_factor S = self.backend.fast_radial_transform(im_array, self.radiuses_to_try, self.alpha) S[:, 0:self.restrict_left] = -1. S[:, self.restrict_right:] = -1. S[0:self.restrict_top, :] = -1. S[self.restrict_bottom:, :] = -1. if self.albino_mode: (pupil_coords, cr_coords) = self.find_albino_features(S, im_array) else: (pupil_coords, cr_coords) = self.backend.find_minmax(S) if pupil_coords == None: pupil_coords = array([0., 0.]) if cr_coords == None: cr_coords = array([0., 0.]) if self.correct_downsampling: features['pupil_position'] = array( [pupil_coords[0], pupil_coords[1]]) * ds features['cr_position'] = array([cr_coords[0], cr_coords[1]]) * ds features['dwnsmp_factor_coord'] = 1 else: features['pupil_position'] = array( [pupil_coords[0], pupil_coords[1]]) features['cr_position'] = array([cr_coords[0], cr_coords[1]]) features['dwnsmp_factor_coord'] = ds features['transform'] = S features['im_array'] = im_array features['im_shape'] = im_array.shape features['restrict_top'] = self.restrict_top features['restrict_bottom'] = self.restrict_bottom features['restrict_left'] = self.restrict_left features['restrict_right'] = self.restrict_right if self.return_sobel: # this is very inefficient, and only for debugging (m, x, y) = self.backend.sobel3x3(im_array) features['sobel'] = m self.result = features def update_parameters(self): self.parameters_updated = 1 def get_result(self): return self.result def find_albino_features(self, T, im): import scipy.ndimage as ndi binarized = zeros_like(T) binarized[T > self.albino_threshold] = True (labels, nlabels) = ndi.label(binarized) slices = ndi.find_objects(labels) intensities = [] transform_means = [] if len(slices) < 2: return (None, None) for s in slices: transform_means.append(mean(T[s])) intensities.append(mean(im[s])) sorted_transform_means = argsort(transform_means) candidate1 = sorted_transform_means[-1] candidate2 = sorted_transform_means[-2] c1_center = array(ndi.center_of_mass(im, labels, candidate1 + 1)) c2_center = array(ndi.center_of_mass(im, labels, candidate2 + 1)) if intensities[candidate1] > intensities[candidate2]: return (c2_center, c1_center) else: return (c1_center, c2_center)
class SubpixelStarburstEyeFeatureFinder(EyeFeatureFinder): def __init__(self, **kwargs): self.parameters_updated = False self.backend = WovenBackend() self.shortcut_sobel = kwargs.get('shortcut_sobel', None) # following values in pixels self.cr_ray_length = kwargs.get('cr_ray_length', 10) self.pupil_ray_length = kwargs.get('pupil_ray_length', 25) self.cr_min_radius = kwargs.get('cr_min_radius', 2) self.pupil_min_radius = kwargs.get('pupil_min_radius', 3) # 14 # how many rays to shoot in the CR self.cr_n_rays = kwargs.get('cr_n_rays', 20) # how many rays to shoot in the pupil self.pupil_n_rays = kwargs.get('pupil_n_rays', 40) # how many pixels per sample along the ray self.cr_ray_sample_spacing = kwargs.get('cr_ray_sample_spacing', 0.5) self.pupil_ray_sample_spacing = kwargs.get('pupil_ray_sample_spacing', 1) self.cr_threshold = kwargs.get('cr_threshold', 1.) self.pupil_threshold = kwargs.get('pupil_threshold', 2.5) self.ray_sampling_method = kwargs.get('ray_sampling_method', 'interp') self.fitting_algorithm = kwargs.get('fitting_algorithm', 'ellipse_least_squares') self.pupil_rays = None self.cr_rays = None self.x_axis = 0 self.y_axis = 1 # rebuild parameters and cached constructs based on the current # parameter settings self.update_parameters() def set_param(self, param, value): new = (value != self.get_param(param)) EyeFeatureFinder.set_param(self, param, value) if new: self.update_parameters() def update_parameters(self): """ Reconstruct internal representations in response to new parameters being set Recache rays, set method pointers, and clear storage for returned starburst parameters """ if self.ray_sampling_method == 'interp': self._get_image_values = self._get_image_values_interp_faster else: self._get_image_values = self._get_image_values_nearest if self.fitting_algorithm == 'circle_least_squares': self._fit_points = self._fit_circle_to_points_lstsq elif self.fitting_algorithm == 'circle_least_squares_ransac': self._fit_points = self._fit_circle_to_points_lstsq_ransac elif self.fitting_algorithm == 'ellipse_least_squares': self._fit_points = self._fit_ellipse_to_points else: self._fit_points = self._fit_mean_to_points # how many samples per ray self.cr_ray_sampling = arange(0, self.cr_ray_length, self.cr_ray_sample_spacing) self.cr_ray_sampling = self.cr_ray_sampling[ 1:] # don't need the zero sample self.cr_min_radius_ray_index = round(self.cr_min_radius / self.cr_ray_sample_spacing) self.pupil_ray_sampling = arange(0, self.pupil_ray_length, self.pupil_ray_sample_spacing) self.pupil_ray_sampling = self.pupil_ray_sampling[ 1:] # don't need the zero sample self.pupil_min_radius_ray_index = round(self.pupil_min_radius / self.pupil_ray_sample_spacing) # ray BY ray samples BY x/y self.cr_rays = zeros((self.cr_n_rays, len(self.cr_ray_sampling), 2)) self.pupil_rays = zeros( (self.pupil_n_rays, len(self.pupil_ray_sampling), 2)) # Choose ray angles in the range [0, 2pi) self.cr_ray_angles = linspace(0, 2 * pi, self.cr_n_rays + 1) self.cr_ray_angles = self.cr_ray_angles[0:-1] self.pupil_ray_angles = linspace(0, 2 * pi, self.pupil_n_rays + 1) self.pupil_ray_angles = self.pupil_ray_angles[0:-1] for r in range(0, self.cr_n_rays): ray_angle = self.cr_ray_angles[r] self.cr_rays[r, :, self.x_axis] = self.cr_ray_sampling \ * cos(ray_angle) self.cr_rays[r, :, self.y_axis] = self.cr_ray_sampling \ * sin(ray_angle) for r in range(0, self.pupil_n_rays): ray_angle = self.pupil_ray_angles[r] self.pupil_rays[r, :, self.x_axis] = self.pupil_ray_sampling \ * cos(ray_angle) self.pupil_rays[r, :, self.y_axis] = self.pupil_ray_sampling \ * sin(ray_angle) self.cr_boundary_points = None self.pupil_boundary_points = None self.cr_ray_starts = None self.cr_ray_ends = None self.pupil_ray_starts = None self.pupil_ray_ends = None self.parameters_updated = True # #@clockit def analyze_image(self, image, guess, **kwargs): """ Begin processing an image to find features """ # print "sb" use_weave = 0 if 'weave' in kwargs: use_weave = kwargs['weave'] # Clear the result self.result = None features = {} if guess is not None and 'frame_number' in guess: features['frame_number'] = guess['frame_number'] if guess is not None and 'restrict_top' in guess: features['restrict_top'] = guess['restrict_top'] features['restrict_bottom'] = guess['restrict_bottom'] features['restrict_left'] = guess['restrict_left'] features['restrict_right'] = guess['restrict_right'] # This is the starting seed-point from which we will start cr_guess = guess['cr_position'] pupil_guess = guess['pupil_position'] if 'cached_sobel' in guess: self.shortcut_sobel = guess['cached_sobel'] # image = double(image) # compute the image gradient if self.shortcut_sobel == None: (image_grad_mag, image_grad_x, image_grad_y) = \ self.backend.sobel3x3(image) else: image_grad_mag = self.shortcut_sobel # Do the heavy lifting # try: if use_weave: cr_boundaries = self._find_ray_boundaries_woven( image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) else: cr_boundaries = self._find_ray_boundaries( image_grad_mag, cr_guess, self.cr_rays, self.cr_min_radius_ray_index, self.cr_threshold) (cr_position, cr_radius, cr_err) = self._fit_points(cr_boundaries) # do a two-stage starburst fit for the pupil # stage 1, rough cut # self.pupil_min_radius_ray_index pupil_boundaries = self._find_ray_boundaries( image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius=2 * cr_radius, ) (pupil_position, pupil_radius, pupil_err) = \ self._fit_points(pupil_boundaries) # stage 2: refine minimum_pupil_guess = round(0.5 * pupil_radius / self.pupil_ray_sample_spacing) pupil_boundaries = self._find_ray_boundaries( image_grad_mag, pupil_position, self.pupil_rays, minimum_pupil_guess, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius=2 * cr_radius, ) (pupil_position, pupil_radius, pupil_err) = \ self._fit_points(pupil_boundaries) # if(False and use_weave): # pupil_boundaries = self._find_ray_boundaries_woven(image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius= 1.2 * cr_radius) # else: # pupil_boundaries = self._find_ray_boundaries(image_grad_mag, pupil_guess, self.pupil_rays, self.pupil_min_radius_ray_index, self.pupil_threshold, exclusion_center=array(cr_position), exclusion_radius= 1.2 * cr_radius) # # pupil_position, pupil_radius, pupil_err = self._fit_points(pupil_boundaries) # except Exception, e: # print "Error analyzing image: %s" % e.message # formatted = formatted_exception() # print formatted[0], ": " # for f in formatted[2]: # print f # cr_position = cr_guess # cr_radius = 0.0 # pupil_position = pupil_guess # pupil_radius = 0.0 # Pack up the results try: features['transform'] = guess.get('transform', None) features['cr_position'] = cr_position features['pupil_position'] = pupil_position features['cr_radius'] = cr_radius features['pupil_radius'] = pupil_radius starburst = {} starburst['cr_boundary'] = cr_boundaries starburst['pupil_boundary'] = pupil_boundaries starburst['cr_rays_start'] = self.cr_rays[:, 0, :] + cr_guess starburst['cr_rays_end'] = self.cr_rays[:, -1, :] + cr_guess starburst['pupil_rays_start'] = self.pupil_rays[:, 0, :] \ + pupil_guess starburst['pupil_rays_end'] = self.pupil_rays[:, -1, :] \ + pupil_guess starburst['cr_err'] = cr_err starburst['pupil_err'] = pupil_err features['starburst'] = starburst except Exception, e: print 'Error packing up results of image analysis' print e.message formatted = formatted_exception() print formatted[0], ': ' for f in formatted[2]: print f # raise self.result = features