aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/user_guide/aruco_markers_pipeline/advanced_topics/aruco_detector_configuration.md1
-rw-r--r--docs/user_guide/aruco_markers_pipeline/advanced_topics/optic_parameters_calibration.md3
-rw-r--r--src/argaze/ArFeatures.py6
-rw-r--r--src/argaze/ArUcoMarkers/ArUcoDetector.py27
-rw-r--r--src/argaze/ArUcoMarkers/ArUcoMarker.py18
-rw-r--r--src/argaze/DataFeatures.py38
6 files changed, 59 insertions, 34 deletions
diff --git a/docs/user_guide/aruco_markers_pipeline/advanced_topics/aruco_detector_configuration.md b/docs/user_guide/aruco_markers_pipeline/advanced_topics/aruco_detector_configuration.md
index 50d6c0e..410e2d7 100644
--- a/docs/user_guide/aruco_markers_pipeline/advanced_topics/aruco_detector_configuration.md
+++ b/docs/user_guide/aruco_markers_pipeline/advanced_topics/aruco_detector_configuration.md
@@ -15,7 +15,6 @@ Here is an extract from the JSON [ArUcoCamera](../../../argaze.md/#argaze.ArUcoM
"size": [1920, 1080],
"aruco_detector": {
"dictionary": "DICT_APRILTAG_16h5",
- "marker_size": 5,
"parameters": {
"adaptiveThreshConstant": 10,
"useAruco3Detection": 1
diff --git a/docs/user_guide/aruco_markers_pipeline/advanced_topics/optic_parameters_calibration.md b/docs/user_guide/aruco_markers_pipeline/advanced_topics/optic_parameters_calibration.md
index a3e9fc7..148a910 100644
--- a/docs/user_guide/aruco_markers_pipeline/advanced_topics/optic_parameters_calibration.md
+++ b/docs/user_guide/aruco_markers_pipeline/advanced_topics/optic_parameters_calibration.md
@@ -55,7 +55,7 @@ aruco_optic_calibrator = ArUcoOpticCalibrator.ArUcoOpticCalibrator()
expected_aruco_board = ArUcoBoard.ArUcoBoard(7, 5, 5, 3, aruco_dictionary)
# Create ArUco detector
-aruco_detector = ArUcoDetector.ArUcoDetector(dictionary=aruco_dictionary, marker_size=3)
+aruco_detector = ArUcoDetector.ArUcoDetector(dictionary=aruco_dictionary)
# Assuming that live Full HD (1920x1080) video stream is enabled
...
@@ -144,7 +144,6 @@ Here is an extract from the JSON [ArUcoCamera](../../../argaze.md/#argaze.ArUcoM
"size": [1920, 1080],
"aruco_detector": {
"dictionary": "DICT_APRILTAG_16h5",
- "marker_size": 5,
"optic_parameters": {
"rms": 0.6688921504088245,
"dimensions": [
diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py
index 0062c53..5951c95 100644
--- a/src/argaze/ArFeatures.py
+++ b/src/argaze/ArFeatures.py
@@ -163,7 +163,7 @@ class ArLayer(DataFeatures.SharedObject, DataFeatures.PipelineStepObject):
for name, analyzer in self.__aoi_scan_path_analyzers.items():
analyzer.parent = self
-
+
@property
def aoi_scene(self) -> AOIFeatures.AOIScene:
"""Get layer's aoi scene object."""
@@ -574,7 +574,7 @@ class ArFrame(DataFeatures.SharedObject, DataFeatures.PipelineStepObject):
for name, layer in self.__layers.items():
layer.parent = self
-
+
@property
def size(self) -> tuple[int]:
"""Get frame's size."""
@@ -1111,7 +1111,7 @@ class ArScene(DataFeatures.PipelineStepObject):
for name, frame in self.__frames.items():
frame.parent = self
-
+
@property
def layers(self) -> dict:
"""Get scene's layers dictionary."""
diff --git a/src/argaze/ArUcoMarkers/ArUcoDetector.py b/src/argaze/ArUcoMarkers/ArUcoDetector.py
index d326aaa..8c843ae 100644
--- a/src/argaze/ArUcoMarkers/ArUcoDetector.py
+++ b/src/argaze/ArUcoMarkers/ArUcoDetector.py
@@ -131,21 +131,13 @@ class DetectorParameters():
return self.__parameters
class ArUcoDetector(DataFeatures.PipelineStepObject):
- """ArUco markers detector.
+ """OpenCV ArUco library wrapper."""
- Parameters:
- dictionary: ArUco markers dictionary to detect.
- marker_size: Size of ArUco markers to detect in centimeter.
- optic_parameters: Optic parameters to use for ArUco detection into image.
- parameters: ArUco detector parameters.
- """
-
- def __init__(self, dictionary: ArUcoMarkersDictionary.ArUcoMarkersDictionary = None, marker_size: float = 0., optic_parameters: ArUcoOpticCalibrator.OpticParameters = None, parameters: DetectorParameters = None):
- """ Initialize ArUcoDetector.
+ def __init__(self, dictionary: ArUcoMarkersDictionary.ArUcoMarkersDictionary = None, optic_parameters: ArUcoOpticCalibrator.OpticParameters = None, parameters: DetectorParameters = None):
+ """Initialize ArUcoDetector.
Parameters:
dictionary: ArUco markers dictionary to detect.
- marker_size: Size of ArUco markers to detect in centimeter.
optic_parameters: Optic parameters to use for ArUco detection into image.
parameters: ArUco detector parameters.
"""
@@ -155,7 +147,6 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
# Init private attributes
self.__dictionary = dictionary
- self.__marker_size = marker_size
self.__optic_parameters = optic_parameters
self.__parameters = parameters
@@ -178,11 +169,6 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
return self.__dictionary
@property
- def marker_size(self) -> float:
- """Get aruco detector's marker size."""
- return self.__marker_size
-
- @property
def optic_parameters(self) -> ArUcoOpticCalibrator.OpticParameters:
"""Get aruco detector's opetic parameters object."""
return self.__optic_parameters
@@ -224,9 +210,6 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
new_dictionary = ArUcoMarkersDictionary.ArUcoMarkersDictionary(**dictionary_value)
- # Load ArUco marker size
- new_marker_size = aruco_detector_data.pop('marker_size')
-
# Load optic parameters
try:
optic_parameters_value = aruco_detector_data.pop('optic_parameters')
@@ -268,7 +251,7 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
new_parameters = DetectorParameters()
# Create aruco detector
- return ArUcoDetector(new_dictionary, new_marker_size, new_optic_parameters, new_parameters)
+ return ArUcoDetector(new_dictionary, new_optic_parameters, new_parameters)
@classmethod
def from_json(self, json_filepath: str) -> ArUcoDetectorType:
@@ -323,7 +306,7 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
for i, marker_id in enumerate(detected_markers_ids):
- marker = ArUcoMarker.ArUcoMarker(self.__dictionary, marker_id, self.__marker_size)
+ marker = ArUcoMarker.ArUcoMarker(self.__dictionary, marker_id)
marker.corners = detected_markers_corners[i][0]
# No pose estimation: call estimate_markers_pose to get one
diff --git a/src/argaze/ArUcoMarkers/ArUcoMarker.py b/src/argaze/ArUcoMarkers/ArUcoMarker.py
index 0f368f6..b626ea4 100644
--- a/src/argaze/ArUcoMarkers/ArUcoMarker.py
+++ b/src/argaze/ArUcoMarkers/ArUcoMarker.py
@@ -8,6 +8,7 @@ __copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)"
__license__ = "BSD"
from dataclasses import dataclass, field
+import math
from argaze.ArUcoMarkers import ArUcoMarkersDictionary
@@ -25,7 +26,7 @@ class ArUcoMarker():
identifier: int
"""Index into dictionary"""
- size: float
+ size: float = field(default=math.nan)
"""Size of marker in centimeters."""
corners: numpy.array = field(init=False, repr=False)
@@ -47,7 +48,13 @@ class ArUcoMarker():
return self.corners[0].mean(axis=0)
def image(self, dpi) -> numpy.array:
- """Create marker matrix image at a given resolution."""
+ """Create marker matrix image at a given resolution.
+
+ !!! warning
+ Marker size have to be setup before.
+ """
+
+ assert(not math.isnan(self.size))
dimension = round(self.size * dpi / 2.54) # 1 cm = 2.54 inches
matrix = numpy.zeros((dimension, dimension, 1), dtype="uint8")
@@ -63,6 +70,9 @@ class ArUcoMarker():
image: image where to draw
color: marker color (if None, no marker drawn)
draw_axes: enable marker axes drawing
+
+ !!! warning
+ draw_axes needs marker size and pose estimation.
"""
# Draw marker if required
@@ -70,8 +80,8 @@ class ArUcoMarker():
aruco.drawDetectedMarkers(image, [numpy.array([list(self.corners)])], numpy.array([self.identifier]), color)
- # Draw marker axes if pose has been estimated and if required
- if self.translation.size == 3 and self.rotation.size == 9 and draw_axes is not None:
+ # Draw marker axes if pose has been estimated, marker have a size and if required
+ if self.translation.size == 3 and self.rotation.size == 9 and not math.isnan(self.size) and draw_axes is not None:
cv2.drawFrameAxes(image, numpy.array(K), numpy.array(D), self.rotation, self.translation, self.size, **draw_axes)
diff --git a/src/argaze/DataFeatures.py b/src/argaze/DataFeatures.py
index 688ad4a..a3b7034 100644
--- a/src/argaze/DataFeatures.py
+++ b/src/argaze/DataFeatures.py
@@ -218,7 +218,6 @@ class TimeStampedBuffer(collections.OrderedDict):
raise KeyError(f'No data stored before {ts} timestamp.')
-
def get_last_until(self, ts) -> Tuple[TimeStampType, DataType]:
"""Retreive last item timestamp until a given timestamp value."""
@@ -410,6 +409,24 @@ class PipelineStepObject():
# parent attribute will be setup later by parent it self
self.__parent = None
+ def __enter__(self):
+ """At with statement start."""
+
+ # Start observers
+ for observer_name, observer in self.__observers.items():
+
+ observer.__enter__()
+
+ return self
+
+ def __exit__(self, type, value, traceback):
+ """At with statement end."""
+
+ # End observers
+ for observer_name, observer in self.__observers.items():
+
+ observer.__exit__(type, value, traceback)
+
@property
def name(self) -> str:
"""Get layer's name."""
@@ -441,7 +458,6 @@ class PipelineStepObject():
Returns:
object_data: dictionary with pipeline step object attributes values.
"""
-
return {
"name": self.__name,
"observers": self.__observers
@@ -655,3 +671,21 @@ class PipelineStepObserver():
!!! note
To subscribe to a method call, the inherited class simply needs to define 'on_<method_name>' functions with timestamp and object argument.
"""
+
+ def __enter__(self):
+ """
+ Define abstract __enter__ method to use observer as a context.
+
+ !!! warning
+ This method is called provided that the observed PipelineStepObject is created as a context using a with statement.
+ """
+ return self
+
+ def __exit__(self, type, value, traceback):
+ """
+ Define abstract __exit__ method to use observer as a context.
+
+ !!! warning
+ This method is called provided that the observed PipelineStepObject is created as a context using a with statement.
+ """
+ pass \ No newline at end of file