From 163d72eda8450ef3e7337d8490917e75d04ef3dd Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Tue, 12 Mar 2024 23:30:10 +0100 Subject: [PATCH] rename SeeTrue to SeeTrue STONE now have hardcoded camera calibration for the SeeTrue STONE, provided by SeeTrue --- .../{SeeTrue.py => SeeTrue_STONE.py} | 32 +++++++++++++++---- src/glassesValidator/preprocess/__init__.py | 12 +++---- src/glassesValidator/utils/__init__.py | 4 +-- 3 files changed, 34 insertions(+), 14 deletions(-) rename src/glassesValidator/preprocess/{SeeTrue.py => SeeTrue_STONE.py} (92%) diff --git a/src/glassesValidator/preprocess/SeeTrue.py b/src/glassesValidator/preprocess/SeeTrue_STONE.py similarity index 92% rename from src/glassesValidator/preprocess/SeeTrue.py rename to src/glassesValidator/preprocess/SeeTrue_STONE.py index 5614f2e..e0deb67 100644 --- a/src/glassesValidator/preprocess/SeeTrue.py +++ b/src/glassesValidator/preprocess/SeeTrue_STONE.py @@ -23,7 +23,7 @@ def preprocessData(output_dir, source_dir=None, rec_info=None, cam_cal_file=None RuntimeError('ffmpeg must be on path to prep SeeTrue recording for processing with GlassesValidator') """ - Run all preprocessing steps on SeeTrue data + Run all preprocessing steps on SeeTrue STONE data """ output_dir = pathlib.Path(output_dir) if source_dir is not None: @@ -36,8 +36,8 @@ def preprocessData(output_dir, source_dir=None, rec_info=None, cam_cal_file=None source_dir = pathlib.Path(rec_info.source_directory) if rec_info is not None: - if rec_info.eye_tracker!=utils.EyeTracker.SeeTrue: - raise ValueError(f'Provided rec_info is for a device ({rec_info.eye_tracker.value}) that is not an {utils.EyeTracker.SeeTrue.value}. Cannot use.') + if rec_info.eye_tracker!=utils.EyeTracker.SeeTrue_STONE: + raise ValueError(f'Provided rec_info is for a device ({rec_info.eye_tracker.value}) that is not an {utils.EyeTracker.SeeTrue_STONE.value}. Cannot use.') if not rec_info.proc_directory_name: rec_info.proc_directory_name = utils.make_fs_dirname(rec_info, output_dir) newDir = output_dir / rec_info.proc_directory_name @@ -57,7 +57,7 @@ def preprocessData(output_dir, source_dir=None, rec_info=None, cam_cal_file=None else: recInfos = getRecordingInfo(source_dir) if recInfos is None: - raise RuntimeError(f"The folder {source_dir} does not contain SeeTrue recordings.") + raise RuntimeError(f"The folder {source_dir} does not contain SeeTrue STONE recordings.") # make output dirs for i in range(len(recInfos)): @@ -83,7 +83,8 @@ def preprocessData(output_dir, source_dir=None, rec_info=None, cam_cal_file=None if cam_cal_file is not None: shutil.copyfile(str(cam_cal_file), str(newDataDir / 'calibration.xml')) else: - print(' !! No camera calibration provided!') + print(' !! No camera calibration provided! Defaulting to hardcoded') + getCameraHardcoded(newDataDir) # NB: gaze data and scene video prep are intertwined, status messages are output inside this function gazeDf, frameTimestamps = copySeeTrueRecording(source_dir, newDataDir, rec_info) @@ -119,7 +120,7 @@ def getRecordingInfo(inputDir): # print(f"folder {sceneVidDir} not found, meaning there is no scene video for this recording, skipping") continue - recInfos.append(utils.Recording(source_directory=inputDir, eye_tracker=utils.EyeTracker.SeeTrue)) + recInfos.append(utils.Recording(source_directory=inputDir, eye_tracker=utils.EyeTracker.SeeTrue_STONE)) recInfos[-1].participant = inputDir.name recInfos[-1].name = recording @@ -266,6 +267,25 @@ def copySeeTrueRecording(inputDir, outputDir, recInfo): return gazeDf, frameTimestamps +def getCameraHardcoded(outputDir): + """ + Get camera calibration + Hardcoded as per info received from SeeTrue + """ + # turn into camera matrix and distortion coefficients as used by OpenCV + camera = {} + camera['cameraMatrix'] = np.array([[495, 0, 300], + [ 0, 495, 255], + [ 0, 0, 1]], dtype=np.float64) + camera['distCoeff'] = np.array([-0.55, 0.4, 0, 0, -0.2]) + camera['resolution'] = np.array([640, 480]) + + # store to file + fs = cv2.FileStorage(str(outputDir / 'calibration.xml'), cv2.FILE_STORAGE_WRITE) + for key,value in camera.items(): + fs.write(name=key,val=value) + fs.release() + def formatGazeData(inputFile, sceneVideoDimensions): """ diff --git a/src/glassesValidator/preprocess/__init__.py b/src/glassesValidator/preprocess/__init__.py index 3a32b8d..56b89c7 100644 --- a/src/glassesValidator/preprocess/__init__.py +++ b/src/glassesValidator/preprocess/__init__.py @@ -4,7 +4,7 @@ from .. import utils as _utils from .adhawk_mindlink import preprocessData as adhawk_mindlink -from .SeeTrue import preprocessData as SeeTrue +from .SeeTrue_STONE import preprocessData as SeeTrue_STONE from .SMI_ETG import preprocessData as SMI_ETG from .tobii_G2 import preprocessData as tobii_G2 from .tobii_G3 import preprocessData as tobii_G3 @@ -37,8 +37,8 @@ def get_recording_info(source_dir: str | pathlib.Path, device: str | _utils.EyeT case _utils.EyeTracker.Pupil_Neon: from .pupilLabs import getRecordingInfo rec_info = getRecordingInfo(source_dir, device) - case _utils.EyeTracker.SeeTrue: - from .SeeTrue import getRecordingInfo + case _utils.EyeTracker.SeeTrue_STONE: + from .SeeTrue_STONE import getRecordingInfo rec_info = getRecordingInfo(source_dir) case _utils.EyeTracker.SMI_ETG: from .SMI_ETG import getRecordingInfo @@ -104,8 +104,8 @@ def do_import(output_dir: str | pathlib.Path, source_dir: str | pathlib.Path = N rec_info = pupil_invisible(output_dir, source_dir, rec_info) case _utils.EyeTracker.Pupil_Neon: rec_info = pupil_neon(output_dir, source_dir, rec_info) - case _utils.EyeTracker.SeeTrue: - rec_info = SeeTrue(output_dir, source_dir, rec_info) + case _utils.EyeTracker.SeeTrue_STONE: + rec_info = SeeTrue_STONE(output_dir, source_dir, rec_info) case _utils.EyeTracker.SMI_ETG: rec_info = SMI_ETG(output_dir, source_dir, rec_info) case _utils.EyeTracker.Tobii_Glasses_2: @@ -120,5 +120,5 @@ def do_import(output_dir: str | pathlib.Path, source_dir: str | pathlib.Path = N return rec_info -__all__ = ['pupil_core','pupil_invisible','pupil_neon','SeeTrue','SMI_ETG','tobii_G2','tobii_G3','adhawk_mindlink', +__all__ = ['pupil_core','pupil_invisible','pupil_neon','SeeTrue_STONE','SMI_ETG','tobii_G2','tobii_G3','adhawk_mindlink', 'get_recording_info','do_import'] \ No newline at end of file diff --git a/src/glassesValidator/utils/__init__.py b/src/glassesValidator/utils/__init__.py index ad42464..017fd21 100644 --- a/src/glassesValidator/utils/__init__.py +++ b/src/glassesValidator/utils/__init__.py @@ -70,7 +70,7 @@ class EyeTracker(AutoName): Pupil_Invisible = auto() Pupil_Neon = auto() SMI_ETG = auto() - SeeTrue = auto() + SeeTrue_STONE = auto() Tobii_Glasses_2 = auto() Tobii_Glasses_3 = auto() Unknown = auto() @@ -81,7 +81,7 @@ class EyeTracker(AutoName): EyeTracker.Pupil_Invisible.color = hex_to_rgba_0_1("#3CB44B") EyeTracker.Pupil_Neon .color = hex_to_rgba_0_1("#C6B41E") EyeTracker.SMI_ETG .color = hex_to_rgba_0_1("#4363D8") -EyeTracker.SeeTrue .color = hex_to_rgba_0_1("#911EB4") +EyeTracker.SeeTrue_STONE .color = hex_to_rgba_0_1("#911EB4") EyeTracker.Tobii_Glasses_2.color = hex_to_rgba_0_1("#F58231") EyeTracker.Tobii_Glasses_3.color = hex_to_rgba_0_1("#F032E6") EyeTracker.Unknown .color = hex_to_rgba_0_1("#393939")