Exemplo n.º 1
0
    def update(self, frame, events):
        if self.active:
            recent_pupil_positions = events['pupil_positions']
            gray_img = frame.gray

            if self.clicks_to_close <= 0:
                self.stop()
                return

            #detect the marker
            self.candidate_ellipses = get_candidate_ellipses(
                gray_img,
                area_threshold=self.area_threshold,
                dist_threshold=self.dist_threshold,
                min_ring_count=5,
                visual_debug=False)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos, (frame.width, frame.height),
                                     flip_y=True)

            else:
                self.detected = False
                self.pos = None  #indicate that no reference is detected

            #only save a valid ref position if within sample window of calibraiton routine
            on_position = self.lead_in < self.screen_marker_state < (
                self.lead_in + self.sample_duration)

            if on_position and self.detected:
                ref = {}
                ref["norm_pos"] = self.pos
                ref["screen_pos"] = marker_pos
                ref["timestamp"] = frame.timestamp
                self.ref_list.append(ref)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)

            # Animate the screen marker
            if self.screen_marker_state < self.sample_duration + self.lead_in + self.lead_out:
                if self.detected or not on_position:
                    self.screen_marker_state += 1
            else:
                self.screen_marker_state = 0
                self.active_site += 1
                logger.debug("Moving screen marker to site no %s" %
                             self.active_site)
                if self.active_site >= len(self.sites):
                    self.stop()
                    return

            #use np.arrays for per element wise math
            self.display_pos = np.array(self.sites[self.active_site])
            self.on_position = on_position
            self.button.status_text = '%s / %s' % (self.active_site, 9)
Exemplo n.º 2
0
    def update(self,frame,events):
        if self.active:
            recent_pupil_positions = events['pupil_positions']
            gray_img = frame.gray

            if self.clicks_to_close <=0:
                self.stop()
                return

            #detect the marker
            self.candidate_ellipses = get_candidate_ellipses(gray_img,
                                                            area_threshold=self.area_threshold,
                                                            dist_threshold=self.dist_threshold,
                                                            min_ring_count=5,
                                                            visual_debug=False)

            if len(self.candidate_ellipses) > 0:
                self.detected= True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos,(frame.width,frame.height),flip_y=True)

            else:
                self.detected = False
                self.pos = None #indicate that no reference is detected


            #only save a valid ref position if within sample window of calibraiton routine
            on_position = self.lead_in < self.screen_marker_state < (self.lead_in+self.sample_duration)

            if on_position and self.detected:
                ref = {}
                ref["norm_pos"] = self.pos
                ref["screen_pos"] = marker_pos
                ref["timestamp"] = frame.timestamp
                self.ref_list.append(ref)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)

            # Animate the screen marker
            if self.screen_marker_state < self.sample_duration+self.lead_in+self.lead_out:
                if self.detected or not on_position:
                    self.screen_marker_state += 1
            else:
                self.screen_marker_state = 0
                if not self.sites:
                    self.stop()
                    return
                self.active_site = self.sites.pop(0)
                logger.debug("Moving screen marker to site at %s %s"%tuple(self.active_site))



            #use np.arrays for per element wise math
            self.display_pos = np.array(self.active_site)
            self.on_position = on_position
            self.button.status_text = '%s / %s'%(self.active_site,9)
Exemplo n.º 3
0
    def update(self,frame,events):
        """
        gets called once every frame.
        reference positon need to be published to shared_pos
        if no reference was found, publish 0,0
        """
        if self.active:

            gray_img  = frame.gray

            if self.world_size is None:
                self.world_size = frame.width,frame.height
        
            self.candidate_ellipses = get_candidate_ellipses(gray_img,
                                                         area_threshold=self.area_threshold,
                                                         dist_threshold=self.dist_threshold,
                                                         min_ring_count=5,
                                                         visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                self.lastTime = frame.timestamp
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos,(frame.width,frame.height),flip_y=True)
#                smoother = 0.3
#                smooth_pos = np.array(self.smooth_pos)
#                pos = np.array(self.pos)
#                new_smooth_pos = smooth_pos + smoother*(pos-smooth_pos)
#                smooth_pos = new_smooth_pos
#                self.smooth_pos = list(smooth_pos)

                for p in events.get('gaze_positions',[]):
                        #gp_on_s = tuple(s.img_to_ref_surface(np.array(p['norm_gaze'])))
                        dist = np.linalg.norm(np.array(p['norm_pos'])-self.pos)
                        p['realtime gaze on circles'] = dist



