#!/usr/bin/env python import argparse import bisect import os from argaze import GazeFeatures from argaze.TobiiGlassesPro2 import TobiiEntities from argaze.utils import MiscFeatures def main(): """ Analyse Tobii segment fixations """ # Manage arguments parser = argparse.ArgumentParser(description=main.__doc__.split('-')[0]) parser.add_argument('-s', '--segment_path', metavar='SEGMENT_PATH', type=str, default=None, help='path to a tobii segment folder') 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('-d', '--dispersion_threshold', metavar='DISPERSION_THRESHOLD', type=int, default=10, help='dispersion threshold in pixel') parser.add_argument('-t', '--duration_threshold', metavar='DURATION_THRESHOLD', type=int, default=100, help='duration threshold in millisecond') parser.add_argument('-o', '--output', metavar='OUT', type=str, default=None, help='destination folder path (segment folder by default)') args = parser.parse_args() if args.segment_path != None: # Manage destination path if args.output != None: if not os.path.exists(os.path.dirname(args.output)): os.makedirs(os.path.dirname(args.output)) print(f'{os.path.dirname(args.output)} folder created') fixations_filepath = f'{args.output}/fixations.csv' else: fixations_filepath = f'{args.segment_path}/fixations.csv' # Load a tobii segment tobii_segment = TobiiEntities.TobiiSegment(args.segment_path, int(args.time_range[0] * 1000000), int(args.time_range[1] * 1000000) if args.time_range[1] != None else None) # Load a tobii segment video tobii_segment_video = tobii_segment.load_video() print(f'Video duration: {tobii_segment_video.get_duration()/1000000}, width: {tobii_segment_video.get_width()}, height: {tobii_segment_video.get_height()}') # Load a tobii segment data tobii_segment_data = tobii_segment.load_data() print(f'Data keys: {tobii_segment_data.keys()}') # Access to timestamped gaze position data buffer tobii_ts_gaze_positions = tobii_segment_data.gidx_l_gp print(f'{len(tobii_ts_gaze_positions)} gaze positions loaded') # Format tobii gaze data into generic gaze data and store them using millisecond unit timestamp generic_ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() for ts, tobii_data in tobii_ts_gaze_positions.items(): generic_data = GazeFeatures.GazePosition(tobii_data.gp[0] * tobii_segment_video.get_width(), tobii_data.gp[1] * tobii_segment_video.get_height()) generic_ts_gaze_positions[ts/1000] = generic_data print(f'Dispersion threshold: {args.dispersion_threshold}') print(f'Duration threshold: {args.duration_threshold}') # Start fixation identification fixation_analyser = GazeFeatures.DispersionBasedFixationIdentifier(generic_ts_gaze_positions, args.dispersion_threshold, args.duration_threshold) fixations = GazeFeatures.TimeStampedFixations() # Initialise progress bar MiscFeatures.printProgressBar(0, int(tobii_segment_video.get_duration()/1000), prefix = 'Progress:', suffix = 'Complete', length = 100) for ts, item in fixation_analyser: if item == None: continue fixations[ts] = item # Update Progress Bar progress = ts - int(args.time_range[0] * 1000) MiscFeatures.printProgressBar(progress, int(tobii_segment_video.get_duration()/1000), prefix = 'Progress:', suffix = 'Complete', length = 100) print(f'\n{len(fixations)} fixations found') # Export fixations analysis results fixations.export_as_csv(fixations_filepath) print(f'Fixations saved into {fixations_filepath}') if __name__ == '__main__': main()