From 95be300b3af83db71307ce3d00c51ad3889013bc Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Mon, 10 Jul 2023 17:07:00 +0200 Subject: ArFrame look returns fixation only. --- src/argaze/ArFeatures.py | 111 +++++++++++++++++++---------- src/argaze/utils/demo_ar_features_run.py | 7 +- src/argaze/utils/demo_gaze_features_run.py | 2 +- 3 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py index 3e2bc12..43496ef 100644 --- a/src/argaze/ArFeatures.py +++ b/src/argaze/ArFeatures.py @@ -294,9 +294,10 @@ class ArFrame(): GazeFeatures.AOIScanStepError Returns: - gaze_movement: identified gaze movement (if gaze_movement_identifier is intanciated) - scan_step: new scan step (if scan_path is intanciated) - aoi_scan_step: new scan step (if aoi_scan_path is intanciated) + fixation: identified fixation (if gaze_movement_identifier is instanciated) + look at: when identified fixation looks at + scan_step: new scan step (if scan_path is instanciated) + aoi_scan_step: new scan step (if aoi_scan_path is instanciated) """ # Lock frame exploitation @@ -305,6 +306,9 @@ class ArFrame(): # Update current gaze position self.__gaze_position = inner_gaze_position + # No fixation is identified by default + fixation = GazeFeatures.UnvalidGazeMovement() + # No aoi is looked by default look_at = None @@ -318,63 +322,92 @@ class ArFrame(): # Identify finished gaze movement finished_gaze_movement = self.gaze_movement_identifier.identify(timestamp, self.__gaze_position) - if GazeFeatures.is_fixation(finished_gaze_movement): + # Valid and finished gaze movement has been identified + if finished_gaze_movement.valid: - # Does the fixation match an aoi? - for name, aoi in self.aoi_2d_scene.items(): + if GazeFeatures.is_fixation(finished_gaze_movement): - _, _, circle_ratio = aoi.circle_intersection(finished_gaze_movement.focus, finished_gaze_movement.deviation_max) + # Update current fixation + fixation = finished_gaze_movement - if circle_ratio > 0.25: + # Does the fixation match an aoi? + for name, aoi in self.aoi_2d_scene.items(): - if name != self.name: + _, _, circle_ratio = aoi.circle_intersection(finished_gaze_movement.focus, finished_gaze_movement.deviation_max) - # Update current look at - look_at = name - break + if circle_ratio > 0.25: - # Append fixation to scan path - if self.scan_path != None: + if name != self.name: - self.scan_path.append_fixation(timestamp, finished_gaze_movement) + # Update current look at + look_at = name + break - # Append fixation to aoi scan path - if self.aoi_scan_path != None and look_at != None: + # Append fixation to scan path + if self.scan_path != None: - aoi_scan_step = self.aoi_scan_path.append_fixation(timestamp, finished_gaze_movement, look_at) + self.scan_path.append_fixation(timestamp, finished_gaze_movement) - # Analyze aoi scan path - if aoi_scan_step and len(self.aoi_scan_path) > 1: + # Append fixation to aoi scan path + if self.aoi_scan_path != None and look_at != None: - for aoi_scan_path_analyzer_type, aoi_scan_path_analyzer in self.aoi_scan_path_analyzers.items(): + aoi_scan_step = self.aoi_scan_path.append_fixation(timestamp, finished_gaze_movement, look_at) - aoi_scan_path_analyzer.analyze(self.aoi_scan_path) + # Analyze aoi scan path + if aoi_scan_step and len(self.aoi_scan_path) > 1: - aoi_scan_step_analysis[aoi_scan_path_analyzer_type] = aoi_scan_path_analyzer.analysis + for aoi_scan_path_analyzer_type, aoi_scan_path_analyzer in self.aoi_scan_path_analyzers.items(): - elif GazeFeatures.is_saccade(finished_gaze_movement): + aoi_scan_path_analyzer.analyze(self.aoi_scan_path) - # Update current look at - look_at = None + aoi_scan_step_analysis[aoi_scan_path_analyzer_type] = aoi_scan_path_analyzer.analysis - # Append saccade to scan path - if self.scan_path != None: - - scan_step = self.scan_path.append_saccade(timestamp, finished_gaze_movement) + elif GazeFeatures.is_saccade(finished_gaze_movement): + + # Update current look at + look_at = None + + # Append saccade to scan path + if self.scan_path != None: + + scan_step = self.scan_path.append_saccade(timestamp, finished_gaze_movement) + + # Analyze aoi scan path + if scan_step and len(self.scan_path) > 1: + + for scan_path_analyzer_type, scan_path_analyzer in self.scan_path_analyzers.items(): + + scan_path_analyzer.analyze(self.scan_path) + + scan_step_analysis[scan_path_analyzer_type] = scan_path_analyzer.analysis + + # Append saccade to aoi scan path + if self.aoi_scan_path != None: + + self.aoi_scan_path.append_saccade(timestamp, finished_gaze_movement) + + # No valid finished gaze movement: check current fixation + else: + + current_fixation = self.gaze_movement_identifier.current_fixation + + if current_fixation.valid: - # Analyze aoi scan path - if scan_step and len(self.scan_path) > 1: + # Update current fixation + fixation = current_fixation - for scan_path_analyzer_type, scan_path_analyzer in self.scan_path_analyzers.items(): + # Does the fixation match an aoi? + for name, aoi in self.aoi_2d_scene.items(): - scan_path_analyzer.analyze(self.scan_path) + _, _, circle_ratio = aoi.circle_intersection(current_fixation.focus, current_fixation.deviation_max) - scan_step_analysis[scan_path_analyzer_type] = scan_path_analyzer.analysis + if circle_ratio > 0.25: - # Append saccade to aoi scan path - if self.aoi_scan_path != None: + if name != self.name: - self.aoi_scan_path.append_saccade(timestamp, finished_gaze_movement) + # Update current look at + look_at = name + break # Update heatmap if self.heatmap: @@ -385,7 +418,7 @@ class ArFrame(): self.__look_lock.release() # Return look data - return finished_gaze_movement, look_at, scan_step_analysis, aoi_scan_step_analysis + return fixation, look_at, scan_step_analysis, aoi_scan_step_analysis def draw(self, image:numpy.array): """ diff --git a/src/argaze/utils/demo_ar_features_run.py b/src/argaze/utils/demo_ar_features_run.py index 6151188..f8158d6 100644 --- a/src/argaze/utils/demo_ar_features_run.py +++ b/src/argaze/utils/demo_ar_features_run.py @@ -47,8 +47,11 @@ def main(): # Project gaze position into environment for frame, look_data in ar_environment.look(timestamp, GazeFeatures.GazePosition((x, y))): - # Do nothing with look data - pass + # Unpack look data + fixation, look_at, scan_step_analysis, aoi_scan_step_analysis = look_data + + # Do something with look data + # ... # Attach mouse callback to window cv2.setMouseCallback(ar_environment.name, on_mouse_event) diff --git a/src/argaze/utils/demo_gaze_features_run.py b/src/argaze/utils/demo_gaze_features_run.py index 2e6070f..8719e84 100644 --- a/src/argaze/utils/demo_gaze_features_run.py +++ b/src/argaze/utils/demo_gaze_features_run.py @@ -56,7 +56,7 @@ def main(): timestamp = int((time.time() - start_time) * 1e3) # Project gaze position into frame - ended_gaze_movement, look_at, scan_step_analysis, aoi_scan_step_analysis = ar_frame.look(timestamp, GazeFeatures.GazePosition((x, y))) + fixation, look_at, scan_step_analysis, aoi_scan_step_analysis = ar_frame.look(timestamp, GazeFeatures.GazePosition((x, y))) # Do something with look data # ... -- cgit v1.1