def recent_events(self, events): frame = events.get('frame') if not frame: return if self.fill: thickness = -1 else: thickness = self.thickness for pt in events.get('gaze_positions', []): self.pupil_display_list.append( (pt['norm_pos'], pt['confidence'] * 0.8)) self.pupil_display_list[:-3] = [] # pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[]) if pt['confidence']>=self.min_confidence] for pt, a in self.pupil_display_list: #print('vis_circle', pt, a) transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness) draw_points_norm([pt], size=self.radius, color=RGBA(self.r, self.g, self.b, self.a))
def recent_events(self, events): if self.bg_task: recent = [d for d in self.bg_task.fetch()] if recent: progress, data = zip(*recent) self.fixations.extend(chain(*data)) self.status = progress[-1] if self.fixations: current = self.fixations[-1]['timestamp'] progress = (current - self.g_pool.timestamps[0]) /\ (self.g_pool.timestamps[1] - self.g_pool.timestamps[0]) self.menu_icon.indicator_stop = progress if self.bg_task.completed: self.correlate_and_publish() self.bg_task = None self.menu_icon.indicator_stop = 0. frame = events.get('frame') if not frame: return self.last_frame_ts = frame.timestamp events['fixations'] = self.g_pool.fixations_by_frame[frame.index] if self.show_fixations: for f in self.g_pool.fixations_by_frame[frame.index]: x = int(f['norm_pos'][0] * frame.width) y = int((1. - f['norm_pos'][1]) * frame.height) transparent_circle(frame.img, (x, y), radius=25., color=(0., 1., 1., 1.), thickness=-1) cv2.putText(frame.img, '{}'.format(f['id']), (x + 30, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100)) if self.prev_index != frame.index: info = '' for f in self.g_pool.fixations_by_frame[frame.index]: info += 'Current fixation, {} of {}\n'.format(f['id'], len(self.g_pool.fixations)) info += ' Confidence: {:.2f}\n'.format(f['confidence']) info += ' Duration: {:.2f} milliseconds\n'.format(f['duration']) info += ' Dispersion: {:.3f} degrees\n'.format(f['dispersion']) info += ' Frame range: {}-{}\n'.format(f['start_frame_index'] + 1, f['end_frame_index'] + 1) info += ' 2d gaze pos: x={:.3f}, y={:.3f}\n'.format(*f['norm_pos']) if 'gaze_point_3d' in f: info += ' 3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n'.format(*f['gaze_point_3d']) else: info += ' 3d gaze pos: N/A\n' if f['id'] > 1: prev_f = self.g_pool.fixations[f['id'] - 2] time_lapsed = f['timestamp'] - prev_f['timestamp'] + prev_f['duration'] / 1000 info += ' Time since prev. fixation: {:.2f} seconds\n'.format(time_lapsed) else: info += ' Time since prev. fixation: N/A\n' if f['id'] < len(self.g_pool.fixations): next_f = self.g_pool.fixations[f['id']] time_lapsed = next_f['timestamp'] - f['timestamp'] + f['duration'] / 1000 info += ' Time to next fixation: {:.2f} seconds\n'.format(time_lapsed) else: info += ' Time to next fixation: N/A\n' self.current_fixation_details.text = info self.prev_index = frame.index
def update(self, frame, events): if self.fill: thickness = -1 else: thickness = self.thickness fixation_pts = [ denormalize(pt['norm_pos'], frame.img.shape[:-1][::-1], flip_y=True) for pt in events.get('fixations', []) ] not_fixation_pts = [ denormalize(pt['norm_pos'], frame.img.shape[:-1][::-1], flip_y=True) for pt in events.get('gaze_positions', []) ] if fixation_pts: for pt in fixation_pts: transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness) else: for pt in not_fixation_pts: transparent_circle(frame.img, pt, radius=7.0, color=(0.2, 0.0, 0.7, 0.5), thickness=thickness)
def update(self,frame,events): events['fixations'] = self.g_pool.fixations_by_frame[frame.index] if self.show_fixations: for f in self.g_pool.fixations_by_frame[frame.index]: x = int(f['norm_pos'][0]*self.img_size[0]) y = int((1-f['norm_pos'][1])*self.img_size[1]) transparent_circle(frame.img, (x,y), radius=f['pix_dispersion'], color=(.5, .2, .6, .7), thickness=-1) cv2.putText(frame.img,'%i'%f['id'],(x+20,y), cv2.FONT_HERSHEY_DUPLEX,0.8,(255,150,100))
def draw_circle(self, segment: model.Classified_Segment): segment_point = segment.mean_2d_point_within_world(self.canvas_size) segment_color = color_from_segment(segment).to_bgra().channels pm.transparent_circle( self._image, segment_point, radius=25.0, color=segment_color, thickness=3 ) self.draw_id(segment=segment, ref_point=segment_point)
def update(self,frame,events): if self.fill: thickness = -1 else: thickness = self.thickness pts = [denormalize(pt['norm_gaze'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events['pupil_positions'] if pt['norm_gaze'] is not None] for pt in pts: transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
def update(self,frame,events): if self.fill: thickness = -1 else: thickness = self.thickness pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[])] for pt in pts: transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
def update(self,frame,events): if self.fill: thickness = -1 else: thickness = self.thickness pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[]) if pt['confidence']>=self.g_pool.min_data_confidence] for pt in pts: transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
def update(self, frame, events): events["fixations"] = self.g_pool.fixations_by_frame[frame.index] if self.show_fixations: for f in self.g_pool.fixations_by_frame[frame.index]: x = int(f["norm_pos"][0] * self.img_size[0]) y = int((1 - f["norm_pos"][1]) * self.img_size[1]) transparent_circle( frame.img, (x, y), radius=f["pix_dispersion"], color=(0.5, 0.2, 0.6, 0.7), thickness=-1 ) cv2.putText(frame.img, "%i" % f["id"], (x + 20, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))
def update(self,frame,recent_pupil_positions,events): color = map(lambda x:int(x*255),self.color) color = color[:3][::-1]+color[-1:] if self.fill.value: thickness= -1 else: thickness = self.thickness.value radius = self.radius.value pts = [denormalize(pt['norm_gaze'],frame.img.shape[:-1][::-1],flip_y=True) for pt in recent_pupil_positions if pt['norm_gaze'] is not None] for pt in pts: transparent_circle(frame.img, pt, radius=radius, color=color, thickness=thickness)
def update(self, frame, events): self.last_frame_ts = frame.timestamp from player_methods import transparent_circle events['fixations'] = self.g_pool.fixations_by_frame[frame.index] if self.show_fixations: for f in self.g_pool.fixations_by_frame[frame.index]: x = int(f['norm_pos'][0] * self.img_size[0]) y = int((1 - f['norm_pos'][1]) * self.img_size[1]) transparent_circle(frame.img, (x, y), radius=f['pix_dispersion'] / 2, color=(.5, .2, .6, .7), thickness=-1) cv2.putText(frame.img, '{:d}'.format(f['id']), (x + 20, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))
def update(self,frame,events): self.last_frame_ts = frame.timestamp from player_methods import transparent_circle events['fixations'] = self.g_pool.fixations_by_frame[frame.index] if self.show_fixations: for f in self.g_pool.fixations_by_frame[frame.index]: eye_id = f['eye_id'] x = int(f['norm_pos'][0]*self.img_size[0]) y = int((1-f['norm_pos'][1])*self.img_size[1]) transparent_circle(frame.img, (x,y), radius=f['pix_dispersion']/2, color=(.5, .2, .6, .7), thickness=-1) cv2.putText( frame.img, '%i - eye %i'%(f['id'],eye_id), (x+20,y-5+30*eye_id), cv2.FONT_HERSHEY_DUPLEX, 0.8,(255,150,100))
def update(self,frame,events): if self.fill: thickness = -1 else: thickness = self.thickness fixation_pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('fixations',[])] not_fixation_pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[])] if fixation_pts: for pt in fixation_pts: transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness) else: for pt in not_fixation_pts: transparent_circle(frame.img, pt, radius=7.0, color=(0.2, 0.0, 0.7, 0.5), thickness=thickness)
def recent_events(self, events): frame = events.get('frame') if not frame: return self.last_frame_ts = frame.timestamp from player_methods import transparent_circle events['fixations'] = self.g_pool.fixations_by_frame[frame.index] if self.show_fixations: for f in self.g_pool.fixations_by_frame[frame.index]: eye_id = f['eye_id'] x = int(f['norm_pos'][0] * self.img_size[0]) y = int((1 - f['norm_pos'][1]) * self.img_size[1]) transparent_circle(frame.img, (x, y), radius=f['pix_dispersion'] / 2, color=(.5, .2, .6, .7), thickness=-1) cv2.putText(frame.img, '{:d} - eye {:d}'.format(f['id'], eye_id), (x + 20, y - 5 + 30 * eye_id), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))
def recent_events(self, events): frame = events.get('frame') if not frame: return if self.fill: thickness = -1 else: thickness = self.thickness pts = [ denormalize(pt['norm_pos'], frame.img.shape[:-1][::-1], flip_y=True) for pt in events.get('gaze_positions', []) if pt['confidence'] >= self.g_pool.min_data_confidence ] for pt in pts: transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
def _draw_scan_path_debug(self, frame, events): from methods import denormalize from player_methods import transparent_circle gaze_data = self.scan_path_controller.scan_path_gaze_for_frame(frame) if gaze_data is None: return points_to_draw_count = len(gaze_data) image_size = frame.img.shape[:-1][::-1] for idx, datum in enumerate(gaze_data): point = (datum["norm_x"], datum["norm_y"]) point = denormalize(point, image_size, flip_y=True) gray = float(idx) / points_to_draw_count transparent_circle(frame.img, point, radius=20, color=(gray, gray, gray, 0.9), thickness=2)
def recent_events(self, events): frame = events.get("frame") if not frame: return if self.fill: thickness = -1 else: thickness = self.thickness fixation_pts = [ denormalize(pt["norm_pos"], frame.img.shape[:-1][::-1], flip_y=True) for pt in events.get("fixations", []) ] not_fixation_pts = [ denormalize(pt["norm_pos"], frame.img.shape[:-1][::-1], flip_y=True) for pt in events.get("gaze", []) ] if fixation_pts: for pt in fixation_pts: transparent_circle( frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness, ) else: for pt in not_fixation_pts: transparent_circle( frame.img, pt, radius=7.0, color=(0.2, 0.0, 0.7, 0.5), thickness=thickness, )
def recent_events(self, events): frame = events.get("frame") if not frame: return if self.fill: thickness = -1 else: thickness = self.thickness frame_width_height = frame.img.shape[:-1][::-1] pts = [ denormalize(pt["norm_pos"], frame_width_height, flip_y=True) for pt in events.get("gaze", []) if pt["confidence"] >= self.g_pool.min_data_confidence ] for pt in pts: transparent_circle( frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness, )
def recent_events(self, events): if self.bg_task: for progress, fixation_result in self.bg_task.fetch(): self.status = progress if fixation_result: serialized, start_ts, stop_ts = fixation_result self.fixation_data.append( fm.Serialized_Dict(msgpack_bytes=serialized) ) self.fixation_start_ts.append(start_ts) self.fixation_stop_ts.append(stop_ts) if self.fixation_data: current_ts = self.fixation_stop_ts[-1] progress = (current_ts - self.g_pool.timestamps[0]) / ( self.g_pool.timestamps[-1] - self.g_pool.timestamps[0] ) self.menu_icon.indicator_stop = progress if self.bg_task.completed: self.status = "{} fixations detected".format(len(self.fixation_data)) self.correlate_and_publish() self.bg_task = None self.menu_icon.indicator_stop = 0.0 frame = events.get("frame") if not frame: return self.last_frame_idx = frame.index frame_window = pm.enclosing_window(self.g_pool.timestamps, frame.index) fixations = self.g_pool.fixations.by_ts_window(frame_window) events["fixations"] = fixations if self.show_fixations: for f in fixations: x = int(f["norm_pos"][0] * frame.width) y = int((1.0 - f["norm_pos"][1]) * frame.height) pm.transparent_circle( frame.img, (x, y), radius=25.0, color=(0.0, 1.0, 1.0, 1.0), thickness=3, ) cv2.putText( frame.img, "{}".format(f["id"]), (x + 30, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100), ) if self.current_fixation_details and self.prev_index != frame.index: info = "" for f in fixations: info += "Current fixation, {} of {}\n".format( f["id"], len(self.g_pool.fixations) ) info += " Confidence: {:.2f}\n".format(f["confidence"]) info += " Duration: {:.2f} milliseconds\n".format(f["duration"]) info += " Dispersion: {:.3f} degrees\n".format(f["dispersion"]) info += " Frame range: {}-{}\n".format( f["start_frame_index"] + 1, f["end_frame_index"] + 1 ) info += " 2d gaze pos: x={:.3f}, y={:.3f}\n".format(*f["norm_pos"]) if "gaze_point_3d" in f: info += " 3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n".format( *f["gaze_point_3d"] ) else: info += " 3d gaze pos: N/A\n" if f["id"] > 1: prev_f = self.g_pool.fixations[f["id"] - 2] time_lapsed = ( f["timestamp"] - prev_f["timestamp"] + prev_f["duration"] / 1000 ) info += " Time since prev. fixation: {:.2f} seconds\n".format( time_lapsed ) else: info += " Time since prev. fixation: N/A\n" if f["id"] < len(self.g_pool.fixations): next_f = self.g_pool.fixations[f["id"]] time_lapsed = ( next_f["timestamp"] - f["timestamp"] + f["duration"] / 1000 ) info += " Time to next fixation: {:.2f} seconds\n".format( time_lapsed ) else: info += " Time to next fixation: N/A\n" self.current_fixation_details.text = info self.prev_index = frame.index
def recent_events(self, events): if self.bg_task: for progress, fixation_result in self.bg_task.fetch(): self.status = progress if fixation_result: serialized, start_ts, stop_ts = fixation_result self.fixation_data.append( fm.Serialized_Dict(msgpack_bytes=serialized)) self.fixation_start_ts.append(start_ts) self.fixation_stop_ts.append(stop_ts) if self.fixation_data: current_ts = self.fixation_stop_ts[-1] progress = (current_ts - self.g_pool.timestamps[0]) / ( self.g_pool.timestamps[-1] - self.g_pool.timestamps[0]) self.menu_icon.indicator_stop = progress if self.bg_task.completed: self.status = "{} fixations detected".format( len(self.fixation_data)) self.correlate_and_publish() self.bg_task = None self.menu_icon.indicator_stop = 0.0 frame = events.get("frame") if not frame: return self.last_frame_idx = frame.index frame_window = pm.enclosing_window(self.g_pool.timestamps, frame.index) fixations = self.g_pool.fixations.by_ts_window(frame_window) events["fixations"] = fixations if self.show_fixations: for f in fixations: x = int(f["norm_pos"][0] * frame.width) y = int((1.0 - f["norm_pos"][1]) * frame.height) pm.transparent_circle( frame.img, (x, y), radius=25.0, color=(0.0, 1.0, 1.0, 1.0), thickness=3, ) cv2.putText( frame.img, "{}".format(f["id"]), (x + 30, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100), ) if self.current_fixation_details and self.prev_index != frame.index: info = "" for f in fixations: info += "Current fixation, {} of {}\n".format( f["id"], len(self.g_pool.fixations)) info += " Confidence: {:.2f}\n".format(f["confidence"]) info += " Duration: {:.2f} milliseconds\n".format( f["duration"]) info += " Dispersion: {:.3f} degrees\n".format( f["dispersion"]) info += " Frame range: {}-{}\n".format( f["start_frame_index"] + 1, f["end_frame_index"] + 1) info += " 2d gaze pos: x={:.3f}, y={:.3f}\n".format( *f["norm_pos"]) if "gaze_point_3d" in f: info += " 3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n".format( *f["gaze_point_3d"]) else: info += " 3d gaze pos: N/A\n" if f["id"] > 1: prev_f = self.g_pool.fixations[f["id"] - 2] time_lapsed = (f["timestamp"] - prev_f["timestamp"] + prev_f["duration"] / 1000) info += " Time since prev. fixation: {:.2f} seconds\n".format( time_lapsed) else: info += " Time since prev. fixation: N/A\n" if f["id"] < len(self.g_pool.fixations): next_f = self.g_pool.fixations[f["id"]] time_lapsed = (next_f["timestamp"] - f["timestamp"] + f["duration"] / 1000) info += " Time to next fixation: {:.2f} seconds\n".format( time_lapsed) else: info += " Time to next fixation: N/A\n" self.current_fixation_details.text = info self.prev_index = frame.index
def recent_events(self, events): frame = events.get('frame') events['fixations'] = self.g_pool.fixations_by_frame[frame.index] img = frame.img img_shape = img.shape[:-1][::-1] # width,height succeeding_frame = frame.index-self.prev_frame_idx == 1 same_frame = frame.index == self.prev_frame_idx gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #vars for calcOpticalFlowPyrLK lk_params = dict( winSize = (90, 90), maxLevel = 3, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 20, 0.03)) updated_past_gaze = [] updated_past_fixations = [] if self.past_fixation_positions and succeeding_frame: past_screen_fixation = np.array( [denormalize(ng['norm_pos'], img_shape, flip_y=True) for ng in self.past_fixation_positions], dtype=np.float32) new_pts, status, err = cv2.calcOpticalFlowPyrLK(self.prev_gray, gray_img, past_screen_fixation, None, minEigThreshold=0.005, **lk_params) for fixation, new_gaze_pt, s, e in zip(self.past_fixation_positions, new_pts, status, err): if s: # print "norm,updated",gaze['norm_gaze'], normalize(new_gaze_pt,img_shape[:-1],flip_y=True) fixation['norm_pos'] = normalize(new_gaze_pt, img_shape, flip_y=True) updated_past_fixations.append(fixation) # logger.debug("updated gaze") else: # logger.debug("dropping gaze") # Since we will replace self.past_gaze_positions later, # not appedning tu updated_past_gaze is like deliting this data point. pass else: # we must be seeking, do not try to do optical flow, or pausing: see below. pass if same_frame: # re-use last result events['fixations'][:] = self.past_fixation_positions[:] else: if events.get('fixations', []): now = events.get('fixations', [])[0]['timestamp'] cutoff = now - self.timeframe updated_past_fixations = [g for g in updated_past_fixations if g['timestamp'] > cutoff] # inject the scan path gaze points into recent_gaze_positions events.get('fixations', [])[:] = updated_past_fixations + events.get('fixations',[]) events.get('fixations', []).sort(key=lambda x: x['timestamp']) fixation_pts = [] for pt in events.get('fixations', []): denorm_pos = denormalize(pt['norm_pos'], frame.img.shape[:-1][::-1], flip_y=True) fixation_pts.append(denorm_pos) transparent_circle(frame.img, denorm_pos, 20, color=(0.2, 0.0, 0.7, 0.5), thickness=2) try: aoi_label = pt['aoi_label'] #self.aoi_encoder.hex_hash(pt['aoi']) #self.aoi_encoder.encode_aoi(pt['aoi']) cv2.putText(img, aoi_label, tuple(map(int, denorm_pos)), cv2.FONT_HERSHEY_SIMPLEX, .7, (185, 224, 236), 1, lineType=cv2.LINE_AA) except: #logger.info(str(pt['timestamp'])) pass #pt['aoi'] = None # aoi = self.aoi_encoder.encode_aoi(pt['aoi']) # if aoi is not None: # cv2.putText(img, aoi, tuple(map(int, denorm_pos)), cv2.FONT_HERSHEY_SIMPLEX, .7, (185, 224, 236), 1, lineType=cv2.LINE_AA) if fixation_pts: pts = np.array([fixation_pts], dtype=np.int32) cv2.polylines(frame.img, pts, isClosed=False, color= (0.25*255,0.7*255,0,0.2*255), thickness=2, lineType=cv2.LINE_AA) else: pass #Visualize the gaze-points #update info for next frame. self.prev_gray = gray_img self.prev_frame_idx = frame.index self.past_gaze_positions = events['gaze_positions'] self.past_fixation_positions = events.get('fixations', [])
except KeyError, e: #print e color = map(lambda x: int(x * 255),(0, 0, 0, self.a)) transparent_circle( img, pt_codes[x][_POINT], radius = int(radius/2), color = color, thickness = thickness ) # do not find any contour else: for pt in pts: transparent_circle( frame.img, pt, radius = radius, color = map(lambda x: int(x * 255),self.colors[-1]), thickness = thickness ) cv2.putText(img, '?', (int(pt[0] -10),int(pt[1]) +10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1, lineType = cv2.CV_AA ) def init_gui(self): # initialize the menu self.menu = ui.Scrolling_Menu('Gaze Circles on Contours') # load the configuration of last session self.menu.configuration = self.menu_conf # add menu to the window self.g_pool.gui.append(self.menu) self.menu.append(ui.Info_Text('Circle Properties')) self.menu.append(ui.Slider('radius',self,min=1,step=1,max=100,label='Radius')) self.menu.append(ui.Slider('thickness',self,min=1,step=1,max=15,label='Stroke width')) self.menu.append(ui.Switch('fill',self,label='Fill'))
def update(self,frame,events): # get image from frame img = frame.img # set color1 color1 = map(lambda x: int(x * 255),(self.b, self.g, self.r, self.a)) # cv2.THRESH_BINARY # cv2.THRESH_BINARY_INV # cv2.THRESH_TRUNC # find raw ellipses from cv2.findContours # the less the difference between ellipse area and source contour area are, # the better a fit between ellipse and source contour will be # delta_area_threshold gives the maximum allowed difference ellipses = [] merge = [] contained_contours = [] ellipses, merge, contained_contours = ellipses_from_findContours(img,cv2_thresh_mode=cv2.THRESH_BINARY,delta_area_threshold=self.delta_area_threshold,threshold=self.threshold) alfa = self.ellipse_size if self.show_edges: #frame.img = cv2.merge(merge) #cv2.drawContours(frame.img, contained_contours,-1, (0,0,255)) if ellipses: for ellipse in ellipses: center = ( int(round( ellipse[0][0] )), int( round( ellipse[0][1] ))) axes = ( int( round( ellipse[1][0]/alfa )), int( round( ellipse[1][1]/alfa ))) angle = int( round(ellipse[2] )) cv2.ellipse(img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift= 0) # we need denormalized points for point polygon tests pts = [denormalize(pt['norm_gaze'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events['pupil_positions'] if pt['norm_gaze'] is not None] if ellipses: # get area of all ellipses ellipses_temp = [e[1][0]/2. * e[1][1]/2. * np.pi for e in ellipses] ellipses_temp.sort() # take the highest area as reference area_threshold = ellipses_temp[-1] # filtering by proportional area ellipses_temp = [] for e in ellipses: a,b = e[1][0] / 2., e[1][1] / 2. ellipse_area = np.pi * a * b if (ellipse_area/area_threshold) < .10: pass else: ellipses_temp.append(e) # cluster_hierarchy is ordenated by appearence order, from top left screen # it is a list of clustered ellipses cluster_hierarchy = [] cluster_hierarchy = get_cluster_hierarchy( ellipses=ellipses_temp, dist_threshold=self.dist_threshold) # total_stm is expected to be the number of stimuli on screen # total_stm = len(cluster_hierarchy) # we need contours for point polygon tests, not ellipses stm_contours = [] # cluster_set is the ellipse set associated with each stimulus on screen temp = list(cluster_hierarchy) for cluster_set in temp: #print len(cluster_set) if len(cluster_set) > 2: cluster_hierarchy.append(cluster_hierarchy.pop(cluster_hierarchy.index(cluster_set))) for cluster_set in cluster_hierarchy: if len(cluster_set) > 0: if True: for ellipse in cluster_set: center = ( int(round( ellipse[0][0] )), int( round( ellipse[0][1] ))) axes = ( int( round( ellipse[1][0]/alfa )), int( round( ellipse[1][1]/alfa ))) angle = int( round(ellipse[2] )) cv2.ellipse(img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift= 0) # use only the biggest (last) ellipse for reference stm_contours.append(ellipse_to_contour(cluster_set[-1], alfa)) #print stm_contours # pt_codes is a list tuples: # tuple((denormalized point as a float x, y coordenate), 'string code given by the PointPolygonTextEx function') # ex.: tuple([x, y], '+1-2') contour_count = 0 pt_codes = [] for pt in pts: contour_count = 0 counter_code = '' for contour in stm_contours: contour_count, counter_code = PolygonTestRC(contour, pt, contour_count, counter_code) # a single code for a single point pt_codes.append((pt, counter_code)) #print pt_codes else: #print 'else' contour_count = 0 # transparent circle parameters radius = self.radius if self.fill: thickness= -1 else: thickness = self.thickness # each code specifies the color of each point # in accordance with the self.ColorDictionary if contour_count > 0: for x in xrange(len(pt_codes)): try: #print pt_codes[x] color = self.ColorDictionary[pt_codes[x][_CODE]] except KeyError, e: #print e color = map(lambda x: int(x * 255),(0, 0, 0, self.a)) transparent_circle( img, pt_codes[x][_POINT], radius = int(radius/2), color = color, thickness = thickness )
def recent_events(self, events): if self.bg_task: for progress, fixation_result in self.bg_task.fetch(): self.status = progress if fixation_result: serialized, start_ts, stop_ts = fixation_result self.fixation_data.append(fm.Serialized_Dict(msgpack_bytes=serialized)) self.fixation_start_ts.append(start_ts) self.fixation_stop_ts.append(stop_ts) if self.fixation_data: current_ts = self.fixation_stop_ts[-1] progress = ((current_ts - self.g_pool.timestamps[0]) / (self.g_pool.timestamps[-1] - self.g_pool.timestamps[0])) self.menu_icon.indicator_stop = progress if self.bg_task.completed: self.status = "{} fixations detected".format(len(self.fixation_data)) self.correlate_and_publish() self.bg_task = None self.menu_icon.indicator_stop = 0. frame = events.get('frame') if not frame: return self.last_frame_idx = frame.index frame_window = pm.enclosing_window(self.g_pool.timestamps, frame.index) fixations = self.g_pool.fixations.by_ts_window(frame_window) events['fixations'] = fixations if self.show_fixations: for f in fixations: x = int(f['norm_pos'][0] * frame.width) y = int((1. - f['norm_pos'][1]) * frame.height) pm.transparent_circle(frame.img, (x, y), radius=25., color=(0., 1., 1., 1.), thickness=3) cv2.putText(frame.img, '{}'.format(f['id']), (x + 30, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100)) if self.current_fixation_details and self.prev_index != frame.index: info = '' for f in fixations: info += 'Current fixation, {} of {}\n'.format(f['id'], len(self.g_pool.fixations)) info += ' Confidence: {:.2f}\n'.format(f['confidence']) info += ' Duration: {:.2f} milliseconds\n'.format(f['duration']) info += ' Dispersion: {:.3f} degrees\n'.format(f['dispersion']) info += ' Frame range: {}-{}\n'.format(f['start_frame_index'] + 1, f['end_frame_index'] + 1) info += ' 2d gaze pos: x={:.3f}, y={:.3f}\n'.format(*f['norm_pos']) if 'gaze_point_3d' in f: info += ' 3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n'.format(*f['gaze_point_3d']) else: info += ' 3d gaze pos: N/A\n' if f['id'] > 1: prev_f = self.g_pool.fixations[f['id'] - 2] time_lapsed = f['timestamp'] - prev_f['timestamp'] + prev_f['duration'] / 1000 info += ' Time since prev. fixation: {:.2f} seconds\n'.format(time_lapsed) else: info += ' Time since prev. fixation: N/A\n' if f['id'] < len(self.g_pool.fixations): next_f = self.g_pool.fixations[f['id']] time_lapsed = next_f['timestamp'] - f['timestamp'] + f['duration'] / 1000 info += ' Time to next fixation: {:.2f} seconds\n'.format(time_lapsed) else: info += ' Time to next fixation: N/A\n' self.current_fixation_details.text = info self.prev_index = frame.index
def recent_events(self, events): frame = events['frame'] if frame is not None: # get image from frame img = frame.img # set color1 color1 = map(lambda x: int(x * 255), (self.b, self.g, self.r, self.a)) # cv2.THRESH_BINARY # cv2.THRESH_BINARY_INV # cv2.THRESH_TRUNC # find raw ellipses from cv2.findContours # the less the difference between ellipse area and source contour area are, # the better a fit between ellipse and source contour will be # delta_area_threshold gives the maximum allowed difference ellipses = [] merge = [] ellipses, merge, ellipses_contours = ellipses_from_findContours( img, cv2_thresh_mode=cv2.THRESH_BINARY, delta_area_threshold=self.delta_area_threshold, threshold=self.threshold) # for contour in ellipses_contours: # print(contour.shape) # break alfa = self.ellipse_size # if self.show_edges: # #frame.img = cv2.merge(merge) # #cv2.drawContours(frame.img, contained_contours,-1, (0,0,255)) # if ellipses: # for ellipse in ellipses: # center = ( int(round( ellipse[0][0] )), int( round( ellipse[0][1] ))) # axes = ( int( round( ellipse[1][0]/alfa )), int( round( ellipse[1][1]/alfa ))) # angle = int( round(ellipse[2] )) # cv2.ellipse(img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift= 0) # we need denormalized points for point polygon tests pts = [ denormalize(pt['norm_pos'], frame.img.shape[:-1][::-1], flip_y=True) for pt in events.get('gaze_positions', []) ] contour_count = 0 if ellipses: # get area of all ellipses ellipses_temp = [ e[1][0] / 2. * e[1][1] / 2. * np.pi for e in ellipses ] ellipses_temp.sort() # take the highest area as reference area_threshold = ellipses_temp[-1] # filtering by proportional area ellipses_temp = [] for e in ellipses: a, b = e[1][0] / 2., e[1][1] / 2. ellipse_area = np.pi * a * b if (ellipse_area / area_threshold) < .10: pass else: ellipses_temp.append(e) # cluster_hierarchy is ordenated by appearence order, from top left screen # it is a list of clustered ellipses cluster_hierarchy = [] cluster_hierarchy = get_cluster_hierarchy( ellipses=ellipses_temp, dist_threshold=self.dist_threshold) # total_stm is expected to be the number of stimuli on screen # total_stm = len(cluster_hierarchy) # we need contours for point polygon tests, not ellipses stm_contours = [] # cluster_set is the ellipse set associated with each stimulus on screen temp = list(cluster_hierarchy) for cluster_set in temp: #print(len(cluster_set)) if len(cluster_set) > 2: cluster_hierarchy.append( cluster_hierarchy.pop( cluster_hierarchy.index(cluster_set))) for cluster_set in cluster_hierarchy: if len(cluster_set) > 0: # use only the smallest (first) ellipse for reference ellipse = cluster_set[0] stm_contours.append(ellipse_to_contour(ellipse, alfa)) if self.show_edges: # for ellipse in cluster_set: center = (int(round(ellipse[0][0])), int(round(ellipse[0][1]))) axes = (int(round(ellipse[1][0] / alfa)), int(round(ellipse[1][1] / alfa))) angle = int(round(ellipse[2])) cv2.ellipse(frame.img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift=0) #print(stm_contours) # pt_codes is a list tuples: # tuple((denormalized point as a float x, y coordenate), 'string code given by the PointPolygonTextEx function') # ex.: tuple([x, y], '+1-2') # if self.show_edges: # for contour in stm_contours: # populated by ellipse2Poly # print(np.array([[c] for c in contour]).shape) # sys.exit("contour") # (x, y, w, h) = cv2.boundingRect(np.array([[c] for c in contour])) # cv2.rectangle(frame.img, (x, y), (x+w, y+h), (255,0,0), 2) # box = np.int0(cv2.cv.BoxPoints(cv2.minAreaRect(np.array([[c] for c in contour])))) # cv2.drawContours(frame.img,[box],0,color1,1) pt_codes = [] for pt in pts: contour_count = 0 counter_code = '' for contour in stm_contours: contour_count, counter_code = PolygonTestRC( contour, pt, contour_count, counter_code) # a single code for a single point pt_codes.append((pt, counter_code)) #print(pt_codes) # transparent circle parameters radius = self.radius if self.fill: thickness = -1 else: thickness = self.thickness # each code specifies the color of each point # in accordance with the self.ColorDictionary if contour_count > 0: for pt in pt_codes: try: #print(pt) color = self.ColorDictionary[pt[_CODE]] except KeyError: #print(e) color = map(lambda x: int(x * 255), (0, 0, 0, self.a)) transparent_circle(frame.img, pt[_XY], radius=int(radius / 2), color=color, thickness=thickness) # do not find any contour else: for pt in pts: transparent_circle(frame.img, pt, radius=radius, color=map(lambda x: int(x * 255), self.colors[-1]), thickness=thickness) cv2.putText(frame.img, '?', (int(pt[0] - 10), int(pt[1]) + 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 1, lineType=cv2.CV_AA)