#            else:
#                self.detected = False
#                timeDiff = frame.timestamp - self.lastTime
#                if timeDiff < 0.5:
#                    for p in events.get('gaze_positions',[]):
#                        #gp_on_s = tuple(s.img_to_ref_surface(np.array(p['norm_gaze'])))
#                        dist = np.linalg.norm(np.array(p['norm_pos'])-self.smooth_pos)
#                        p['realtime gaze on circles'] = dist
#                self.pos = None #indicate that no reference is detected





        else:
            pass
Exemplo n.º 4
0
    def update(self,frame,events):
        """
        gets called once every frame.
        reference positon need to be published to shared_pos
        if no reference was found, publish 0,0
        """
        if self.active:
            recent_pupil_positions = events['pupil_positions']

            gray_img  = frame.gray

            if self.world_size is None:
                self.world_size = frame.width,frame.height

            self.candidate_ellipses = get_candidate_ellipses(gray_img,
                                                            area_threshold=self.area_threshold,
                                                            dist_threshold=self.dist_threshold,
                                                            min_ring_count=5,
                                                            visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos,(frame.width,frame.height),flip_y=True)


            else:
                self.detected = False
                self.pos = None #indicate that no reference is detected


            # center dark or white?
            if self.detected:
                second_ellipse =  self.candidate_ellipses[1]
                col_slice = int(second_ellipse[0][0]-second_ellipse[1][0]/2),int(second_ellipse[0][0]+second_ellipse[1][0]/2)
                row_slice = int(second_ellipse[0][1]-second_ellipse[1][1]/2),int(second_ellipse[0][1]+second_ellipse[1][1]/2)
                marker_gray = gray_img[slice(*row_slice),slice(*col_slice)]
                avg = cv2.mean(marker_gray)[0] #CV2 fn return has changed!
                center = marker_gray[second_ellipse[1][1]/2,second_ellipse[1][0]/2]
                rel_shade = center-avg

                #auto_stop logic
                if rel_shade > 30:
                    #bright marker center found
                    self.auto_stop +=1
                    self.stop_marker_found = True

                else:
                    self.auto_stop = 0
                    self.stop_marker_found = False


            #tracking logic
            if self.detected and not self.stop_marker_found:
                # calculate smoothed manhattan velocity
                smoother = 0.3
                smooth_pos = np.array(self.smooth_pos)
                pos = np.array(self.pos)
                new_smooth_pos = smooth_pos + smoother*(pos-smooth_pos)
                smooth_vel_vec = new_smooth_pos - smooth_pos
                smooth_pos = new_smooth_pos
                self.smooth_pos = list(smooth_pos)
                #manhattan distance for velocity
                new_vel = abs(smooth_vel_vec[0])+abs(smooth_vel_vec[1])
                self.smooth_vel = self.smooth_vel + smoother*(new_vel-self.smooth_vel)

                #distance to last sampled site
                sample_ref_dist = smooth_pos-np.array(self.sample_site)
                sample_ref_dist = abs(sample_ref_dist[0])+abs(sample_ref_dist[1])

                # start counter if ref is resting in place and not at last sample site
                if not self.counter:

                    if self.smooth_vel < 0.01 and sample_ref_dist > 0.1:
                        self.sample_site = self.smooth_pos
                        audio.beep()
                        logger.debug("Steady marker found. Starting to sample %s datapoints" %self.counter_max)
                        self.counter = self.counter_max

                if self.counter:
                    if self.smooth_vel > 0.01:
                        audio.tink()
                        logger.debug("Marker moved to quickly: Aborted sample. Sampled %s datapoints. Looking for steady marker again."%(self.counter_max-self.counter))
                        self.counter = 0
                    else:
                        self.counter -= 1
                        ref = {}
                        ref["norm_pos"] = self.pos
                        ref["timestamp"] = frame.timestamp
                        self.ref_list.append(ref)
                        if self.counter == 0:
                            #last sample before counter done and moving on
                            audio.tink()
                            logger.debug("Sampled %s datapoints. Stopping to sample. Looking for steady marker again."%self.counter_max)


            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)

            if self.counter:
                if self.detected:
                    self.button.status_text = 'Sampling Gaze Data'
                else:
                    self.button.status_text = 'Marker Lost'
            else:
                self.button.status_text = 'Looking for Marker'



            #stop if autostop condition is satisfied:
            if self.auto_stop >=self.auto_stop_max:
                self.auto_stop = 0
                self.stop()


        else:
            pass
