aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/use_cases/air_controller_gaze_study/pipeline.md4
-rw-r--r--src/argaze/ArFeatures.py41
-rw-r--r--src/argaze/ArUcoMarker/ArUcoCamera.py94
-rw-r--r--src/argaze/__main__.py3
4 files changed, 80 insertions, 62 deletions
diff --git a/docs/use_cases/air_controller_gaze_study/pipeline.md b/docs/use_cases/air_controller_gaze_study/pipeline.md
index b1df62a..52d8cac 100644
--- a/docs/use_cases/air_controller_gaze_study/pipeline.md
+++ b/docs/use_cases/air_controller_gaze_study/pipeline.md
@@ -357,10 +357,10 @@ The video file is a record of the sector screen frame image.
This file contains the logs of *ArUcoCamera.look* method execution info. It is created into an *_export* folder from where the [*load* command](../../user_guide/utils/main_commands.md) is launched.
-On a MacBookPro (2,3GHz Intel Core i9 8 cores), the *look* method execution time is ~5,6ms and it is called ~163 times per second.
+On a MacBookPro (2,3GHz Intel Core i9 8 cores), the *look* method execution time is ~3,4ms and it is called ~43 times per second.
## watch_performance.csv
This file contains the logs of *ArUcoCamera.watch* method execution info. It is created into an *_export* folder from where the [*load* command](../../user_guide/utils/main_commands.md) is launched.
-On a MacBookPro (2,3GHz Intel Core i9 8 cores), the *watch* method execution time is ~52ms and it is called ~11,8 times per second.
+On a MacBookPro (2,3GHz Intel Core i9 8 cores) without CUDA acceleration, the *watch* method execution time is ~56ms and it is called ~11 times per second.
diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py
index 4515ae1..b05cfba 100644
--- a/src/argaze/ArFeatures.py
+++ b/src/argaze/ArFeatures.py
@@ -1176,14 +1176,16 @@ class ArCamera(ArFrame):
for layer_name, layer in self.layers.items():
- # Initialize layer if needed
- if layer.aoi_scene is None:
+ with layer._lock:
- layer.aoi_scene = AOI2DScene.AOI2DScene()
+ # Initialize layer if needed
+ if layer.aoi_scene is None:
- else:
+ layer.aoi_scene = AOI2DScene.AOI2DScene()
+
+ else:
- layer.aoi_scene.clear()
+ layer.aoi_scene.clear()
def _write_projection_cache(self, timestamp: int|float, exception = None):
"""Write layers aoi scene into the projection cache.
@@ -1493,6 +1495,7 @@ class ArContext(DataFeatures.PipelineStepObject):
# Init private attributes
self.__pipeline = None
self.__exceptions = DataFeatures.TimestampedExceptions()
+ self.__gaze_positions_buffer = GazeFeatures.TimeStampedGazePositions()
# Init protected attributes
self._stop_event = threading.Event()
@@ -1543,23 +1546,33 @@ class ArContext(DataFeatures.PipelineStepObject):
if issubclass(type(self.__pipeline), ArFrame):
- try:
+ # Edit gaze position
+ if x is None and y is None:
- if x is None and y is None:
+ gaze_position = GazeFeatures.GazePosition(timestamp=timestamp)
- # Edit empty gaze position
- self.__pipeline.look(GazeFeatures.GazePosition(timestamp=timestamp))
+ else:
- else:
+ gaze_position = GazeFeatures.GazePosition((x, y), precision=precision, timestamp=timestamp)
+
+ # Buffer gaze position
+ self.__gaze_positions_buffer.append(gaze_position)
+
+ # Process all buffered gaze positions while the pipeline is available
+ while not self.__pipeline.busy() and self.__gaze_positions_buffer:
+
+ gaze_position = self.__gaze_positions_buffer.pop(0)
+
+ try:
# Edit gaze position
- self.__pipeline.look(GazeFeatures.GazePosition((x, y), precision=precision, timestamp=timestamp))
+ self.__pipeline.look(gaze_position)
- except DataFeatures.TimestampedException as e:
+ except DataFeatures.TimestampedException as e:
- logging.warning('%s._process_gaze_position: %s', DataFeatures.get_class_path(self), e)
+ logging.warning('%s._process_gaze_position: %s', DataFeatures.get_class_path(self), e)
- self.__exceptions.append(e)
+ self.__exceptions.append(e)
else:
diff --git a/src/argaze/ArUcoMarker/ArUcoCamera.py b/src/argaze/ArUcoMarker/ArUcoCamera.py
index 8ae8cb8..4fa8b83 100644
--- a/src/argaze/ArUcoMarker/ArUcoCamera.py
+++ b/src/argaze/ArUcoMarker/ArUcoCamera.py
@@ -119,61 +119,63 @@ class ArUcoCamera(ArFeatures.ArCamera):
logging.debug('ArUcoCamera.watch')
- # Use camera frame lock feature
- with self._lock:
+ # Draw black rectangles to mask sides
+ if self.__sides_mask > 0:
+
+ logging.debug('\t> drawing sides mask (%i px)', self.__sides_mask)
- # Draw black rectangles to mask sides
- if self.__sides_mask > 0:
- logging.debug('\t> drawing sides mask (%i px)', self.__sides_mask)
+ height, width, _ = image.shape
- height, width, _ = image.shape
+ cv2.rectangle(image, (0, 0), (self.__sides_mask, height), (0, 0, 0), -1)
+ cv2.rectangle(image, (width - self.__sides_mask, 0), (width, height), (0, 0, 0), -1)
- cv2.rectangle(image, (0, 0), (self.__sides_mask, height), (0, 0, 0), -1)
- cv2.rectangle(image, (width - self.__sides_mask, 0), (width, height), (0, 0, 0), -1)
+ # Fill camera frame background with timestamped image
+ with self._lock:
- # Fill camera frame background with timestamped image
self.background = image
- # Read projection from the cache if required
- if not self._read_projection_cache(image.timestamp):
+ # Read projection from the cache if required
+ if not self._read_projection_cache(image.timestamp):
- # Detect aruco markers
- logging.debug('\t> detect markers')
+ # Detect aruco markers
+ logging.debug('\t> detect markers')
- self.__aruco_detector.detect_markers(image)
+ self.__aruco_detector.detect_markers(image)
- # Clear former layers projection into camera frame
- self._clear_projection()
+ # Clear former layers projection into camera frame
+ self._clear_projection()
- # Project each aoi 3d scene into camera frame
- for scene_name, scene in self.scenes.items():
+ # Project each aoi 3d scene into camera frame
+ for scene_name, scene in self.scenes.items():
- ''' TODO: Enable aruco_aoi processing
- if scene.aruco_aoi:
+ ''' TODO: Enable aruco_aoi processing
+ if scene.aruco_aoi:
- try:
+ try:
- # Build AOI scene directly from detected ArUco marker corners
- self.layers[??].aoi_2d_scene |= scene.build_aruco_aoi_scene(self.__aruco_detector.detected_markers())
+ # Build AOI scene directly from detected ArUco marker corners
+ self.layers[??].aoi_2d_scene |= scene.build_aruco_aoi_scene(self.__aruco_detector.detected_markers())
- except ArFeatures.PoseEstimationFailed:
+ except ArFeatures.PoseEstimationFailed:
- pass
- '''
+ pass
+ '''
- # Estimate scene pose from detected scene markers
- logging.debug('\t> estimate %s scene pose', scene_name)
+ # Estimate scene pose from detected scene markers
+ logging.debug('\t> estimate %s scene pose', scene_name)
- try:
+ try:
+
+ tvec, rmat, _ = scene.estimate_pose(self.__aruco_detector.detected_markers(), timestamp=image.timestamp)
- tvec, rmat, _ = scene.estimate_pose(self.__aruco_detector.detected_markers(), timestamp=image.timestamp)
+ # Project scene into camera frame according estimated pose
+ for layer_name, layer_projection in scene.project(tvec, rmat, self.visual_hfov, self.visual_vfov, timestamp=image.timestamp):
- # Project scene into camera frame according estimated pose
- for layer_name, layer_projection in scene.project(tvec, rmat, self.visual_hfov, self.visual_vfov, timestamp=image.timestamp):
+ logging.debug('\t> project %s scene %s layer', scene_name, layer_name)
- logging.debug('\t> project %s scene %s layer', scene_name, layer_name)
+ try:
- try:
+ with self.layers[layer_name]._lock:
# Update camera layer aoi
self.layers[layer_name].aoi_scene |= layer_projection
@@ -181,23 +183,25 @@ class ArUcoCamera(ArFeatures.ArCamera):
# Timestamp camera layer
self.layers[layer_name].timestamp = image.timestamp
- except KeyError:
+ except KeyError:
+
+ pass
- pass
+ # Write projection into the cache if required
+ self._write_projection_cache(image.timestamp)
- # Write projection into the cache if required
- self._write_projection_cache(image.timestamp)
+ except DataFeatures.TimestampedException as e:
- except DataFeatures.TimestampedException as e:
+ # Write exception into the cache if required
+ self._write_projection_cache(image.timestamp, e)
- # Write exception into the cache if required
- self._write_projection_cache(image.timestamp, e)
+ # Raise exception
+ raise e
- # Raise exception
- raise e
+ # Copy camera frame background into scene frames background if required
+ if self.copy_background_into_scenes_frames:
- # Copy camera frame background into scene frames background if required
- if self.copy_background_into_scenes_frames:
+ with self._lock:
self._copy_background_into_scenes_frames()
diff --git a/src/argaze/__main__.py b/src/argaze/__main__.py
index c65d6e5..e4363ca 100644
--- a/src/argaze/__main__.py
+++ b/src/argaze/__main__.py
@@ -182,7 +182,7 @@ def load_context(args):
pass
# Key interaction
- key_pressed = cv2.waitKey(40)
+ key_pressed = cv2.waitKey( int(1000 / args.fps) )
#print("key_pressed", key_pressed)
# f: disable/enable pipeline drawing
@@ -323,6 +323,7 @@ parser_load.add_argument('context_file', metavar='CONTEXT_FILE', type=str, help=
parser_load.add_argument('-v', '--verbose', action='store_true', default=False, help='enable verbose mode to print information in console')
parser_load.add_argument('-p', '--pipe_path', metavar='PIPE_PATH', type=str, default=None, help='enable pipe communication to execute external commands')
parser_load.add_argument('-x', '--display', metavar='DISPLAY', nargs="+", type=int, default=None, help='adapt windows to display dimension')
+parser_load.add_argument('-f', '--fps', metavar='FPS', type=int, default=15, help='set window fps')
parser_load.add_argument('--no-window', action='store_true', default=False, help='disable window mode')
parser_load.set_defaults(func=load_context)