aboutsummaryrefslogtreecommitdiff
path: root/src/argaze/utils/tobii_segment_display.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/argaze/utils/tobii_segment_display.py')
-rw-r--r--src/argaze/utils/tobii_segment_display.py116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/argaze/utils/tobii_segment_display.py b/src/argaze/utils/tobii_segment_display.py
new file mode 100644
index 0000000..86d0057
--- /dev/null
+++ b/src/argaze/utils/tobii_segment_display.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+import argparse
+
+from argaze import GazeFeatures
+from argaze.TobiiGlassesPro2 import TobiiEntities, TobiiVideo, TobiiData
+from argaze.utils import MiscFeatures
+
+import numpy
+
+import cv2 as cv
+
+def main():
+ """
+ Replay Tobii segment video
+ """
+
+ # manage arguments
+ parser = argparse.ArgumentParser(description=main.__doc__.split('-')[0])
+ parser.add_argument('-s', '--segment_path', metavar='SEGMENT_PATH', type=str, default=None, help='segment path')
+ parser.add_argument('-r', '--time_range', metavar=('START_TIME', 'END_TIME'), nargs=2, type=float, default=(0., None), help='start and end time (in second)')
+ parser.add_argument('-w', '--window', metavar='DISPLAY', type=bool, default=True, help='enable window display', action=argparse.BooleanOptionalAction)
+ args = parser.parse_args()
+
+ if args.segment_path != None:
+
+ # Load a tobii segment
+ tobii_segment = TobiiEntities.TobiiSegment(args.segment_path, int(args.time_range[0] * 1e6), int(args.time_range[1] * 1e6) if args.time_range[1] != None else None)
+
+ # Load a tobii segment video
+ tobii_segment_video = tobii_segment.load_video()
+ print(f'Video properties:\n\tduration: {tobii_segment_video.get_duration() / 1e6} s\n\twidth: {tobii_segment_video.get_width()} px\n\theight: {tobii_segment_video.get_height()} px')
+
+ # Load a tobii segment data
+ tobii_segment_data = tobii_segment.load_data()
+
+ print(f'Loaded data count:')
+ for name in tobii_segment_data.keys():
+ print(f'\t{name}: {len(tobii_segment_data[name])} data')
+
+ # Access to timestamped gaze position data buffer
+ tobii_ts_gaze_positions = tobii_segment_data['GazePosition']
+
+ # Access to timestamped pupil diameter data buffer
+ tobii_ts_pupil_diameter = tobii_segment_data['PupilDiameter']
+
+ # Access to timestamped events data buffer
+ tobii_ts_events = tobii_segment_data['Event']
+
+ # Video and data replay loop
+ try:
+
+ # Initialise progress bar
+ MiscFeatures.printProgressBar(0, tobii_segment_video.get_duration() / 1e3, prefix = 'Video progression:', suffix = 'Complete', length = 100)
+
+ # Iterate on video frames
+ for video_ts, video_frame in tobii_segment_video.frames():
+
+ video_ts_ms = video_ts / 1e3
+
+ # Write segment timing
+ cv.putText(video_frame.matrix, f'Segment time: {int(video_ts_ms)} ms', (20, 40), cv.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv.LINE_AA)
+
+ try:
+
+ # Get closest gaze position before video timestamp and remove all gaze positions before
+ closest_gaze_ts, closest_gaze_position = tobii_ts_gaze_positions.pop_first_until(video_ts)
+
+ # Get closest pupil diameter before video timestamp and remove all pupil diameters before
+ closest_pupil_ts, closest_pupil_diameter = tobii_ts_pupil_diameter.pop_first_until(video_ts)
+
+ # Draw gaze position
+ gaze_position = (int(closest_gaze_position.value[0] * video_frame.width), int(closest_gaze_position.value[1] * video_frame.height))
+ pupil_diameter = int((10 - closest_pupil_diameter.value) / 2)
+
+ cv.circle(video_frame.matrix, gaze_position, 10, (0, 255, 255), pupil_diameter)
+
+ # Wait for gaze position
+ except ValueError:
+ continue
+
+ try:
+
+ # Get closest event before video timestamp and remove all gaze positions before
+ closest_event_ts, closest_event = tobii_ts_events.pop_first_until(video_ts)
+
+ print(closest_event_ts / 1e3, closest_event)
+
+ # Write events
+ cv.putText(video_frame.matrix, str(closest_event), (20, 140), cv.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv.LINE_AA)
+
+ except ValueError:
+ pass
+
+ if args.window:
+
+ # Close window using 'Esc' key
+ if cv.waitKey(1) == 27:
+ break
+
+ cv.imshow(f'Segment {tobii_segment.get_id()} video', video_frame.matrix)
+
+ # Update Progress Bar
+ progress = video_ts_ms - int(args.time_range[0] * 1e3)
+ MiscFeatures.printProgressBar(progress, tobii_segment_video.get_duration() / 1e3, prefix = 'Video progression:', suffix = 'Complete', length = 100)
+
+ # Exit on 'ctrl+C' interruption
+ except KeyboardInterrupt:
+ pass
+
+ # Stop frame display
+ cv.destroyAllWindows()
+
+if __name__ == '__main__':
+
+ main() \ No newline at end of file