Exemplo n.º 5
0
    def update(self, frame, events):
        """
        gets called once every frame.
        reference positon need to be published to shared_pos
        if no reference was found, publish 0,0
        """
        if self.active:
            recent_pupil_positions = events['pupil_positions']

            gray_img = frame.gray

            if self.world_size is None:
                self.world_size = frame.width, frame.height

            self.candidate_ellipses = get_candidate_ellipses(
                gray_img,
                area_threshold=self.area_threshold,
                dist_threshold=self.dist_threshold,
                min_ring_count=5,
                visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos, (frame.width, frame.height),
                                     flip_y=True)

            else:
                self.detected = False
                self.pos = None  #indicate that no reference is detected

            # center dark or white?
            if self.detected:
                second_ellipse = self.candidate_ellipses[1]
                col_slice = int(second_ellipse[0][0] - second_ellipse[1][0] /
                                2), int(second_ellipse[0][0] +
                                        second_ellipse[1][0] / 2)
                row_slice = int(second_ellipse[0][1] - second_ellipse[1][1] /
                                2), int(second_ellipse[0][1] +
                                        second_ellipse[1][1] / 2)
                marker_gray = gray_img[slice(*row_slice), slice(*col_slice)]
                avg = cv2.mean(marker_gray)[0]  #CV2 fn return has changed!
                center = marker_gray[second_ellipse[1][1] / 2,
                                     second_ellipse[1][0] / 2]
                rel_shade = center - avg

                #auto_stop logic
                if rel_shade > 30:
                    #bright marker center found
                    self.auto_stop += 1
                    self.stop_marker_found = True

                else:
                    self.auto_stop = 0
                    self.stop_marker_found = False

            #tracking logic
            if self.detected and not self.stop_marker_found:
                # calculate smoothed manhattan velocity
                smoother = 0.3
                smooth_pos = np.array(self.smooth_pos)
                pos = np.array(self.pos)
                new_smooth_pos = smooth_pos + smoother * (pos - smooth_pos)
                smooth_vel_vec = new_smooth_pos - smooth_pos
                smooth_pos = new_smooth_pos
                self.smooth_pos = list(smooth_pos)
                #manhattan distance for velocity
                new_vel = abs(smooth_vel_vec[0]) + abs(smooth_vel_vec[1])
                self.smooth_vel = self.smooth_vel + smoother * (
                    new_vel - self.smooth_vel)

                #distance to last sampled site
                sample_ref_dist = smooth_pos - np.array(self.sample_site)
                sample_ref_dist = abs(sample_ref_dist[0]) + abs(
                    sample_ref_dist[1])

                # start counter if ref is resting in place and not at last sample site
                if not self.counter:

                    if self.smooth_vel < 0.01 and sample_ref_dist > 0.1:
                        self.sample_site = self.smooth_pos
                        audio.beep()
                        logger.debug(
                            "Steady marker found. Starting to sample %s datapoints"
                            % self.counter_max)
                        self.counter = self.counter_max

                if self.counter:
                    if self.smooth_vel > 0.01:
                        audio.tink()
                        logger.debug(
                            "Marker moved to quickly: Aborted sample. Sampled %s datapoints. Looking for steady marker again."
                            % (self.counter_max - self.counter))
                        self.counter = 0
                    else:
                        self.counter -= 1
                        ref = {}
                        ref["norm_pos"] = self.pos
                        ref["timestamp"] = frame.timestamp
                        self.ref_list.append(ref)
                        if self.counter == 0:
                            #last sample before counter done and moving on
                            audio.tink()
                            logger.debug(
                                "Sampled %s datapoints. Stopping to sample. Looking for steady marker again."
                                % self.counter_max)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)

            if self.counter:
                if self.detected:
                    self.button.status_text = 'Sampling Gaze Data'
                else:
                    self.button.status_text = 'Marker Lost'
            else:
                self.button.status_text = 'Looking for Marker'

            #stop if autostop condition is satisfied:
            if self.auto_stop >= self.auto_stop_max:
                self.auto_stop = 0
                self.stop()

        else:
            pass
