Example #1
0
    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
Example #2
0
    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
Example #3
0
    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 = 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, **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
Example #7
0
 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)
Example #8
0
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
Example #10
0
    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()
Example #11
0
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)
Example #16
0
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)
Example #17
0
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