aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/user_guide/utils/demonstrations_scripts.md10
-rw-r--r--src/argaze/utils/contexts/OpenCV.py96
2 files changed, 103 insertions, 3 deletions
diff --git a/docs/user_guide/utils/demonstrations_scripts.md b/docs/user_guide/utils/demonstrations_scripts.md
index 68d3dff..22a6245 100644
--- a/docs/user_guide/utils/demonstrations_scripts.md
+++ b/docs/user_guide/utils/demonstrations_scripts.md
@@ -36,6 +36,16 @@ Load **opencv_movie_context.json** file to playback movie pictures and also capt
python -m argaze load ./src/argaze/utils/demo/opencv_movie_context.json
```
+## OpenCV camera context
+
+Edit **aruco_markers_pipeline.json** file as to adapt the *size* to the camera resolution and to reduce the value of the *sides_mask*.
+
+Then, load **opencv_camera_context.json** file to capture camera pictures and also capture cursor pointer positions over OpenCV window:
+
+```shell
+python -m argaze load ./src/argaze/utils/demo/opencv_camera_context.json
+```
+
## Tobii Pro Glasses 2
### Live stream context
diff --git a/src/argaze/utils/contexts/OpenCV.py b/src/argaze/utils/contexts/OpenCV.py
index ff3ed82..6859a0c 100644
--- a/src/argaze/utils/contexts/OpenCV.py
+++ b/src/argaze/utils/contexts/OpenCV.py
@@ -157,8 +157,6 @@ class Movie(Cursor):
if success:
- video_height, video_width, _ = image.shape
-
# Refresh once
self.__refresh = False
@@ -225,4 +223,96 @@ class Movie(Cursor):
else:
- return 0. \ No newline at end of file
+ return 0.
+
+class Camera(Cursor):
+ """Capture camera images and capture cursor position over OpenCV window.
+
+ !!! warning
+ It is assumed that an OpenCV window with the same name than the context is used to display context's pipeline image.
+ """
+ @DataFeatures.PipelineStepInit
+ def __init__(self, **kwargs):
+
+ # Init Cursor class
+ super().__init__()
+
+ # Init private attributes
+ self.__camera_id = None
+ self.__camera = None
+ self.__video_fps = None
+ self.__video_width = None
+ self.__video_height = None
+
+ @property
+ def identifier(self) -> int:
+ """Camera device id."""
+ return self.__camera_id
+
+ @identifier.setter
+ def identifier(self, camera_id: int):
+
+ self.__camera_id = camera_id
+
+ # Load movie
+ self.__camera = cv2.VideoCapture(self.__camera_id)
+ self.__video_fps = self.__camera.get(cv2.CAP_PROP_FPS)
+ self.__video_width = int(self.__camera.get(cv2.CAP_PROP_FRAME_WIDTH))
+ self.__video_height = int(self.__camera.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+ @DataFeatures.PipelineStepEnter
+ def __enter__(self):
+
+ logging.info('OpenCV.Movie context starts...')
+
+ # Enter in Cursor context
+ super().__enter__()
+
+ # Open reading thread
+ self.__reading_thread = threading.Thread(target=self.__read)
+
+ logging.debug('> starting reading thread...')
+ self.__reading_thread.start()
+
+ return self
+
+ def __read(self):
+ """Iterate on camera images."""
+
+ while self.is_running():
+
+ # Check pause event (and stop event)
+ while self.is_paused() and self.is_running():
+
+ logging.debug('> reading is paused at %i', current_image_time)
+
+ time.sleep(1)
+
+ # Select a new image
+ success, image = self.__camera.read()
+ image_time = self.__camera.get(cv2.CAP_PROP_POS_MSEC)
+
+ if success:
+
+ # Timestamp image
+ image = DataFeatures.TimestampedImage(image, timestamp=image_time)
+
+ # Process movie image
+ self._process_camera_image(timestamp=image_time, image=image)
+
+ # Wait
+ time.sleep(1 / self.__video_fps)
+
+ @DataFeatures.PipelineStepExit
+ def __exit__(self, exception_type, exception_value, exception_traceback):
+
+ logging.info('OpenCV.Movie context stops...')
+
+ # Exit from Cursor context
+ super().__exit__(exception_type, exception_value, exception_traceback)
+
+ # Close data capture
+ self.stop()
+
+ # Stop reading thread
+ threading.Thread.join(self.__reading_thread)