diff --git a/pupil_src/shared_modules/offline_marker_detector.py b/pupil_src/shared_modules/offline_marker_detector.py index f77915ce5f..4f759f5c63 100644 --- a/pupil_src/shared_modules/offline_marker_detector.py +++ b/pupil_src/shared_modules/offline_marker_detector.py @@ -23,7 +23,7 @@ from multiprocessing.sharedctypes import Value from itertools import chain -from gl_utils import draw_gl_polyline,adjust_gl_view,draw_gl_polyline_norm,clear_gl_screen,draw_gl_point,draw_gl_points,draw_gl_point_norm,draw_gl_points_norm,basic_gl_setup,cvmat_to_glmat, draw_named_texture +from gl_utils import * from OpenGL.GL import * from OpenGL.GLU import gluOrtho2D from methods import normalize,denormalize @@ -181,9 +181,40 @@ def update_bar_markers(self): def recalculate(self): + + in_mark = self.g_pool.trim_marks.in_mark + out_mark = self.g_pool.trim_marks.out_mark + section = slice(in_mark,out_mark) + + # calc heatmaps for s in self.surfaces: if s.defined: - s.generate_heatmap() + s.generate_heatmap(section) + + # calc metrics: + gaze_in_section = list(chain(*self.g_pool.positions_by_frame[section])) + results = [] + for s in self.surfaces: + gaze_on_srf = s.gaze_on_srf_in_section(section) + results.append(len(gaze_on_srf)) + self.metrics_gazecount = len(gaze_on_srf) + + max_res = max(results) + results = np.array(results,dtype=np.float32) + if not max_res: + logger.warning("No gaze on any surface for this section!") + else: + results *= 255./max_res + results = np.uint8(results) + results_c_maps = cv2.applyColorMap(results, cv2.COLORMAP_JET) + + for s,c_map in zip(self.surfaces,results_c_maps): + heatmap = np.ones((1,1,4),dtype=np.uint8)*125 + heatmap[:,:,:3] = c_map + s.metrics_texture = create_named_texture(heatmap) + + + def update(self,frame,recent_pupil_positions,events): self.img = frame.img @@ -269,9 +300,10 @@ def gl_display(self): if self.mode.value in (0,1): for m in self.markers: - hat = np.array([[[0,0],[0,1],[.5,1.3],[1,1],[1,0],[0,0]]],dtype=np.float32) + hat = np.array([[[0,0],[0,1],[1,1],[1,0],[0,0]]],dtype=np.float32) hat = cv2.perspectiveTransform(hat,m_marker_to_screen(m)) - draw_gl_polyline(hat.reshape((6,2)),(0.1,1.,1.,.5)) + draw_gl_polyline(hat.reshape((5,2)),(0.1,1.,1.,.3),type='Polygon') + draw_gl_polyline(hat.reshape((5,2)),(0.1,1.,1.,.6)) for s in self.surfaces: s.gl_draw_frame() @@ -283,12 +315,10 @@ def gl_display(self): for s in self.surfaces: s.gl_display_heatmap() if self.mode.value == 3: - pass #draw a backdrop to represent the gaze that is not on any surface for s in self.surfaces: - pass #draw a quad on surface with false color of value. - + s.gl_display_metrics() def gl_display_cache_bars(self): """ diff --git a/pupil_src/shared_modules/offline_reference_surface.py b/pupil_src/shared_modules/offline_reference_surface.py index 3f8c361b20..c1acf590c9 100644 --- a/pupil_src/shared_modules/offline_reference_surface.py +++ b/pupil_src/shared_modules/offline_reference_surface.py @@ -10,7 +10,7 @@ import numpy as np import cv2 -from gl_utils import draw_gl_polyline,adjust_gl_view,draw_gl_polyline_norm,clear_gl_screen,draw_gl_point,draw_gl_points,draw_gl_point_norm,draw_gl_points_norm,basic_gl_setup,cvmat_to_glmat, draw_named_texture,create_named_texture +from gl_utils import * from glfw import * from OpenGL.GL import * from OpenGL.GLU import gluOrtho2D @@ -39,6 +39,9 @@ def __init__(self,g_pool,name="unnamed",saved_definition=None, gaze_positions_by self.heatmap_detail = .2 self.heatmap = None self.heatmap_texture = None + self.metrics_gazecount = None + self.metrics_texture = None + #cache fn for offline marker def locate_from_cache(self,frame_idx): if self.cache == None: @@ -165,6 +168,30 @@ def gl_display_heatmap(self): glPopMatrix() + def gl_display_metrics(self): + if self.metrics_texture and self.detected: + + + # cv uses 3x3 gl uses 4x4 tranformation matricies + m = cvmat_to_glmat(self.m_to_screen) + + glMatrixMode(GL_PROJECTION) + glPushMatrix() + glLoadIdentity() + gluOrtho2D(0, 1, 0, 1) # gl coord convention + + glMatrixMode(GL_MODELVIEW) + glPushMatrix() + #apply m to our quad - this will stretch the quad such that the ref suface will span the window extends + glLoadMatrixf(m) + + draw_named_texture(self.metrics_texture) + + glMatrixMode(GL_PROJECTION) + glPopMatrix() + glMatrixMode(GL_MODELVIEW) + glPopMatrix() + #### fns to draw surface in seperate window def gl_display_in_window(self,world_tex_id): @@ -208,10 +235,7 @@ def gl_display_in_window(self,world_tex_id): glfwMakeContextCurrent(active_window) - def generate_heatmap(self): - - in_mark = self.g_pool.trim_marks.in_mark - out_mark = self.g_pool.trim_marks.out_mark + def generate_heatmap(self,section): x,y = self.scale_factor x = max(1,int(x)) @@ -221,11 +245,10 @@ def generate_heatmap(self): std_dev = filter_size /6. self.heatmap = np.ones((y,x,4),dtype=np.uint8) all_gaze = [] - for idx,c_e in enumerate(self.cache): - if in_mark <= idx <= out_mark: - if c_e: - for gp in c_e['gaze_on_srf']: - all_gaze.append(gp['norm_gaze_on_srf']) + for c_e in self.cache[section]: + if c_e: + for gp in c_e['gaze_on_srf']: + all_gaze.append(gp['norm_gaze_on_srf']) if not all_gaze: logger.warning("No gaze data on surface for heatmap found.")