Exemplo n.º 6
0
    def update(self, frame, events):

        recent_pupil_positions = events['gaze']

        #get world image size for error fitting later.
        if self.world_size is None:
            self.world_size = frame.width, frame.height
            self.res = np.sqrt(self.world_size[0]**2 + self.world_size[1]**2)

        if self.active:
            gray_img = frame.gray

            #detect the marker
            self.candidate_ellipses = get_candidate_ellipses(
                gray_img,
                area_threshold=self.area_threshold,
                dist_threshold=self.dist_threshold,
                min_ring_count=4,
                visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos, (frame.width, frame.height),
                                     flip_y=True)

            else:
                self.detected = False
                self.pos = None  #indicate that no reference is detected

            #only save a valid ref position if within sample window of calibraiton routine
            on_position = 0 < self.screen_marker_state < self.screen_marker_max - 50
            if on_position and self.detected:
                ref = {}
                ref["norm_pos"] = self.pos
                ref["timestamp"] = frame.timestamp
                ref['site'] = self.active_site
                self.ref_list.append(ref)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.gaze_list.append(p_pt)
            # Animate the screen marker
            if self.screen_marker_state < self.screen_marker_max:
                if self.detected or not on_position:
                    self.screen_marker_state += 1
            else:
                self.screen_marker_state = 0
                self.active_site += 1
                logger.debug("Moving screen marker to site no %s" %
                             self.active_site)
                if self.active_site == len(self.sites) - 2:
                    self.stop()
                    return

            # function to smoothly interpolate between points input:(0-screen_marker_max) output: (0-1)
            m, s = self.screen_marker_max, self.screen_marker_state

            interpolation_weight = np.tanh(
                ((s - 2 / 3. * m) * 4.) / (1 / 3. * m)) * (-.5) + .5

            #use np.arrays for per element wise math
            current = np.array(self.sites[self.active_site])
            next = np.array(self.sites[self.active_site + 1])
            # weighted sum to interpolate between current and next
            new_pos = current * interpolation_weight + next * (
                1 - interpolation_weight)
            #broadcast next commanded marker postion of screen
            self.display_pos = list(new_pos)
            self.on_position = on_position
