aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/argaze.test/ArGazeScene.py59
-rw-r--r--src/argaze.test/ArScene.py59
-rw-r--r--src/argaze/ArScene.py (renamed from src/argaze/ArGazeScene.py)22
-rw-r--r--src/argaze/ArUcoMarkers/ArUcoScene.py172
-rw-r--r--src/argaze/__init__.py2
-rw-r--r--src/argaze/utils/tobii_segment_arscene_export.py (renamed from src/argaze/utils/tobii_segment_argaze_scene_export.py)36
6 files changed, 180 insertions, 170 deletions
diff --git a/src/argaze.test/ArGazeScene.py b/src/argaze.test/ArGazeScene.py
deleted file mode 100644
index 4d0b3ae..0000000
--- a/src/argaze.test/ArGazeScene.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-import os
-
-from argaze import ArGazeScene
-
-import numpy
-
-class TestArGazeSceneClass(unittest.TestCase):
- """Test ArGazeScene class."""
-
- def test_from_json(self):
- """Test ArGazeScene creation from json file."""
-
- # Edit scene file path
- current_directory = os.path.dirname(os.path.abspath(__file__))
- json_filepath = os.path.join(current_directory, 'utils/scene.json')
-
- # Load scene
- argaze_scene = ArGazeScene.ArGazeScene.from_json(json_filepath)
-
- # Check scene meta data
- self.assertEqual(argaze_scene.name, "TestScene")
- self.assertEqual(argaze_scene.aruco_dictionary.name, "DICT_ARUCO_ORIGINAL")
- self.assertEqual(argaze_scene.aruco_marker_size, 3.0)
-
- # Check ArUco camera
- self.assertEqual(argaze_scene.aruco_camera.rms, 1.0)
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_camera.dimensions, [1920, 1080]))
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_camera.K, [[1.0, 0.0, 1.0], [0.0, 1.0, 1.0], [0.0, 0.0, 1.0]]))
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_camera.D, [-1.0, -0.5, 0.0, 0.5, 1.0]))
-
- # Check ArUco tracker
- self.assertEqual(argaze_scene.aruco_tracker.tracking_data.cornerRefinementMethod, 3)
- self.assertEqual(argaze_scene.aruco_tracker.tracking_data.aprilTagQuadSigma, 2)
- self.assertEqual(argaze_scene.aruco_tracker.tracking_data.aprilTagDeglitch, 1)
-
- # Check ArUco scene
- self.assertEqual(argaze_scene.aruco_scene.angle_tolerance, 1.0)
- self.assertEqual(argaze_scene.aruco_scene.distance_tolerance, 2.0)
- self.assertEqual(len(argaze_scene.aruco_scene.places), 2)
-
- # Check ArUco scene places
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_scene.places['A'].translation, [1, 0, 0]))
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_scene.places['A'].rotation, [0, 0, 0]))
- self.assertEqual(argaze_scene.aruco_scene.places['A'].marker.identifier, 0)
-
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_scene.places['B'].translation, [0, 1, 0]))
- self.assertIsNone(numpy.testing.assert_array_equal(argaze_scene.aruco_scene.places['B'].rotation, [0, 90, 0]))
- self.assertEqual(argaze_scene.aruco_scene.places['B'].marker.identifier, 1)
-
- # Check AOI scene
- self.assertEqual(len(argaze_scene.aoi_scene.items()), 1)
- self.assertEqual(argaze_scene.aoi_scene['Test'].size, 4)
-
-if __name__ == '__main__':
-
- unittest.main() \ No newline at end of file
diff --git a/src/argaze.test/ArScene.py b/src/argaze.test/ArScene.py
new file mode 100644
index 0000000..cfb949b
--- /dev/null
+++ b/src/argaze.test/ArScene.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+import unittest
+import os
+
+from argaze import ArScene
+
+import numpy
+
+class TestArSceneClass(unittest.TestCase):
+ """Test ArScene class."""
+
+ def test_from_json(self):
+ """Test ArScene creation from json file."""
+
+ # Edit scene file path
+ current_directory = os.path.dirname(os.path.abspath(__file__))
+ json_filepath = os.path.join(current_directory, 'utils/scene.json')
+
+ # Load scene
+ ar_scene = ArScene.ArScene.from_json(json_filepath)
+
+ # Check scene meta data
+ self.assertEqual(ar_scene.name, "TestScene")
+ self.assertEqual(ar_scene.aruco_dictionary.name, "DICT_ARUCO_ORIGINAL")
+ self.assertEqual(ar_scene.aruco_marker_size, 3.0)
+
+ # Check ArUco camera
+ self.assertEqual(ar_scene.aruco_camera.rms, 1.0)
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_camera.dimensions, [1920, 1080]))
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_camera.K, [[1.0, 0.0, 1.0], [0.0, 1.0, 1.0], [0.0, 0.0, 1.0]]))
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_camera.D, [-1.0, -0.5, 0.0, 0.5, 1.0]))
+
+ # Check ArUco tracker
+ self.assertEqual(ar_scene.aruco_tracker.tracking_data.cornerRefinementMethod, 3)
+ self.assertEqual(ar_scene.aruco_tracker.tracking_data.aprilTagQuadSigma, 2)
+ self.assertEqual(ar_scene.aruco_tracker.tracking_data.aprilTagDeglitch, 1)
+
+ # Check ArUco scene
+ self.assertEqual(ar_scene.aruco_scene.angle_tolerance, 1.0)
+ self.assertEqual(ar_scene.aruco_scene.distance_tolerance, 2.0)
+ self.assertEqual(len(ar_scene.aruco_scene.places), 2)
+
+ # Check ArUco scene places
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_scene.places['A'].translation, [1, 0, 0]))
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_scene.places['A'].rotation, [0, 0, 0]))
+ self.assertEqual(ar_scene.aruco_scene.places['A'].marker.identifier, 0)
+
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_scene.places['B'].translation, [0, 1, 0]))
+ self.assertIsNone(numpy.testing.assert_array_equal(ar_scene.aruco_scene.places['B'].rotation, [0, 90, 0]))
+ self.assertEqual(ar_scene.aruco_scene.places['B'].marker.identifier, 1)
+
+ # Check AOI scene
+ self.assertEqual(len(ar_scene.aoi_scene.items()), 1)
+ self.assertEqual(ar_scene.aoi_scene['Test'].size, 4)
+
+if __name__ == '__main__':
+
+ unittest.main() \ No newline at end of file
diff --git a/src/argaze/ArGazeScene.py b/src/argaze/ArScene.py
index 0eb4ebc..0a88b0c 100644
--- a/src/argaze/ArGazeScene.py
+++ b/src/argaze/ArScene.py
@@ -10,11 +10,11 @@ from argaze.AreaOfInterest import *
import numpy
-ArGazeSceneType = TypeVar('ArGazeScene', bound="ArGazeScene")
+ArSceneType = TypeVar('ArScene', bound="ArScene")
# Type definition for type annotation convenience
@dataclass
-class ArGazeScene():
+class ArScene():
"""Define an Augmented Reality environnement thanks to ArUco markers and project it onto incoming frames."""
name: str
@@ -74,7 +74,7 @@ class ArGazeScene():
self.__dict__.update(kwargs)
@classmethod
- def from_json(self, json_filepath: str) -> ArGazeSceneType:
+ def from_json(self, json_filepath: str) -> ArSceneType:
"""Load ArGaze project from .json file."""
with open(json_filepath) as configuration_file:
@@ -82,7 +82,7 @@ class ArGazeScene():
# Store current directory to allow relative path loading
self.__current_directory = os.path.dirname(os.path.abspath(json_filepath))
- return ArGazeScene(**json.load(configuration_file))
+ return ArScene(**json.load(configuration_file))
def __str__(self) -> str:
"""String display"""
@@ -95,8 +95,8 @@ class ArGazeScene():
return output
- def project(self, frame, valid_markers:int = 1, visual_hfov=0):
- """Project ArGazeScene into frame."""
+ def project(self, frame, consistent_markers_number:int = 1, visual_hfov=0):
+ """Project ArScene into frame."""
# Track markers with pose estimation and draw them
self.aruco_tracker.track(frame)
@@ -107,17 +107,17 @@ class ArGazeScene():
raise UserWarning('No marker detected')
# Estimate set pose from tracked markers
- tvec, rvec, success, validity, unvalid = self.aruco_scene.estimate_pose(self.aruco_tracker.tracked_markers)
+ tvec, rvec, success, consistent_markers, unconsistencies = self.aruco_scene.estimate_pose(self.aruco_tracker.tracked_markers)
# When pose estimation fails, ignore AOI scene projection
if not success:
raise UserWarning('Pose estimation fails')
- # Consider pose estimation only if it is validated by a given number of valid markers at least
- elif validity >= valid_markers:
+ # Consider pose estimation only if theer is a given number of consistent markers at least
+ elif len(consistent_markers) >= consistent_markers_number:
- # Clip AOI out of the horizontal visual field of view (optional)
+ # Clip AOI out of the visual horizontal field of view (optional)
if visual_hfov > 0:
# Transform scene into camera referential
@@ -145,4 +145,4 @@ class ArGazeScene():
raise UserWarning('AOI projection is empty')
- return aoi_scene_projection, unvalid
+ return aoi_scene_projection, unconsistencies
diff --git a/src/argaze/ArUcoMarkers/ArUcoScene.py b/src/argaze/ArUcoMarkers/ArUcoScene.py
index 857ebf4..b267102 100644
--- a/src/argaze/ArUcoMarkers/ArUcoScene.py
+++ b/src/argaze/ArUcoMarkers/ArUcoScene.py
@@ -77,7 +77,7 @@ class ArUcoScene():
self._translation = numpy.zeros(3)
self._rotation = numpy.zeros(3)
self._succeded = False
- self._validity = 0
+ self._consistent_markers = 0
# Process markers ids to speed up further calculations
self.__identifier_cache = {}
@@ -308,7 +308,7 @@ class ArUcoScene():
I = numpy.identity(3, dtype = R.dtype)
return numpy.linalg.norm(I - numpy.dot(R.T, R)) < 1e-6
- def __normalise_place_pose(self, name, place, F):
+ def __normalise_marker_pose(self, name, place, F):
# Transform place rotation into scene rotation vector
R = self.__rotation_cache[name]
@@ -328,73 +328,73 @@ class ArUcoScene():
return rvec, tvec
def estimate_pose(self, tracked_markers) -> Tuple[numpy.array, numpy.array, bool, int, dict]:
- """Estimate scene pose from tracked markers (cf ArUcoTracker.track())
+ """Estimate scene pose from tracked markers (cf ArUcoTracker.track()) and validate its consistency according expected scene places.
* **Returns:**
- - translation vector
- - rotation vector
- - pose estimation success status
- - the number of places used to estimate the pose as validity score
- - dict of non valid distance and angle
+ - scene translation vector
+ - scene rotation vector
+ - scene pose estimation success status
+ - all tracked markers considered as consistent and used to estimate the pose
+ - dict of identified distance or angle unconsistencies and out-of-bounds values
"""
# Init pose data
self._translation = numpy.zeros(3)
self._rotation = numpy.zeros(3)
self._succeded = False
- self._validity = 0
- self._unvalid = {}
+ self._consistent_markers = {}
+ self._unconsistencies = {}
# Don't try to estimate pose if there is no tracked markers
if len(tracked_markers) == 0:
- return self._translation, self._rotation, self._succeded, self._validity, self._unvalid
+ return self._translation, self._rotation, self._succeded, self._consistent_markers, self._unconsistencies
- # Look for places related to tracked markers
- tracked_places = {}
+ # Look for tracked markers which belong to the scene and store them by name
+ scene_markers = {}
for (marker_id, marker) in tracked_markers.items():
try:
name = self.__identifier_cache[marker_id]
- tracked_places[name] = marker
+ scene_markers[name] = marker
except KeyError:
continue
#print('-------------- ArUcoScene pose estimation --------------')
- # Pose validity checking is'nt possible when only one place of the scene is tracked
- if len(tracked_places.keys()) == 1:
+ # Pose consistency checking is'nt possible when only one marker is tracked
+ if len(scene_markers) == 1:
- # Get scene pose from to the unique place pose
- name, place = tracked_places.popitem()
- F, _ = cv.Rodrigues(place.rotation)
+ # Get scene pose from to the unique marker
+ name, marker = scene_markers.popitem()
+ F, _ = cv.Rodrigues(marker.rotation)
- self._rotation, self._translation = self.__normalise_place_pose(name, place, F)
+ self._rotation, self._translation = self.__normalise_marker_pose(name, marker, F)
self._succeded = True
- self._validity = 1
+ self._consistent_markers[name] = marker
#print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
#print(f'ArUcoScene rotation vector: {self._rotation[0][0]:3f} {self._rotation[1][0]:3f} {self._rotation[2][0]:3f}')
#print(f'ArUcoScene translation vector: {self._translation[0]:3f} {self._translation[1]:3f} {self._translation[2]:3f}')
- # Pose validity checking processes places two by two
+ # Pose consistency checking processes markers two by two
else:
- valid_places = []
- valid_rvecs = []
- valid_tvecs = []
+ consistent_markers = []
+ consistent_rvecs = []
+ consistent_tvecs = []
- for (A_name, A_place), (B_name, B_place) in itertools.combinations(tracked_places.items(), 2):
+ for (A_name, A_marker), (B_name, B_marker) in itertools.combinations(scene_markers.items(), 2):
#print(f'** {A_name} > {B_name}')
- # Get place rotation estimation
+ # Get marker rotation estimation
# Use rotation matrix instead of rotation vector
- A, _ = cv.Rodrigues(A_place.rotation)
- B, _ = cv.Rodrigues(B_place.rotation)
+ A, _ = cv.Rodrigues(A_marker.rotation)
+ B, _ = cv.Rodrigues(B_marker.rotation)
- # Rotation matrix from A place to B place
+ # Rotation matrix from A marker to B marker
AB = B.dot(A.T)
assert(self.__is_rotation_matrix(AB))
@@ -403,102 +403,102 @@ class ArUcoScene():
angle = numpy.rad2deg(numpy.arccos((numpy.trace(AB) - 1) / 2))
expected_angle = self.__angle_cache[A_name][B_name]
- # Calculate distance between A place center and B place center
- distance = numpy.linalg.norm(A_place.translation - B_place.translation)
+ # Calculate distance between A marker center and B marker center
+ distance = numpy.linalg.norm(A_marker.translation - B_marker.translation)
expected_distance = self.__distance_cache[A_name][B_name]
- # Check angle and distance according given tolerance then normalise place pose
- valid_angle = math.isclose(angle, expected_angle, abs_tol=self.angle_tolerance)
- valid_distance = math.isclose(distance, expected_distance, abs_tol=self.distance_tolerance)
+ # Check angle and distance according given tolerance then normalise marker pose
+ consistent_angle = math.isclose(angle, expected_angle, abs_tol=self.angle_tolerance)
+ consistent_distance = math.isclose(distance, expected_distance, abs_tol=self.distance_tolerance)
- if valid_angle and valid_distance:
+ if consistent_angle and consistent_distance:
- if A_name not in valid_places:
+ if A_name not in consistent_markers:
- # Remember this place is already validated
- valid_places.append(A_name)
+ # Remember this marker is already validated
+ consistent_markers.append(A_name)
- rvec, tvec = self.__normalise_place_pose(A_name, A_place, A)
+ rvec, tvec = self.__normalise_marker_pose(A_name, A_marker, A)
- # Store normalised place pose
- valid_rvecs.append(rvec)
- valid_tvecs.append(tvec)
+ # Store normalised marker pose
+ consistent_rvecs.append(rvec)
+ consistent_tvecs.append(tvec)
- if B_name not in valid_places:
+ if B_name not in consistent_markers:
- # Remember this place is already validated
- valid_places.append(B_name)
+ # Remember this marker is already validated
+ consistent_markers.append(B_name)
- rvec, tvec = self.__normalise_place_pose(B_name, B_place, B)
+ rvec, tvec = self.__normalise_marker_pose(B_name, B_marker, B)
- # Store normalised place pose
- valid_rvecs.append(rvec)
- valid_tvecs.append(tvec)
+ # Store normalised marker pose
+ consistent_rvecs.append(rvec)
+ consistent_tvecs.append(tvec)
else:
- if not valid_angle:
- self._unvalid[f'{A_name}/{B_name} angle'] = angle
+ if not consistent_angle:
+ self._unconsistencies[f'{A_name}/{B_name} angle'] = angle
- if not valid_distance:
- self._unvalid[f'{A_name}/{B_name} distance'] = distance
+ if not consistent_distance:
+ self._unconsistencies[f'{A_name}/{B_name} distance'] = distance
- if len(valid_places) > 1:
+ if len(consistent_markers) > 1:
- # Consider ArUcoScene rotation as the mean of all valid translations
+ # Consider ArUcoScene rotation as the mean of all consistent translations
# !!! WARNING !!! This is a bad hack : processing rotations average is a very complex problem that needs to well define the distance calculation method before.
- self._rotation = numpy.mean(numpy.array(valid_rvecs), axis=0)
+ self._rotation = numpy.mean(numpy.array(consistent_rvecs), axis=0)
- # Consider ArUcoScene translation as the mean of all valid translations
- self._translation = numpy.mean(numpy.array(valid_tvecs), axis=0)
+ # Consider ArUcoScene translation as the mean of all consistent translations
+ self._translation = numpy.mean(numpy.array(consistent_tvecs), axis=0)
#print(':::::::::::::::::::::::::::::::::::::::::::::::::::')
#print(f'ArUcoScene rotation vector: {self._rotation[0][0]:3f} {self._rotation[1][0]:3f} {self._rotation[2][0]:3f}')
#print(f'ArUcoScene translation vector: {self._translation[0]:3f} {self._translation[1]:3f} {self._translation[2]:3f}')
self._succeded = True
- self._validity = len(valid_places)
+ self._consistent_markers = consistent_markers
else:
- unvalid_rvecs = []
- unvalid_tvecs = []
+ unconsistent_rvecs = []
+ unconsistent_tvecs = []
- # Gather unvalid pose estimations
- for name, place in tracked_places.items():
+ # Gather unconsistent pose estimations
+ for name, marker in scene_markers.items():
- if name not in valid_places:
+ if name not in consistent_markers:
- R, _ = cv.Rodrigues(place.rotation)
- rvec, tvec = self.__normalise_place_pose(name, place, R)
+ R, _ = cv.Rodrigues(marker.rotation)
+ rvec, tvec = self.__normalise_marker_pose(name, marker, R)
- unvalid_rvecs = [rvec]
- unvalid_tvecs = [tvec]
+ unconsistent_rvecs = [rvec]
+ unconsistent_tvecs = [tvec]
- # Consider ArUcoScene rotation as the mean of all unvalid translations
+ # Consider ArUcoScene rotation as the mean of all unconsistent translations
# !!! WARNING !!! This is a bad hack : processing rotations average is a very complex problem that needs to well define the distance calculation method before.
- self._rotation = numpy.mean(numpy.array(unvalid_rvecs), axis=0)
+ self._rotation = numpy.mean(numpy.array(unconsistent_rvecs), axis=0)
- # Consider ArUcoScene translation as the mean of all unvalid translations
- self._translation = numpy.mean(numpy.array(unvalid_tvecs), axis=0)
+ # Consider ArUcoScene translation as the mean of all unconsistent translations
+ self._translation = numpy.mean(numpy.array(unconsistent_tvecs), axis=0)
#print(':::::::::::::::::::::::::::::::::::::::::::::::::::')
#print(f'ArUcoScene rotation vector: {self._rotation[0][0]:3f} {self._rotation[1][0]:3f} {self._rotation[2][0]:3f}')
#print(f'ArUcoScene translation vector: {self._translation[0]:3f} {self._translation[1]:3f} {self._translation[2]:3f}')
self._succeded = False
- self._validity = len(tracked_places)
+ self._consistent_markers = {}
#print('----------------------------------------------------')
- return self._translation, self._rotation, self._succeded, self._validity, self._unvalid
+ return self._translation, self._rotation, self._succeded, self._consistent_markers, self._unconsistencies
@property
def translation(self) -> numpy.array:
"""Access to scene translation vector.
.. warning::
- Setting scene translation vector implies succeded status to be True and validity score to be 0."""
+ Setting scene translation vector implies succeded status to be True and consistency score to be 0."""
return self._translation
@@ -507,14 +507,14 @@ class ArUcoScene():
self._translation = tvec
self._succeded = True
- self._validity = 0
+ self._consistent_markers = 0
@property
def rotation(self) -> numpy.array:
"""Access to scene rotation vector.
.. warning::
- Setting scene rotation vector implies succeded status to be True and validity score to be 0."""
+ Setting scene rotation vector implies succeded status to be True and consistency score to be 0."""
return self._translation
@@ -523,7 +523,7 @@ class ArUcoScene():
self._rotation = rvec
self._succeded = True
- self._validity = 0
+ self._consistent_markers = 0
@property
def succeded(self) -> bool:
@@ -532,10 +532,10 @@ class ArUcoScene():
return self._succeded
@property
- def validity(self) -> int:
- """Access to scene pose estimation validity score."""
+ def consistency(self) -> int:
+ """Access to scene pose estimation consistency score."""
- return self._validity
+ return len(self._consistent_markers)
def draw(self, frame, K, D, draw_places=True):
"""Draw scene axis and places."""
@@ -543,9 +543,9 @@ class ArUcoScene():
l = self.__marker_size / 2
ll = self.__marker_size
- # Select color according validity score
- n = 95 * self._validity if self._validity < 2 else 0
- f = 159 * self._validity if self._validity < 2 else 255
+ # Select color according consistency score
+ n = 95 * self.consistency if self.consistency < 2 else 0
+ f = 159 * self.consistency if self.consistency < 2 else 255
try:
@@ -584,5 +584,5 @@ class ArUcoScene():
print(self._translation)
print(self._rotation)
print(self._succeded)
- print(self._validity)
+ print(self._consistent_markers)
print(axisPoints)
diff --git a/src/argaze/__init__.py b/src/argaze/__init__.py
index 1e1b5bb..f02a31a 100644
--- a/src/argaze/__init__.py
+++ b/src/argaze/__init__.py
@@ -2,4 +2,4 @@
.. include:: ../../README.md
"""
__docformat__ = "restructuredtext"
-__all__ = ['utils','ArUcoMarkers','AreaOfInterest','GazeFeatures','DataStructures','GazeAnalysis','ArGazeScene','TobiiGlassesPro2'] \ No newline at end of file
+__all__ = ['utils','ArUcoMarkers','AreaOfInterest','GazeFeatures','DataStructures','GazeAnalysis','ArScene','TobiiGlassesPro2'] \ No newline at end of file
diff --git a/src/argaze/utils/tobii_segment_argaze_scene_export.py b/src/argaze/utils/tobii_segment_arscene_export.py
index a038e34..7bbef59 100644
--- a/src/argaze/utils/tobii_segment_argaze_scene_export.py
+++ b/src/argaze/utils/tobii_segment_arscene_export.py
@@ -98,13 +98,16 @@ def main():
# Access to video timestamp data buffer
tobii_ts_vts = tobii_segment_data['VideoTimeStamp']
+ # Access to timestamped gaze position data buffer
+ tobii_ts_gaze_positions = tobii_segment_data['GazePosition']
+
# Prepare video exportation at the same format than segment video
output_video = TobiiVideo.TobiiVideoOutput(vs_video_filepath, tobii_segment_video.stream)
- # Load argaze project
- argaze_scene = ArGazeScene.ArGazeScene.from_json(args.project_path)
+ # Load ar scene
+ ar_scene = ArScene.ArScene.from_json(args.project_path)
- print(argaze_scene)
+ print(ar_scene)
# Create timestamped buffer to store AOIs and primary time stamp offset
ts_offset_aois = DataStructures.TimeStampedBuffer()
@@ -132,18 +135,18 @@ def main():
# Get nearest video timestamp
_, nearest_vts = tobii_ts_vts.get_last_before(video_ts)
- projected_aois['offset'] = nearest_vts
+ projected_aois['offset'] = nearest_vts.offset
# Hide frame left and right borders before tracking to ignore markers outside focus area
cv.rectangle(video_frame.matrix, (0, 0), (int(video_frame.width/6), int(video_frame.height)), (0, 0, 0), -1)
cv.rectangle(video_frame.matrix, (int(video_frame.width*(1 - 1/6)), 0), (int(video_frame.width), int(video_frame.height)), (0, 0, 0), -1)
# Project scene into frame
- scene_projection, unvalid = argaze_scene.project(video_frame.matrix, valid_markers=1, visual_hfov=TobiiSpecifications.VISUAL_HFOV)
+ scene_projection, unconsistencies = ar_scene.project(video_frame.matrix, consistent_markers_number=1, visual_hfov=TobiiSpecifications.VISUAL_HFOV)
- # DEBUG: print unvalid distances or angles
- for key, value in unvalid.items():
- print(f'{video_ts}: Unvalid {key}: {value}.')
+ # DEBUG: print unconsistencies distances or angles
+ for key, value in unconsistencies.items():
+ print(f'{video_ts}: Unconsistent {key}: {value}')
# Store all projected aoi
for aoi_name in scene_projection.keys():
@@ -151,7 +154,7 @@ def main():
projected_aois[aoi_name] = numpy.rint(scene_projection[aoi_name]).astype(int)
# Draw tracked markers
- argaze_scene.aruco_tracker.draw_tracked_markers(visu_frame.matrix)
+ ar_scene.aruco_tracker.draw_tracked_markers(visu_frame.matrix)
# Draw scene projection
scene_projection.draw(visu_frame.matrix, (0, 0), color=(0, 255, 255))
@@ -159,10 +162,10 @@ def main():
# Catch warnings raised by project_scene method
except UserWarning as w:
- projected_aois['warning'] = w
+ projected_aois['comment'] = w
# Draw tracked markers
- argaze_scene.aruco_tracker.draw_tracked_markers(visu_frame.matrix)
+ ar_scene.aruco_tracker.draw_tracked_markers(visu_frame.matrix)
if w == 'Pose estimation fails':
@@ -174,7 +177,14 @@ def main():
# Raised when timestamped buffer is empty
except KeyError as e:
- pass
+
+ e = 'VideoTimeStamp missing'
+
+ projected_aois['offset'] = 0
+ projected_aois['comment'] = e
+
+ cv.rectangle(visu_frame.matrix, (0, 50), (550, 100), (127, 127, 127), -1)
+ cv.putText(visu_frame.matrix, str(e), (20, 80), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1, cv.LINE_AA)
# Store projected AOI
ts_offset_aois[video_ts] = projected_aois
@@ -218,7 +228,7 @@ def main():
# Print aruco tracking metrics
print('\nAruco marker tracking metrics')
- try_count, tracked_counts = argaze_scene.aruco_tracker.track_metrics
+ try_count, tracked_counts = ar_scene.aruco_tracker.track_metrics
for marker_id, tracked_count in tracked_counts.items():
print(f'Markers {marker_id} has been detected in {tracked_count} / {try_count} frames ({round(100 * tracked_count / try_count, 2)} %)')