def __init__(self, g_pool, atb_pos=(10, 400)): Plugin.__init__(self) self.context = zmq.Context() self.socket = self.context.socket(zmq.PUB) self.address = create_string_buffer("tcp://127.0.0.1:5000", 512) self.set_server(self.address) help_str = "Pupil Message server: Using ZMQ and the *Publish-Subscribe* scheme" self._bar = atb.Bar(name=self.__class__.__name__, label='Server', help=help_str, color=(50, 50, 50), alpha=100, text='light', position=atb_pos, refresh=.3, size=(300, 40)) self._bar.define("valueswidth=170") self._bar.add_var("server address", self.address, getter=lambda: self.address, setter=self.set_server) self._bar.add_button("close", self.close) self.exclude_list = [ 'ellipse', 'pos_in_roi', 'major', 'minor', 'axes', 'angle', 'center' ]
def __init__(self,g_pool,atb_pos=(0,0)): Plugin.__init__(self) self.window_should_open = False self.window_should_close = False self._window = None self.fullscreen = c_bool(0) self.realdata = c_bool(False) self.x = c_float(0) self.y = c_float(0) self.blink_time = c_float(1) self.should_blink = False self.blink_start = None atb_label = "android coordinate plugin" # Creating an ATB Bar. self._bar = atb.Bar(name =self.__class__.__name__, label=atb_label, help="ref detection parameters", color=(50, 50, 50), alpha=100, text='light', position=atb_pos,refresh=.3, size=(300, 100)) self._bar.add_var("real data", self.realdata) self._bar.add_var("X", self.x) self._bar.define("min=0 max=1 step=0.01", "X") self._bar.add_var("Y", self.y) self._bar.define("min=0 max=1 step=0.01", "Y") self._bar.add_var("blink time", self.blink_time, min=0,max=10,step=0.05,help="Simulated blink time") # self._bar.define("min=0 max=10000 step=50", "blink time") self._bar.add_button("simulate blink", self.schedule_blink)
def __init__(self,g_pool,atb_pos=(0,0)): Plugin.__init__(self) self.collect_new = False self.calculated = False self.obj_grid = _gen_pattern_grid((4, 11)) self.img_points = [] self.obj_points = [] self.count = 10 self.img_shape = None self.display_grid = _make_grid() self.window_should_open = False self.window_should_close = False self._window = None self.fullscreen = c_bool(0) self.monitor_idx = c_int(0) self.monitor_handles = glfwGetMonitors() self.monitor_names = [glfwGetMonitorName(m) for m in self.monitor_handles] monitor_enum = atb.enum("Monitor",dict(((key,val) for val,key in enumerate(self.monitor_names)))) #primary_monitor = glfwGetPrimaryMonitor() atb_label = "estimate camera instrinsics" # Creating an ATB Bar is required. Show at least some info about the Ref_Detector self._bar = atb.Bar(name =self.__class__.__name__, label=atb_label, help="ref detection parameters", color=(50, 50, 50), alpha=100, text='light', position=atb_pos,refresh=.3, size=(300, 100)) self._bar.add_var("monitor",self.monitor_idx, vtype=monitor_enum) self._bar.add_var("fullscreen", self.fullscreen) self._bar.add_button(" show pattern ", self.do_open, key='c') self._bar.add_button(" Capture Pattern", self.advance, key="SPACE") self._bar.add_var("patterns to capture", getter=self.get_count)
def __init__(self, g_pool, atb_pos=(10, 400), on_char_fn=None): Plugin.__init__(self) self.g_pool = g_pool self.on_char_fn = on_char_fn self.order = .9 #excecute late in the plugin list. self.context = zmq.Context() self.socket = self.context.socket(zmq.REP) self.address = create_string_buffer('', 512) self.set_server(create_string_buffer("tcp://*:50020", 512)) help_str = "Pupil Remote using REQ RREP schema. " self._bar = atb.Bar(name=self.__class__.__name__, label='Remote', help=help_str, color=(50, 50, 50), alpha=100, text='light', position=atb_pos, refresh=.3, size=(300, 40)) self._bar.define("valueswidth=170") self._bar.add_var("server address", self.address, getter=lambda: self.address, setter=self.set_server) self._bar.add_button("close", self.close) self.exclude_list = [ 'ellipse', 'pos_in_roi', 'major', 'minor', 'axes', 'angle', 'center' ]
def __init__(self,g_pool,atb_pos=(320,220)): super(Marker_Detector, self).__init__() self.g_pool = g_pool self.order = .2 # all markers that are detected in the most recent frame self.markers = [] # all registered surfaces self.surface_definitions = Persistent_Dict(os.path.join(g_pool.user_dir,'surface_definitions') ) self.surfaces = [Reference_Surface(saved_definition=d) for d in self.load('realtime_square_marker_surfaces',[]) if isinstance(d,dict)] # edit surfaces self.surface_edit_mode = c_bool(0) self.edit_surfaces = [] #detector vars self.robust_detection = c_bool(1) self.aperture = c_int(11) self.min_marker_perimeter = 80 #debug vars self.draw_markers = c_bool(0) self.show_surface_idx = c_int(0) self.recent_pupil_positions = [] self.img_shape = None atb_label = "marker detection" self._bar = atb.Bar(name =self.__class__.__name__, label=atb_label, help="marker detection parameters", color=(50, 150, 50), alpha=100, text='light', position=atb_pos,refresh=.3, size=(300, 300)) self.update_bar_markers()
def __init__(self, g_pool, atb_pos=(0, 0)): Plugin.__init__(self) self.active = False self.detected = False self.g_pool = g_pool self.pos = None self.smooth_pos = 0., 0. self.smooth_vel = 0. self.sample_site = (-2, -2) self.counter = 0 self.counter_max = 30 self.candidate_ellipses = [] self.show_edges = c_bool(0) self.aperture = 7 self.dist_threshold = c_int(10) self.area_threshold = c_int(30) self.world_size = None self.stop_marker_found = False self.auto_stop = 0 self.auto_stop_max = 30 atb_label = "calibrate using handheld marker" # Creating an ATB Bar is required. Show at least some info about the Ref_Detector self._bar = atb.Bar(name=self.__class__.__name__, label=atb_label, help="ref detection parameters", color=(50, 50, 50), alpha=100, text='light', position=atb_pos, refresh=.3, size=(300, 100)) self._bar.add_button("start/stop", self.start_stop, key='c') self._bar.add_var("show edges", self.show_edges, group="Advanced")
def create_atb_bar(self, pos): self._bar = atb.Bar(name="Canny_Pupil_Detector", label="Pupil_Detector", help="pupil detection parameters", color=(50, 50, 50), alpha=100, text='light', position=pos, refresh=.3, size=(200, 100)) self._bar.add_var( "use coarse detection", self.coarse_detection, help= "Disbale when you have trouble with detection when using Mascara.") self._bar.add_button( "open debug window", self.toggle_window, help= "Open a debug window that shows geeky visual feedback from the algorithm." ) self._bar.add_var( "pupil_intensity_range", self.intensity_range, help= "Using alorithm view set this as low as possible but so that the pupil is always fully overlayed in blue." ) self._bar.add_var( "pupil_min", self.pupil_min, min=1, help= "Setting good bounds will increase detection robustness. Use alorithm view to see." ) self._bar.add_var( "pupil_max", self.pupil_max, min=1, help= "Setting good bounds will increase detection robustness. Use alorithm view to see." ) self._bar.add_var("Pupil_Aparent_Size", self.target_size, readonly=True) self._bar.add_var( "Contour min length", self.min_contour_size, help= "Setting this low will make the alorithm try to connect even smaller arcs to find the pupil but cost you cpu time!" ) self._bar.add_var("Pupil_Shade", self.bin_thresh, readonly=True) self._bar.add_var( "confidence", self.confidence, readonly=True, help= "The measure of confidence is a number between 0 and 1 of how sure the algorithm is about the detected pupil." )
def __init__(self, g_pool, atb_pos=(0, 0)): Plugin.__init__(self) self.g_pool = g_pool self.active = False self.detected = False self.screen_marker_state = 0 self.screen_marker_max = 70 # maximum bound for state self.active_site = 0 self.sites = [] self.display_pos = None self.on_position = False self.candidate_ellipses = [] self.pos = None self.show_edges = c_bool(0) self.dist_threshold = c_int(5) self.area_threshold = c_int(20) self.world_size = None self._window = None self.window_should_close = False self.window_should_open = False self.fullscreen = c_bool(1) self.monitor_idx = c_int(0) monitor_handles = glfwGetMonitors() self.monitor_names = [glfwGetMonitorName(m) for m in monitor_handles] monitor_enum = atb.enum( "Monitor", dict(((key, val) for val, key in enumerate(self.monitor_names)))) #primary_monitor = glfwGetPrimaryMonitor() self.frame = None self.timebase = 0 atb_label = "calibrate on screen" # Creating an ATB Bar is required. Show at least some info about the Ref_Detector self._bar = atb.Bar(name=self.__class__.__name__, label=atb_label, help="ref detection parameters", color=(50, 50, 50), alpha=100, text='light', position=atb_pos, refresh=.3, size=(300, 90)) self._bar.add_var("monitor", self.monitor_idx, vtype=monitor_enum) self._bar.add_var("fullscreen", self.fullscreen) self._bar.add_button(" start calibrating ", self.start, key='c') self._bar.add_var("show edges", self.show_edges, group="Detector Variables") self._bar.add_var("area threshold", self.area_threshold, group="Detector Variables") self._bar.add_var("eccetricity threshold", self.dist_threshold, group="Detector Variables")
def create_atb_bar(self, pos): self.bar = atb.Bar(name="MSER_Detector", label="MSER PUPIL Detector Controls", help="pupil detection params", color=(50, 50, 50), alpha=100, text='light', position=pos, refresh=.3, size=(200, 200))
def create_atb_bar(self, pos): self._bar = atb.Bar(name="Canny_Pupil_Detector", label="Pupil_Detector", help="pupil detection parameters", color=(50, 50, 50), alpha=100, text='light', position=pos, refresh=.3, size=(200, 100))
def create_atb_bar(self, pos): self.bar = atb.Bar(name="Pupil_Detector", label="Pupil Detector Controls", help="pupil detection params", color=(50, 50, 50), alpha=100, text='light', position=pos, refresh=.3, size=(200, 200)) self.bar.add_var("VAR1", self.var1, step=1., readonly=False)
def init_gui(self): import atb pos = self.gui_settings['pos'] atb_label = "Marker Detector" self._bar = atb.Bar(name =self.__class__.__name__+str(id(self)), label=atb_label, help="circle", color=(50, 150, 50), alpha=50, text='light', position=pos,refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self.update_bar_markers() #set up bar display padding self.on_window_resize(glfwGetCurrentContext(),*glfwGetWindowSize(glfwGetCurrentContext()))
def init_gui(self,pos=None): pos = self.gui_settings['pos'] import atb atb_label = "Gaze Polyline" from time import time self._bar = atb.Bar(name = self.__class__.__name__+str(id(self)), label=atb_label, help="polyline", color=(50, 50, 50), alpha=100, text='light', position=pos,refresh=.1, size=self.gui_settings['size']) self._bar.add_var('color',self.color) self._bar.add_var('thickness',self.thickness,min=1) self._bar.add_button('remove',self.unset_alive)
def create_atb_bar(self,pos): self._bar = atb.Bar(name = "Canny_Pupil_Detector", label="Pupil_Detector", help="pupil detection parameters", color=(50, 50, 50), alpha=100, text='light', position=pos,refresh=.3, size=(200, 100)) self._bar.add_button("open debug window", self.toggle_window) self._bar.add_var("pupil_intensity_range",self.intensity_range) self._bar.add_var("Pupil_Aparent_Size",self.target_size) self._bar.add_var("Pupil_Shade",self.bin_thresh, readonly=True) self._bar.add_var("Pupil_Certainty",self.goodness, readonly=True) self._bar.add_var("Image_Blur",self.blur, step=2,min=1,max=9) self._bar.add_var("Canny_aparture",self.canny_aperture, step=2,min=3,max=7) self._bar.add_var("canny_threshold",self.canny_thresh, step=1,min=0) self._bar.add_var("Canny_ratio",self.canny_ratio, step=1,min=1)
def init_gui(self,pos=None): pos = self.gui_settings['pos'] import atb atb_label = "Gaze Cross" self._bar = atb.Bar(name =self.__class__.__name__+str(id(self)), label=atb_label, help="circle", color=(50, 50, 50), alpha=50, text='light', position=pos,refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self._bar.add_var('color',self.color) self._bar.add_var('inner',self.inner, min=0) self._bar.add_var('outer',self.outer, min=0) self._bar.add_var('thickness',self.thickness,min=1) self._bar.add_button('remove',self.unset_alive)
def init_gui(self): import atb self.atb_enum = atb.enum pos = self.gui_settings['pos'] atb_label = "Marker Auto Trim Marks" self._bar = atb.Bar(name =self.__class__.__name__+str(id(self)), label=atb_label, help="trim marks", color=(50, 150, 50), alpha=50, text='light', position=pos,refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self._bar.add_button('close',self.unset_alive) #set up bar display padding self.on_window_resize(glfwGetCurrentContext(),*glfwGetWindowSize(glfwGetCurrentContext()))
def init_gui(self, pos=None): pos = self.gui_settings['pos'] import atb atb_label = "Light Points" self._bar = atb.Bar(name=self.__class__.__name__ + str(id(self)), label=atb_label, help="circle", color=(50, 50, 50), alpha=50, text='light', position=pos, refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self._bar.add_button('remove', self.unset_alive)
def create_atb_bar(self,pos): # add uvc camera controls to a separate ATB bar size = (200,200) self.bar = atb.Bar(name="Camera", label=self.name, help="UVC Camera Controls", color=(50,50,50), alpha=100, text='light',position=pos,refresh=2., size=size) cameras_enum = atb.enum("Capture",dict([(c.name,c.src_id) for c in Camera_List()]) ) self.bar.add_var("Capture",vtype=cameras_enum,getter=lambda:self.src_id, setter=self.re_init_cam_by_src_id) self.bar.add_var('framerate', vtype = atb.enum('framerate',self.capture.rates_menu), getter = lambda:self.capture.current_rate_idx, setter=self.capture.set_rate_idx ) self.bar.add_var('hardware timestamps',vtype=atb.TW_TYPE_BOOL8,getter=lambda:self.use_hw_ts) sorted_controls = [c for c in self.controls.itervalues()] sorted_controls.sort(key=lambda c: c.order) for control in sorted_controls: name = control.atb_name if control.type=="bool": self.bar.add_var(name,vtype=atb.TW_TYPE_BOOL8,getter=control.get_val,setter=control.set_val) elif control.type=='int': self.bar.add_var(name,vtype=atb.TW_TYPE_INT32,getter=control.get_val,setter=control.set_val) self.bar.define(definition='min='+str(control.min), varname=name) self.bar.define(definition='max='+str(control.max), varname=name) self.bar.define(definition='step='+str(control.step), varname=name) elif control.type=="menu": if control.menu is None: vtype = None else: vtype= atb.enum(name,control.menu) self.bar.add_var(name,vtype=vtype,getter=control.get_val,setter=control.set_val) if control.menu is None: self.bar.define(definition='min='+str(control.min), varname=name) self.bar.define(definition='max='+str(control.max), varname=name) self.bar.define(definition='step='+str(control.step), varname=name) else: pass if control.flags == "inactive": pass if control.name == 'exposure_auto_priority': # the controll should always be off. we set it to 0 on init (see above) self.bar.define(definition='readonly=1',varname=control.name) self.bar.add_button("refresh",self.controls.update_from_device) self.bar.add_button("load defaults",self.controls.load_defaults) return size
def init_gui(self): atb_label = "Export Recording" atb_pos = 320, 10 self._bar = atb.Bar(name=self.__class__.__name__, label=atb_label, help="export vizualization video", color=(50, 100, 100), alpha=100, text='light', position=atb_pos, refresh=.1, size=(300, 150)) self.update_bar()
def init_gui(self, pos=None): pos = self.gui_settings['pos'] import atb atb_label = "Scan Path" self._bar = atb.Bar(name=self.__class__.__name__ + str(id(self)), label=atb_label, help="polyline", color=(50, 50, 50), alpha=50, text='light', position=pos, refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self._bar.add_var('duration in sec', self.timeframe, min=0, step=0.1) self._bar.add_button('remove', self.unset_alive)
def init_gui(self, pos=None): import atb pos = self.gui_settings['pos'] atb_label = "Filter Fixations" self._bar = atb.Bar(name=self.__class__.__name__ + str(id(self)), label=atb_label, help="polyline", color=(50, 50, 50), alpha=50, text='light', position=pos, refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self._bar.add_var('distance in pixels', self.distance, min=0, step=0.1) self._bar.add_button('remove', self.unset_alive)
def create_atb_bar(self,pos): self.bar = atb.Bar(name = "Canny_Pupil_Detector", label="Pupil_Detector", help="pupil detection parameters", color=(50, 50, 50), alpha=100, text='light', position=pos,refresh=.3, size=(200, 100)) self.bar.fps = c_float(10) self.bar.add_var("fps", self.bar.fps, min=1) self.bar.add_var("use coarse detection",self.coarse_detection,help="Disbale when you have trouble with detection when using Mascara.") self.bar.add_button("open debug window", self.toggle_window,help="Open a debug window that shows geeky visual feedback from the algorithm.") self.bar.add_var("pupil_intensity_range",self.intensity_range,help="Using alorithm view set this as low as possible but so that the pupil is always fully overlayed in blue.") self.bar.add_var("pupil_min",self.pupil_min,min=1,help="Setting good bounds will increase detection robustness. Use alorithm view to see.") self.bar.add_var("pupil_max",self.pupil_max,min=1,help="Setting good bounds will increase detection robustness. Use alorithm view to see.") self.bar.add_var("Pupil_Aparent_Size",self.target_size,readonly=True) self.bar.add_var("Contour min length",self.min_contour_size,help="Setting this low will make the alorithm try to connect even smaller arcs to find the pupil but cost you cpu time!") self.bar.add_var("confidece threshold",c_float(0),getter= lambda: self.final_perimeter_ratio_range[0], setter=self.set_final_perimeter_ratio_range,step=.05,min=0.,max=1. , help="Fraction of pupil boundry that has to be visible and detected for the resukt to be declared valid.") # self.bar.add_var("Pupil_Shade",self.bin_thresh, readonly=True) self.bar.add_var("confidence",self.confidence, readonly=True,help="The measure of confidence is a number between 0 and 1 of how sure the algorithm is about the detected pupil. We currenlty use the fraction of pupil boundry edge that is used as support for the ellipse result.")
def create_atb_bar(self, pos): self._bar = atb.Bar(name="Canny_Pupil_Detector", label="Pupil_Detector", help="pupil detection parameters", color=(50, 50, 50), alpha=100, text='light', position=pos, refresh=.3, size=(200, 100)) self._bar.add_button("open debug window", self.toggle_window) self._bar.add_var("pupil_intensity_range", self.intensity_range) self._bar.add_var("pupil_min", self.pupil_min, min=1) self._bar.add_var("pupil_max", self.pupil_max, min=1) self._bar.add_var("Pupil_Aparent_Size", self.target_size) self._bar.add_var("Contour min length", self.min_contour_size) self._bar.add_var("Pupil_Shade", self.bin_thresh, readonly=True) self._bar.add_var("confidence", self.confidence, readonly=True)
def create_atb_bar(self, pos): # add uvc camera controls to a separate ATB bar size = (250, 100) self.bar = atb.Bar(name="Capture_Controls", label='Could not start real capture.', help="Fake Capture Controls", color=(250, 50, 50), alpha=100, text='light', position=pos, refresh=2., size=size) # cameras_enum = atb.enum("Capture",dict([(c.name,c.src_id) for c in Camera_List()]) ) # self.bar.add_var("Capture",vtype=cameras_enum,getter=lambda:self.src_id, setter=self.re_init_cam_by_src_id) self.bar.add_var("fps", self.fps, min=0, step=1) self.bar.add_button("as fast as possible", self.fastmode) return size
def init_gui(self, pos=None): pos = self.gui_settings['pos'] import atb atb_label = "Manual Gaze Correction" self._bar = atb.Bar(name=self.__class__.__name__ + str(id(self)), label=atb_label, help="polyline", color=(50, 50, 50), alpha=50, text='light', position=pos, refresh=.1, size=self.gui_settings['size']) self._bar.iconified = self.gui_settings['iconified'] self._bar.add_var('x_offset', self.x_offset, step=0.002, help="move gaze sideways. screen width is one unit") self._bar.add_var( 'y_offset', self.y_offset, step=0.002, help="move gaze up and down. screen height is one unit") self._bar.add_button("remove", self.unset_alive)
def __init__(self, g_pool, atb_pos=(0, 0)): Plugin.__init__(self) self.g_pool = g_pool self.first_img = None self.point = None self.count = 0 self.detected = False self.active = False self.pos = None self.r = 40.0 # radius of circle displayed self.ref_list = [] self.pupil_list = [] atb_label = "calibrate using natural features" self._bar = atb.Bar(name=self.__class__.__name__, label=atb_label, help="ref detection parameters", color=(50, 50, 50), alpha=100, text='light', position=atb_pos, refresh=.3, size=(300, 100)) self._bar.add_button("start/stop", self.start_stop, key='c')
def world(g_pool, cap_src, cap_size): """world Creates a window, gl context. Grabs images from a capture. Receives Pupil coordinates from g_pool.pupil_queue Can run various plug-ins. """ # Callback functions def on_resize(window, w, h): active_window = glfwGetCurrentContext() glfwMakeContextCurrent(window) norm_size = normalize((w, h), glfwGetWindowSize(window)) fb_size = denormalize(norm_size, glfwGetFramebufferSize(window)) atb.TwWindowSize(*map(int, fb_size)) adjust_gl_view(w, h, window) glfwMakeContextCurrent(active_window) for p in g_pool.plugins: p.on_window_resize(window, w, h) def on_iconify(window, iconfied): if not isinstance(cap, FakeCapture): g_pool.update_textures.value = not iconfied def on_key(window, key, scancode, action, mods): if not atb.TwEventKeyboardGLFW(key, action): if action == GLFW_PRESS: if key == GLFW_KEY_ESCAPE: on_close(window) def on_char(window, char): if not atb.TwEventCharGLFW(char, 1): pass def on_button(window, button, action, mods): if not atb.TwEventMouseButtonGLFW(button, action): pos = glfwGetCursorPos(window) pos = normalize(pos, glfwGetWindowSize(world_window)) pos = denormalize(pos, (frame.img.shape[1], frame.img.shape[0])) # Position in img pixels for p in g_pool.plugins: p.on_click(pos, button, action) def on_pos(window, x, y): norm_pos = normalize((x, y), glfwGetWindowSize(window)) fb_x, fb_y = denormalize(norm_pos, glfwGetFramebufferSize(window)) if atb.TwMouseMotion(int(fb_x), int(fb_y)): pass def on_scroll(window, x, y): if not atb.TwMouseWheel(int(x)): pass def on_close(window): g_pool.quit.value = True logger.info('Process closing from window') # load session persistent settings session_settings = Persistent_Dict( os.path.join(g_pool.user_dir, 'user_settings_world')) def load(var_name, default): return session_settings.get(var_name, default) def save(var_name, var): session_settings[var_name] = var # Initialize capture cap = autoCreateCapture(cap_src, cap_size, 24, timebase=g_pool.timebase) # Get an image from the grabber try: frame = cap.get_frame() except CameraCaptureError: logger.error("Could not retrieve image from capture") cap.close() return height, width = frame.img.shape[:2] # load last calibration data try: pt_cloud = np.load(os.path.join(g_pool.user_dir, 'cal_pt_cloud.npy')) logger.debug("Using calibration found in %s" % g_pool.user_dir) map_pupil = calibrate.get_map_from_cloud(pt_cloud, (width, height)) except: logger.debug("No calibration found.") def map_pupil(vector): """ 1 to 1 mapping """ return vector # any object we attach to the g_pool object *from now on* will only be visible to this process! # vars should be declared here to make them visible to the code reader. g_pool.plugins = [] g_pool.map_pupil = map_pupil g_pool.update_textures = c_bool(1) if isinstance(cap, FakeCapture): g_pool.update_textures.value = False g_pool.capture = cap g_pool.rec_name = recorder.get_auto_name() # helpers called by the main atb bar def update_fps(): old_time, bar.timestamp = bar.timestamp, time() dt = bar.timestamp - old_time if dt: bar.fps.value += .05 * (1. / dt - bar.fps.value) def set_window_size(mode, data): height, width = frame.img.shape[:2] ratio = (1, .75, .5, .25)[mode] w, h = int(width * ratio), int(height * ratio) glfwSetWindowSize(world_window, w, h) data.value = mode # update the bar.value def get_from_data(data): """ helper for atb getter and setter use """ return data.value def set_rec_name(val): if not val.value: g_pool.rec_name = recorder.get_auto_name() else: g_pool.rec_name = val.value def get_rec_name(): return create_string_buffer(g_pool.rec_name, 512) def open_calibration(selection, data): # prepare destruction of current ref_detector... and remove it for p in g_pool.plugins: if isinstance(p, calibration_routines.detector_by_index): p.alive = False g_pool.plugins = [p for p in g_pool.plugins if p.alive] new_ref_detector = calibration_routines.detector_by_index[selection]( g_pool, atb_pos=bar.next_atb_pos) g_pool.plugins.append(new_ref_detector) g_pool.plugins.sort(key=lambda p: p.order) # save the value for atb bar data.value = selection def toggle_record_video(): for p in g_pool.plugins: if isinstance(p, recorder.Recorder): p.alive = False return new_plugin = recorder.Recorder(g_pool, g_pool.rec_name, bar.fps.value, frame.img.shape, bar.record_eye.value, g_pool.eye_tx, bar.audio.value) g_pool.plugins.append(new_plugin) g_pool.plugins.sort(key=lambda p: p.order) def toggle_show_calib_result(): for p in g_pool.plugins: if isinstance(p, Show_Calibration): p.alive = False return new_plugin = Show_Calibration(g_pool, frame.img.shape) g_pool.plugins.append(new_plugin) g_pool.plugins.sort(key=lambda p: p.order) def toggle_server(): for p in g_pool.plugins: if isinstance(p, Pupil_Server): p.alive = False return new_plugin = Pupil_Server(g_pool, (10, 300)) g_pool.plugins.append(new_plugin) g_pool.plugins.sort(key=lambda p: p.order) def toggle_remote(): for p in g_pool.plugins: if isinstance(p, Pupil_Remote): p.alive = False return new_plugin = Pupil_Remote(g_pool, (10, 360), on_char) g_pool.plugins.append(new_plugin) g_pool.plugins.sort(key=lambda p: p.order) def toggle_ar(): for p in g_pool.plugins: if isinstance(p, Marker_Detector): p.alive = False return new_plugin = Marker_Detector(g_pool, (10, 400)) g_pool.plugins.append(new_plugin) g_pool.plugins.sort(key=lambda p: p.order) def reset_timebase(): #the last frame from worldcam will be t0 g_pool.timebase.value = g_pool.capure.get_now() logger.info( "New timebase set to %s all timestamps will count from here now." % g_pool.timebase.value) atb.init() # add main controls ATB bar bar = atb.Bar(name="World", label="Controls", help="Scene controls", color=(50, 50, 50), alpha=100, valueswidth=150, text='light', position=(10, 10), refresh=.3, size=(300, 200)) bar.next_atb_pos = (10, 220) bar.fps = c_float(0.0) bar.timestamp = time() bar.calibration_type = c_int(load("calibration_type", 0)) bar.record_eye = c_bool(load("record_eye", 0)) bar.audio = c_int(load("audio", -1)) bar.window_size = c_int(load("window_size", 0)) window_size_enum = atb.enum("Display Size", { "Full": 0, "Medium": 1, "Half": 2, "Mini": 3 }) calibrate_type_enum = atb.enum("Calibration Method", calibration_routines.index_by_name) audio_enum = atb.enum("Audio Input", dict(Audio_Input_List())) bar.version = create_string_buffer(g_pool.version, 512) bar.add_var( "fps", bar.fps, step=1., readonly=True, help= "Refresh speed of this process. Especially during recording it should not drop below the camera set frame rate." ) bar.add_var( "display size", vtype=window_size_enum, setter=set_window_size, getter=get_from_data, data=bar.window_size, help="Resize the world window. This has no effect on the actual image." ) bar.add_var("calibration method", setter=open_calibration, getter=get_from_data, data=bar.calibration_type, vtype=calibrate_type_enum, group="Calibration", help="Please choose your desired calibration method.") bar.add_button("show calibration result", toggle_show_calib_result, group="Calibration", help="Click to show calibration result.") bar.add_var("session name", create_string_buffer(512), getter=get_rec_name, setter=set_rec_name, group="Recording", help="Give your recording session a custom name.") bar.add_button("record", toggle_record_video, key="r", group="Recording", help="Start/Stop Recording") bar.add_var("record eye", bar.record_eye, group="Recording", help="check to save raw video of eye") bar.add_var("record audio", bar.audio, vtype=audio_enum, group="Recording", help="Select from audio recording options.") bar.add_button( "start/stop marker tracking", toggle_ar, key="x", help="find markers in scene to map gaze onto referace surfaces") bar.add_button( "start/stop server", toggle_server, key="s", help= "the server broadcasts pupil and gaze positions locally or via network" ) bar.add_button("start/stop remote", toggle_remote, key="w", help="remote allows seding commad to pupil via network") bar.add_button( "set timebase to now", reset_timebase, help="this button allows the timestamps to count from now on.", key="t") bar.add_var( "update screen", g_pool.update_textures, help= "if you dont need to see the camera image updated, you can turn this of to reduce CPU load." ) bar.add_separator("Sep1") bar.add_var("version", bar.version, readonly=True) bar.add_var("exit", g_pool.quit) # add uvc camera controls ATB bar cap.create_atb_bar(pos=(320, 10)) # Initialize glfw glfwInit() world_window = glfwCreateWindow(width, height, "World", None, None) glfwMakeContextCurrent(world_window) # Register callbacks world_window glfwSetWindowSizeCallback(world_window, on_resize) glfwSetWindowCloseCallback(world_window, on_close) glfwSetWindowIconifyCallback(world_window, on_iconify) glfwSetKeyCallback(world_window, on_key) glfwSetCharCallback(world_window, on_char) glfwSetMouseButtonCallback(world_window, on_button) glfwSetCursorPosCallback(world_window, on_pos) glfwSetScrollCallback(world_window, on_scroll) #set the last saved window size set_window_size(bar.window_size.value, bar.window_size) on_resize(world_window, *glfwGetWindowSize(world_window)) glfwSetWindowPos(world_window, 0, 0) # gl_state settings basic_gl_setup() g_pool.image_tex = create_named_texture(frame.img) # refresh speed settings glfwSwapInterval(0) #load calibration plugin open_calibration(bar.calibration_type.value, bar.calibration_type) #load gaze_display plugin g_pool.plugins.append(Display_Recent_Gaze(g_pool)) # Event loop while not g_pool.quit.value: # Get an image from the grabber try: frame = cap.get_frame() except CameraCaptureError: logger.error("Capture from Camera Failed. Stopping.") break except EndofVideoFileError: logger.warning("Video File is done. Stopping") break update_fps() #a container that allows plugins to post and read events events = [] #receive and map pupil positions recent_pupil_positions = [] while not g_pool.pupil_queue.empty(): p = g_pool.pupil_queue.get() if p['norm_pupil'] is None: p['norm_gaze'] = None else: p['norm_gaze'] = g_pool.map_pupil(p['norm_pupil']) recent_pupil_positions.append(p) # allow each Plugin to do its work. for p in g_pool.plugins: p.update(frame, recent_pupil_positions, events) #check if a plugin need to be destroyed g_pool.plugins = [p for p in g_pool.plugins if p.alive] # render camera image glfwMakeContextCurrent(world_window) make_coord_system_norm_based() if g_pool.update_textures.value: draw_named_texture(g_pool.image_tex, frame.img) else: draw_named_texture(g_pool.image_tex) make_coord_system_pixel_based(frame.img.shape) # render visual feedback from loaded plugins for p in g_pool.plugins: p.gl_display() atb.draw() glfwSwapBuffers(world_window) glfwPollEvents() # de-init all running plugins for p in g_pool.plugins: p.alive = False #reading p.alive actually runs plug-in cleanup _ = p.alive save('window_size', bar.window_size.value) save('calibration_type', bar.calibration_type.value) save('record_eye', bar.record_eye.value) save('audio', bar.audio.value) session_settings.close() cap.close() atb.terminate() glfwDestroyWindow(world_window) glfwTerminate() logger.debug("Process done")
def main(): # Callback functions def on_resize(window, w, h): active_window = glfwGetCurrentContext() glfwMakeContextCurrent(window) adjust_gl_view(w, h, window) norm_size = normalize((w, h), glfwGetWindowSize(window)) fb_size = denormalize(norm_size, glfwGetFramebufferSize(window)) atb.TwWindowSize(*map(int, fb_size)) glfwMakeContextCurrent(active_window) for p in g.plugins: p.on_window_resize(window, w, h) def on_key(window, key, scancode, action, mods): if not atb.TwEventKeyboardGLFW(key, action): if action == GLFW_PRESS: pass def on_char(window, char): if not atb.TwEventCharGLFW(char, 1): pass def on_button(window, button, action, mods): if not atb.TwEventMouseButtonGLFW(button, action): pos = glfwGetCursorPos(window) pos = normalize(pos, glfwGetWindowSize(main_window)) pos = denormalize(pos, (frame.img.shape[1], frame.img.shape[0])) # Position in img pixels for p in g.plugins: p.on_click(pos, button, action) def on_pos(window, x, y): norm_pos = normalize((x, y), glfwGetWindowSize(window)) fb_x, fb_y = denormalize(norm_pos, glfwGetFramebufferSize(window)) if atb.TwMouseMotion(int(fb_x), int(fb_y)): pass def on_scroll(window, x, y): if not atb.TwMouseWheel(int(x)): pass def on_close(window): glfwSetWindowShouldClose(main_window, True) logger.debug('Process closing from window') try: rec_dir = sys.argv[1] except: #for dev, supply hardcoded dir: rec_dir = '/Users/mkassner/Desktop/Marker_Tracking_Demo_Recording/' if os.path.isdir(rec_dir): logger.debug("Dev option: Using hadcoded data dir.") else: if getattr(sys, 'frozen', False): logger.warning( "You did not supply a data directory when you called this script! \ \nPlease drag a Pupil recoding directory onto the launch icon." ) else: logger.warning( "You did not supply a data directory when you called this script! \ \nPlease supply a Pupil recoding directory as first arg when calling Pupil Player." ) return if not is_pupil_rec_dir(rec_dir): logger.error( "You did not supply a dir with the required files inside.") return #backwards compatibility fn. patch_meta_info(rec_dir) #parse and load data folder info video_path = rec_dir + "/world.avi" timestamps_path = rec_dir + "/timestamps.npy" gaze_positions_path = rec_dir + "/gaze_positions.npy" meta_info_path = rec_dir + "/info.csv" #parse info.csv file with open(meta_info_path) as info: meta_info = dict( ((line.strip().split('\t')) for line in info.readlines())) rec_version = meta_info["Capture Software Version"] rec_version_float = int( filter(type(rec_version).isdigit, rec_version)[:3]) / 100. #(get major,minor,fix of version) logger.debug("Recording version: %s , %s" % (rec_version, rec_version_float)) #load gaze information gaze_list = np.load(gaze_positions_path) timestamps = np.load(timestamps_path) #correlate data positions_by_frame = correlate_gaze(gaze_list, timestamps) # load session persistent settings session_settings = Persistent_Dict(os.path.join(user_dir, "user_settings")) def load(var_name, default): return session_settings.get(var_name, default) def save(var_name, var): session_settings[var_name] = var # Initialize capture cap = autoCreateCapture(video_path, timestamps=timestamps_path) if isinstance(cap, FakeCapture): logger.error("could not start capture.") return width, height = cap.get_size() # Initialize glfw glfwInit() main_window = glfwCreateWindow( width, height, "Pupil Player: " + meta_info["Recording Name"] + " - " + rec_dir.split(os.path.sep)[-1], None, None) glfwMakeContextCurrent(main_window) # Register callbacks main_window glfwSetWindowSizeCallback(main_window, on_resize) glfwSetWindowCloseCallback(main_window, on_close) glfwSetKeyCallback(main_window, on_key) glfwSetCharCallback(main_window, on_char) glfwSetMouseButtonCallback(main_window, on_button) glfwSetCursorPosCallback(main_window, on_pos) glfwSetScrollCallback(main_window, on_scroll) # create container for globally scoped varfs (within world) g = Temp() g.plugins = [] g.play = False g.new_seek = True g.user_dir = user_dir g.rec_dir = rec_dir g.app = 'player' g.timestamps = timestamps g.positions_by_frame = positions_by_frame # helpers called by the main atb bar def update_fps(): old_time, bar.timestamp = bar.timestamp, time() dt = bar.timestamp - old_time if dt: bar.fps.value += .1 * (1. / dt - bar.fps.value) def set_window_size(mode, data): width, height = cap.get_size() ratio = (1, .75, .5, .25)[mode] w, h = int(width * ratio), int(height * ratio) glfwSetWindowSize(main_window, w, h) data.value = mode # update the bar.value def get_from_data(data): """ helper for atb getter and setter use """ return data.value def get_play(): return g.play def set_play(value): g.play = value def next_frame(): try: cap.seek_to_frame(cap.get_frame_index()) except FileSeekError: pass g.new_seek = True def prev_frame(): try: cap.seek_to_frame(cap.get_frame_index() - 2) except FileSeekError: pass g.new_seek = True def open_plugin(selection, data): if plugin_by_index[selection] not in additive_plugins: for p in g.plugins: if isinstance(p, plugin_by_index[selection]): return g.plugins = [p for p in g.plugins if p.alive] logger.debug('Open Plugin: %s' % name_by_index[selection]) new_plugin = plugin_by_index[selection](g) g.plugins.append(new_plugin) g.plugins.sort(key=lambda p: p.order) if hasattr(new_plugin, 'init_gui'): new_plugin.init_gui() # save the value for atb bar data.value = selection def get_from_data(data): """ helper for atb getter and setter use """ return data.value atb.init() # add main controls ATB bar bar = atb.Bar(name="Controls", label="Controls", help="Scene controls", color=(50, 50, 50), alpha=100, valueswidth=150, text='light', position=(10, 10), refresh=.1, size=(300, 160)) bar.next_atb_pos = (10, 220) bar.fps = c_float(0.0) bar.timestamp = time() bar.window_size = c_int(load("window_size", 0)) window_size_enum = atb.enum("Display Size", { "Full": 0, "Medium": 1, "Half": 2, "Mini": 3 }) bar.version = create_string_buffer(version, 512) bar.recording_version = create_string_buffer(rec_version, 512) bar.add_var("fps", bar.fps, step=1., readonly=True) bar._fps = c_float(cap.get_fps()) bar.add_var("recoding fps", bar._fps, readonly=True) bar.add_var("display size", vtype=window_size_enum, setter=set_window_size, getter=get_from_data, data=bar.window_size) bar.add_var("play", vtype=c_bool, getter=get_play, setter=set_play, key="space") bar.add_button('step next', next_frame, key='right') bar.add_button('step prev', prev_frame, key='left') bar.add_var("frame index", vtype=c_int, getter=lambda: cap.get_frame_index() - 1) bar.plugin_to_load = c_int(0) plugin_type_enum = atb.enum("Plug In", index_by_name) bar.add_var("plugin", setter=open_plugin, getter=get_from_data, data=bar.plugin_to_load, vtype=plugin_type_enum) bar.add_var( "version of recording", bar.recording_version, readonly=True, help="version of the capture software used to make this recording") bar.add_var("version of player", bar.version, readonly=True, help="version of the Pupil Player") bar.add_button("exit", on_close, data=main_window, key="esc") #set the last saved window size set_window_size(bar.window_size.value, bar.window_size) on_resize(main_window, *glfwGetWindowSize(main_window)) glfwSetWindowPos(main_window, 0, 0) #we always load these plugins g.plugins.append( Export_Launcher(g, data_dir=rec_dir, frame_count=len(timestamps))) g.plugins.append(Seek_Bar(g, capture=cap)) g.trim_marks = Trim_Marks(g, capture=cap) g.plugins.append(g.trim_marks) #these are loaded based on user settings for initializer in load('plugins', []): name, args = initializer logger.debug("Loading plugin: %s with settings %s" % (name, args)) try: p = plugin_by_name[name](g, **args) g.plugins.append(p) except: logger.warning("Plugin '%s' failed to load from settings file." % name) if load('plugins', "_") == "_": #lets load some default if we dont have presets g.plugins.append(Scan_Path(g)) g.plugins.append(Vis_Polyline(g)) g.plugins.append(Vis_Circle(g)) # g.plugins.append(Vis_Light_Points(g)) #sort by exec order g.plugins.sort(key=lambda p: p.order) #init gui for p in g.plugins: if hasattr(p, 'init_gui'): p.init_gui() # gl_state settings basic_gl_setup() g.image_tex = create_named_texture((height, width, 3)) while not glfwWindowShouldClose(main_window): update_fps() #grab new frame if g.play or g.new_seek: try: new_frame = cap.get_frame() except EndofVideoFileError: #end of video logic: pause at last frame. g.play = False if g.new_seek: display_time = new_frame.timestamp g.new_seek = False frame = new_frame.copy() #new positons and events we make a deepcopy just like the image is a copy. current_pupil_positions = deepcopy(positions_by_frame[frame.index]) events = [] # allow each Plugin to do its work. for p in g.plugins: p.update(frame, current_pupil_positions, events) #check if a plugin need to be destroyed g.plugins = [p for p in g.plugins if p.alive] # render camera image glfwMakeContextCurrent(main_window) make_coord_system_norm_based() draw_named_texture(g.image_tex, frame.img) make_coord_system_pixel_based(frame.img.shape) # render visual feedback from loaded plugins for p in g.plugins: p.gl_display() #present frames at appropriate speed wait_time = frame.timestamp - display_time display_time = frame.timestamp try: spent_time = time() - timestamp sleep(wait_time - spent_time) except: pass timestamp = time() atb.draw() glfwSwapBuffers(main_window) glfwPollEvents() plugin_save = [] for p in g.plugins: try: p_initializer = p.get_class_name(), p.get_init_dict() plugin_save.append(p_initializer) except AttributeError: #not all plugins need to be savable, they will not have the init dict. # any object without a get_init_dict method will throw this exception. pass # de-init all running plugins for p in g.plugins: p.alive = False #reading p.alive actually runs plug-in cleanup _ = p.alive save('plugins', plugin_save) save('window_size', bar.window_size.value) session_settings.close() cap.close() bar.destroy() glfwDestroyWindow(main_window) glfwTerminate() logger.debug("Process done")
def __init__(self, g_pool, session_str, fps, img_shape, record_eye, eye_tx, audio=-1): Plugin.__init__(self) self.g_pool = g_pool self.session_str = session_str self.record_eye = record_eye self.frame_count = 0 self.timestamps = [] self.gaze_list = [] self.eye_tx = eye_tx self.start_time = time() session = os.path.join(self.g_pool.rec_dir, self.session_str) try: os.mkdir(session) logger.debug("Created new recordings session dir %s" % session) except: logger.debug( "Recordings session dir %s already exists, using it." % session) # set up self incrementing folder within session folder counter = 0 while True: self.rec_path = os.path.join(session, "%03d/" % counter) try: os.mkdir(self.rec_path) logger.debug("Created new recording dir %s" % self.rec_path) break except: logger.debug( "We dont want to overwrite data, incrementing counter & trying to make new data folder" ) counter += 1 self.meta_info_path = os.path.join(self.rec_path, "info.csv") with open(self.meta_info_path, 'w') as f: f.write("Recording Name\t" + self.session_str + "\n") f.write("Start Date\t" + strftime("%d.%m.%Y", localtime(self.start_time)) + "\n") f.write("Start Time\t" + strftime("%H:%M:%S", localtime(self.start_time)) + "\n") if audio >= 0: audio_src = audio audio_path = os.path.join(self.rec_path, "world.wav") self.audio_writer = Audio_Capture(audio_src, audio_path) else: self.audio_writer = None video_path = os.path.join(self.rec_path, "world.avi") self.writer = cv2.VideoWriter(video_path, cv2.cv.CV_FOURCC(*'DIVX'), fps, (img_shape[1], img_shape[0])) self.height = img_shape[0] self.width = img_shape[1] # positions path to eye process if self.record_eye: self.eye_tx.send(self.rec_path) atb_pos = (10, 540) self._bar = atb.Bar(name=self.__class__.__name__, label='REC: ' + session_str, help="capture recording control", color=(220, 0, 0), alpha=150, text='light', position=atb_pos, refresh=.3, size=(300, 80)) self._bar.add_var( "rec time", create_string_buffer(512), getter=lambda: create_string_buffer(self.get_rec_time_str(), 512), readonly=True) self._bar.add_button("stop", self.on_stop, key="s", help="stop recording") self._bar.define("contained=true")
def __init__(self, g_pool, atb_pos=(0,0)): Plugin.__init__(self) self.g_pool = g_pool self.active = False self.detected = False self.screen_marker_state = 0 self.screen_marker_max = 70 # maximum bound for state self.active_site = 0 self.sites = [] self.display_pos = None self.on_position = False self.candidate_ellipses = [] self.pos = None #result calculation variables: self.world_size = None self.fov = c_float(90.) #taken from c930e specsheet, confirmed though mesurement within ~10deg. self.res = c_float(1.) self.outlier_thresh = c_float(5.) self.accuray = c_float(0) self.percision = c_float(0) try: self.pt_cloud = np.load(os.path.join(self.g_pool.user_dir,'accuray_test_pt_cloud.npy')) gaze,ref = self.pt_cloud[:,0:2],self.pt_cloud[:,2:4] error_lines = np.array([[g,r] for g,r in zip(gaze,ref)]) self.error_lines = error_lines.reshape(-1,2) except Exception: self.error_lines = None self.pt_cloud = None self.show_edges = c_bool(0) self.dist_threshold = c_int(5) self.area_threshold = c_int(20) self._window = None self.window_should_close = False self.window_should_open = False self.fullscreen = c_bool(1) self.monitor_idx = c_int(0) monitor_handles = glfwGetMonitors() self.monitor_names = [glfwGetMonitorName(m) for m in monitor_handles] monitor_enum = atb.enum("Monitor",dict(((key,val) for val,key in enumerate(self.monitor_names)))) #primary_monitor = glfwGetPrimaryMonitor() atb_label = "screen marker based accuracy test" # Creating an ATB Bar is required. Show at least some info about the Ref_Detector self._bar = atb.Bar(name = self.__class__.__name__, label=atb_label, help="ref detection parameters", color=(50, 50, 50), alpha=100, text='light', position=atb_pos,refresh=.3, size=(300, 200)) self._bar.add_var("monitor",self.monitor_idx, vtype=monitor_enum) self._bar.add_var("fullscreen", self.fullscreen) self._bar.add_button(" start test ", self.start, key='c') accuray_help ='''Accuracy is calculated as the average angular offset (distance) (in degrees of visual angle) between fixations locations and the corresponding locations of the fixation targets.'''.replace("\n"," ").replace(" ",'') percision_help = '''Precision is calculated as the Root Mean Square (RMS) of the angular distance (in degrees of visual angle) between successive samples during a fixation.'''.replace("\n"," ").replace(" ",'') self._bar.add_var('diagonal FOV',self.fov,help="set the camera FOV here.",group='Error Calculation') self._bar.add_var('diagonal resolution',self.res,readonly= True ,group='Error Calculation') self._bar.add_var('outlier threshold deg',self.outlier_thresh ,group='Error Calculation') self._bar.add_var('angular accuray',self.accuray,readonly=True ,group='Error Calculation',help=accuray_help) self._bar.add_var('angular percision',self.percision,readonly=True ,group='Error Calculation',help=percision_help) self._bar.add_button('calculate result',self.calc_result ,group='Error Calculation') self._bar.add_var("show edges",self.show_edges, group="Detector Variables") self._bar.add_var("area threshold", self.area_threshold ,group="Detector Variables") self._bar.add_var("eccetricity threshold", self.dist_threshold, group="Detector Variables" )