Exemplo n.º 7
0
    def update(self,frame,events):

        recent_pupil_positions = events['pupil_positions']

        #get world image size for error fitting later.
        if self.world_size is None:
            self.world_size = frame.width,frame.height
            self.res = np.sqrt(self.world_size[0]**2+self.world_size[1]**2)

        if self.active:
            gray_img = frame.gray

            #detect the marker
            self.candidate_ellipses = get_candidate_ellipses(gray_img,
                                                            area_threshold=self.area_threshold,
                                                            dist_threshold=self.dist_threshold,
                                                            min_ring_count=4,
                                                            visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected= True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos,(frame.width,frame.height),flip_y=True)

            else:
                self.detected = False
                self.pos = None #indicate that no reference is detected


            #only save a valid ref position if within sample window of calibraiton routine
            on_position = 0 < self.screen_marker_state < self.screen_marker_max-50
            if on_position and self.detected:
                ref = {}
                ref["norm_pos"] = self.pos
                ref["timestamp"] = frame.timestamp
                ref['site'] = self.active_site
                self.ref_list.append(ref)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)
            # Animate the screen marker
            if self.screen_marker_state < self.screen_marker_max:
                if self.detected or not on_position:
                    self.screen_marker_state += 1
            else:
                self.screen_marker_state = 0
                self.active_site += 1
                logger.debug("Moving screen marker to site no %s"%self.active_site)
                if self.active_site == len(self.sites)-2:
                    self.stop()
                    return

            # function to smoothly interpolate between points input:(0-screen_marker_max) output: (0-1)
            m, s = self.screen_marker_max, self.screen_marker_state

            interpolation_weight = np.tanh(((s-2/3.*m)*4.)/(1/3.*m))*(-.5)+.5

            #use np.arrays for per element wise math
            current = np.array(self.sites[self.active_site])
            next = np.array(self.sites[self.active_site+1])
            # weighted sum to interpolate between current and next
            new_pos =  current * interpolation_weight + next * (1-interpolation_weight)
            #broadcast next commanded marker postion of screen
            self.display_pos = list(new_pos)
            self.on_position = on_position
Exemplo n.º 8
0
    def update(self,frame,events):
        if self.active:
            recent_pupil_positions = events['pupil_positions']
            gray_img = frame.gray

            if self.clicks_to_close <=0:
                self.stop()
                return

            #get world image size for error fitting later.
            if self.world_size is None:
                self.world_size = frame.width,frame.height

            #detect the marker
            self.candidate_ellipses = get_candidate_ellipses(gray_img,
                                                            area_threshold=self.area_threshold,
                                                            dist_threshold=self.dist_threshold,
                                                            min_ring_count=4,
                                                            visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected= True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos,(frame.width,frame.height),flip_y=True)

            else:
                self.detected = False
                self.pos = None #indicate that no reference is detected


            #only save a valid ref position if within sample window of calibraiton routine
            # on_position = 40 < self.screen_marker_state < self.screen_marker_max-5
            on_position = self.start_sample < self.screen_marker_state < self.stop_sample

            if on_position and self.detected:
                ref = {}
                ref["norm_pos"] = self.pos
                ref["timestamp"] = frame.timestamp
                self.ref_list.append(ref)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)

            # Animate the screen marker
            if self.screen_marker_state < self.screen_marker_max:
                if self.detected or not on_position:
                    self.screen_marker_state += 1
            else:
                self.screen_marker_state = 0
                self.active_site += 1
                logger.debug("Moving screen marker to site no %s"%self.active_site)
                if self.active_site == 10:
                    self.stop()
                    return
            events["calib_info"] = (self.screen_marker_state, self.active_site)
            # interpolation_weight = np.tanh(((s-1/6.*m)*10.)/(5/6.*m))*(-.5)+.5
            self.pattern_alpha = interp_fn(self.screen_marker_state,0.,1.,float(self.screen_marker_max),float(self.start_sample),float(self.stop_sample))

            #use np.arrays for per element wise math
            self.display_pos = np.array(self.sites[self.active_site])
            self.on_position = on_position
            self.button.status_text = '%s / %s'%(self.active_site,9)
