diff options
Diffstat (limited to 'src/argaze/utils/tobii_segment_display.py')
-rw-r--r-- | src/argaze/utils/tobii_segment_display.py | 116 |
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 |