Exemplo n.º 9
0
    def update(self,frame,events):
        """
        gets called once every frame.
        reference positon need to be published to shared_pos
        if no reference was found, publish 0,0
        """
        if self.active:
            recent_pupil_positions = events['pupil_positions']

            gray_img  = frame.gray

            if self.world_size is None:
                self.world_size = frame.width,frame.height

            self.candidate_ellipses = get_candidate_ellipses(gray_img,
                                                            area_threshold=self.area_threshold,
                                                            dist_threshold=self.dist_threshold,
                                                            min_ring_count=5,
                                                            visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos,(frame.width,frame.height),flip_y=True)



            else:
                self.detected = False
                self.pos = None #indicate that no reference is detected



            #tracking logic
            if self.detected:
                self.auto_stop +=1
                self.stop_marker_found = True

                # calculate smoothed manhattan velocity
                smoother = 0.3
                smooth_pos = np.array(self.smooth_pos)
                pos = np.array(self.pos)
                new_smooth_pos = smooth_pos + smoother*(pos-smooth_pos)
                smooth_vel_vec = new_smooth_pos - smooth_pos
                smooth_pos = new_smooth_pos
                self.smooth_pos = list(smooth_pos)
                #manhattan distance for velocity
                new_vel = abs(smooth_vel_vec[0])+abs(smooth_vel_vec[1])
                self.smooth_vel = self.smooth_vel + smoother*(new_vel-self.smooth_vel)

                #distance to last sampled site
                sample_ref_dist = smooth_pos-np.array(self.sample_site)
                sample_ref_dist = abs(sample_ref_dist[0])+abs(sample_ref_dist[1])

                # start counter if ref is resting in place and not at last sample site
                if not self.counter:

                    if self.smooth_vel < 0.01 and sample_ref_dist > 0.1:
                        self.sample_site = self.smooth_pos
                        audio.beep()
                        logger.debug("Steady marker found. Starting to sample %s datapoints" %self.counter_max)
                        self.counter = self.counter_max

                if self.counter:
                    if self.smooth_vel > 0.01:
                        audio.tink()
                        logger.warning("Marker moved to quickly: Aborted sample. Sampled %s datapoints. Looking for steady marker again."%(self.counter_max-self.counter))
                        self.counter = 0
                    else:
                        self.counter -= 1
                        ref = {}
                        ref["norm_pos"] = self.pos
                        ref["screen_pos"] =  denormalize(self.pos,(frame.width,frame.height),flip_y=True)
                        ref["timestamp"] = frame.timestamp
                        self.ref_list.append(ref)
                        if self.counter == 0:
                            #last sample before counter done and moving on
                            audio.tink()
                            logger.debug("Sampled %s datapoints. Stopping to sample. Looking for steady marker again."%self.counter_max)

            #always save pupil positions
            for pt in events.get('gaze_positions',[]):
                if pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    #we add an id for the calibration preprocess data to work as is usually expects pupil data.
                    pt['id'] = 0
                    self.gaze_list.append(pt)

            if self.counter:
                if self.detected:
                    self.button.status_text = 'Sampling Gaze Data'
                else:
                    self.button.status_text = 'Marker Lost'
            else:
                self.button.status_text = 'Looking for Marker'



            #stop if autostop condition is satisfied:
            if self.auto_stop >=self.auto_stop_max:
                self.auto_stop = 0
                self.stop()


        else:
            pass
Exemplo n.º 10
0
    def update(self, frame, events):
        """
        gets called once every frame.
        reference positon need to be published to shared_pos
        if no reference was found, publish 0,0
        """
        if self.active:
            recent_pupil_positions = events['pupil_positions']

            gray_img = frame.gray

            if self.world_size is None:
                self.world_size = frame.width, frame.height

            self.candidate_ellipses = get_candidate_ellipses(
                gray_img,
                area_threshold=self.area_threshold,
                dist_threshold=self.dist_threshold,
                min_ring_count=5,
                visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos, (frame.width, frame.height),
                                     flip_y=True)

            else:
                self.detected = False
                self.pos = None  #indicate that no reference is detected

            self.auto_stop += 1
            self.stop_marker_found = True

            #tracking logic
            if self.detected:
                # calculate smoothed manhattan velocity
                smoother = 0.3
                smooth_pos = np.array(self.smooth_pos)
                pos = np.array(self.pos)
                new_smooth_pos = smooth_pos + smoother * (pos - smooth_pos)
                smooth_vel_vec = new_smooth_pos - smooth_pos
                smooth_pos = new_smooth_pos
                self.smooth_pos = list(smooth_pos)
                #manhattan distance for velocity
                new_vel = abs(smooth_vel_vec[0]) + abs(smooth_vel_vec[1])
                self.smooth_vel = self.smooth_vel + smoother * (
                    new_vel - self.smooth_vel)

                #distance to last sampled site
                sample_ref_dist = smooth_pos - np.array(self.sample_site)
                sample_ref_dist = abs(sample_ref_dist[0]) + abs(
                    sample_ref_dist[1])

                # start counter if ref is resting in place and not at last sample site
                if not self.counter:

                    if self.smooth_vel < 0.01 and sample_ref_dist > 0.1:
                        self.sample_site = self.smooth_pos
                        audio.beep()
                        logger.debug(
                            "Steady marker found. Starting to sample %s datapoints"
                            % self.counter_max)
                        self.counter = self.counter_max

                if self.counter:
                    if self.smooth_vel > 0.01:
                        audio.tink()
                        logger.debug(
                            "Marker moved to quickly: Aborted sample. Sampled %s datapoints. Looking for steady marker again."
                            % (self.counter_max - self.counter))
                        self.counter = 0
                    else:
                        self.counter -= 1
                        ref = {}
                        ref["norm_pos"] = self.pos
                        ref["timestamp"] = frame.timestamp
                        self.ref_list.append(ref)
                        if self.counter == 0:
                            #last sample before counter done and moving on
                            audio.tink()
                            logger.debug(
                                "Sampled %s datapoints. Stopping to sample. Looking for steady marker again."
                                % self.counter_max)

            #always save pupil positions
            for pt in events.get('gaze_positions', []):
                if pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    #we add an id for the calibration preprocess data to work as is usually expects pupil data.
                    pt['id'] = 0
                    self.gaze_list.append(pt)

            if self.counter:
                if self.detected:
                    self.button.status_text = 'Sampling Gaze Data'
                else:
                    self.button.status_text = 'Marker Lost'
            else:
                self.button.status_text = 'Looking for Marker'

            #stop if autostop condition is satisfied:
            if self.auto_stop >= self.auto_stop_max:
                self.auto_stop = 0
                self.stop()

        else:
            pass
Exemplo n.º 11
0
    def update(self, frame, events):
        if self.active:
            recent_pupil_positions = events['pupil_positions']
            gray_img = frame.gray

            if self.clicks_to_close <= 0:
                self.stop()
                return

            #get world image size for error fitting later.
            if self.world_size is None:
                self.world_size = frame.width, frame.height

            #detect the marker
            self.candidate_ellipses = get_candidate_ellipses(
                gray_img,
                area_threshold=self.area_threshold,
                dist_threshold=self.dist_threshold,
                min_ring_count=4,
                visual_debug=self.show_edges)

            if len(self.candidate_ellipses) > 0:
                self.detected = True
                marker_pos = self.candidate_ellipses[0][0]
                self.pos = normalize(marker_pos, (frame.width, frame.height),
                                     flip_y=True)

            else:
                self.detected = False
                self.pos = None  #indicate that no reference is detected

            #only save a valid ref position if within sample window of calibraiton routine
            # on_position = 40 < self.screen_marker_state < self.screen_marker_max-5
            on_position = self.start_sample < self.screen_marker_state < self.stop_sample

            if on_position and self.detected:
                ref = {}
                ref["norm_pos"] = self.pos
                ref["timestamp"] = frame.timestamp
                self.ref_list.append(ref)

            #always save pupil positions
            for p_pt in recent_pupil_positions:
                if p_pt['confidence'] > self.g_pool.pupil_confidence_threshold:
                    self.pupil_list.append(p_pt)

            # Animate the screen marker
            if self.screen_marker_state < self.screen_marker_max:
                if self.detected or not on_position:
                    self.screen_marker_state += 1
            else:
                self.screen_marker_state = 0
                self.active_site += 1
                logger.debug("Moving screen marker to site no %s" %
                             self.active_site)
                if self.active_site == 10:
                    self.stop()
                    return

            # interpolation_weight = np.tanh(((s-1/6.*m)*10.)/(5/6.*m))*(-.5)+.5
            self.pattern_alpha = interp_fn(self.screen_marker_state, 0., 1.,
                                           float(self.screen_marker_max),
                                           float(self.start_sample),
                                           float(self.stop_sample))

            #use np.arrays for per element wise math
            self.display_pos = np.array(self.sites[self.active_site])
            self.on_position = on_position
            self.button.status_text = '%s / %s' % (self.active_site, 9)