From 6bb8f307f67275543ec50b51fc98a19483b0c066 Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Tue, 28 Mar 2023 14:35:29 +0200 Subject: Making ArUcoDetector as dataclass. --- src/argaze.test/ArUcoMarkers/ArUcoDetector.py | 12 ++++ src/argaze/ArFeatures.py | 17 +++--- src/argaze/ArUcoMarkers/ArUcoDetector.py | 81 ++++++++------------------- 3 files changed, 44 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/argaze.test/ArUcoMarkers/ArUcoDetector.py b/src/argaze.test/ArUcoMarkers/ArUcoDetector.py index 3272f1c..5a45fad 100644 --- a/src/argaze.test/ArUcoMarkers/ArUcoDetector.py +++ b/src/argaze.test/ArUcoMarkers/ArUcoDetector.py @@ -42,6 +42,17 @@ class TestArUcoDetectorClass(unittest.TestCase): # Check ArUcoDetector creation self.assertEqual(aruco_detector.dictionary.name, 'DICT_ARUCO_ORIGINAL') + self.assertEqual(aruco_detector.marker_size, 3) + self.assertIsNone(numpy.testing.assert_array_equal(aruco_detector.camera.dimensions, [0, 0])) + self.assertEqual(aruco_detector.detected_markers_number, 0) + self.assertEqual(aruco_detector.detected_markers, {}) + + aruco_dictionary = ArUcoMarkersDictionary.ArUcoMarkersDictionary('DICT_APRILTAG_16h5') + aruco_detector = ArUcoDetector.ArUcoDetector(aruco_dictionary, 5.2) + + # Check ArUcoDetector creation + self.assertEqual(aruco_detector.dictionary.name, 'DICT_APRILTAG_16h5') + self.assertEqual(aruco_detector.marker_size, 5.2) self.assertIsNone(numpy.testing.assert_array_equal(aruco_detector.camera.dimensions, [0, 0])) self.assertEqual(aruco_detector.detected_markers_number, 0) self.assertEqual(aruco_detector.detected_markers, {}) @@ -58,6 +69,7 @@ class TestArUcoDetectorClass(unittest.TestCase): # Check ArUcoDetector creation self.assertEqual(aruco_detector.dictionary.name, 'DICT_ARUCO_ORIGINAL') + self.assertEqual(aruco_detector.marker_size, 3) self.assertIsNone(numpy.testing.assert_array_equal(aruco_detector.camera.dimensions, [1920, 1080])) self.assertEqual(aruco_detector.parameters.cornerRefinementMethod, 3) self.assertEqual(aruco_detector.parameters.aprilTagQuadSigma, 2) diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py index 21a7d6a..a684fc6 100644 --- a/src/argaze/ArFeatures.py +++ b/src/argaze/ArFeatures.py @@ -39,25 +39,26 @@ class ArEnvironment(): def from_json(self, json_filepath: str) -> ArSceneType: """Load ArEnvironment from .json file.""" - new_name = '' - new_working_directory = '.' - new_aruco_detector = None - new_scenes = {} - with open(json_filepath) as configuration_file: data = json.load(configuration_file) new_name = data.pop('name') - new_working_directory = os.path.dirname(json_filepath) + new_detector_data = data.pop('aruco_detector') + + new_aruco_dictionary = ArUcoMarkersDictionary.ArUcoMarkersDictionary(new_detector_data.pop('dictionary')) + new_marker_size = new_detector_data.pop('marker_size') + new_aruco_camera = ArUcoCamera.ArUcoCamera(**new_detector_data.pop('camera')) + new_aruco_detecor_parameters = ArUcoDetector.DetectorParameters(**new_detector_data.pop('parameters')) - new_aruco_detector = ArUcoDetector.ArUcoDetector(**data.pop('aruco_detector')) + new_aruco_detector = ArUcoDetector.ArUcoDetector(new_aruco_dictionary, new_marker_size, new_aruco_camera, new_aruco_detecor_parameters) for scene_name, scene_data in data.items(): new_aruco_scene = None new_aoi_scene = None + new_scenes = {} # Check aruco_scene value type aruco_scene_value = scene_data.pop('aruco_scene') @@ -89,7 +90,7 @@ class ArEnvironment(): new_scenes[scene_name] = ArScene(self, new_aruco_scene, new_aoi_scene, **scene_data) - return ArEnvironment(new_name, new_working_directory, new_aruco_detector, new_scenes) + return ArEnvironment(new_name, new_working_directory, new_aruco_detector, new_scenes) def __str__(self) -> str: """String display""" diff --git a/src/argaze/ArUcoMarkers/ArUcoDetector.py b/src/argaze/ArUcoMarkers/ArUcoDetector.py index 3ebd442..d96a472 100644 --- a/src/argaze/ArUcoMarkers/ArUcoDetector.py +++ b/src/argaze/ArUcoMarkers/ArUcoDetector.py @@ -27,7 +27,7 @@ ArUcoDetectorType = TypeVar('ArUcoDetector', bound="ArUcoDetector") # Type definition for type annotation convenience class DetectorParameters(): - """Define ArUco marker detector parameters. + """Wrapper class around ArUco marker detector parameters. .. note:: More details on [opencv page](https://docs.opencv.org/4.x/d1/dcd/structcv_1_1aruco_1_1DetectorParameters.html) """ @@ -110,61 +110,23 @@ class DetectorParameters(): def internal(self): return self.__parameters +@dataclass class ArUcoDetector(): """ArUco markers detector.""" - dictionary: ArUcoMarkersDictionary.ArUcoMarkersDictionary = field(init=False, default_factory=ArUcoMarkersDictionary.ArUcoMarkersDictionary) + dictionary: ArUcoMarkersDictionary.ArUcoMarkersDictionary = field(default_factory=ArUcoMarkersDictionary.ArUcoMarkersDictionary) """ArUco markers dictionary to detect.""" - marker_size: float = field(init=False) + marker_size: float = field(default=0.) """Size of ArUco markers to detect in centimeter.""" - camera: ArUcoCamera.ArUcoCamera = field(init=False, default_factory=ArUcoCamera.ArUcoCamera) - """ArUco camera ...""" + camera: ArUcoCamera.ArUcoCamera = field(default_factory=ArUcoCamera.ArUcoCamera) + """ArUco camera to use to setup optical parameters.""" - def __init__(self, **kwargs): - - # Handle dictionary str or instance - try: - dictionary_value = kwargs.pop('dictionary') - - if type(dictionary_value) == str: - self.dictionary = ArUcoMarkersDictionary.ArUcoMarkersDictionary(dictionary_value) - elif isinstance(dictionary_value, ArUcoMarkersDictionary.ArUcoMarkersDictionary): - self.dictionary = dictionary_value - else: - raise ValueError(f'dictionary: {dictionary_value}') - - except KeyError: - - self.dictionary = ArUcoMarkersDictionary.ArUcoMarkersDictionary() - - # Handle camera dict or instance - try: - camera_value = kwargs.pop('camera') - - if type(camera_value) == dict: - self.camera = ArUcoCamera.ArUcoCamera(**camera_value) - elif isinstance(camera_value, ArUcoCamera.ArUcoCamera): - self.camera = camera_value - else: - raise ValueError(f'camera: {camera_value}') - - except KeyError: - - self.camera = ArUcoCamera.ArUcoCamera() + parameters: DetectorParameters = field(default_factory=DetectorParameters) + """ArUco detector parameters.""" - # Init marker size - self.marker_size = kwargs.pop('marker_size') - - # Init detector parameters - try: - - self.__parameters = DetectorParameters(**kwargs.pop('parameters')) - - except KeyError: - - self.__parameters = DetectorParameters() + def __post_init__(self): # Init detected markers data self.__detected_markers = {} @@ -187,22 +149,25 @@ class ArUcoDetector(): with open(json_filepath) as configuration_file: - return ArUcoDetector(**json.load(configuration_file)) + data = json.load(configuration_file) + + new_dictionary = ArUcoMarkersDictionary.ArUcoMarkersDictionary(data.pop('dictionary')) + new_marker_size = data.pop('marker_size') + new_camera = ArUcoCamera.ArUcoCamera(**data.pop('camera')) + new_parameters = DetectorParameters(**data.pop('parameters')) + + return ArUcoDetector(new_dictionary, new_marker_size, new_camera, new_parameters) def __str__(self) -> str: """String display""" - output = f'Camera:\n{self.camera}\n' - output += f'Parameters:\n{self.__parameters}\n' + output = f'Dictionary:\n{self.dictionary}\n' + output += f'Marker size:\n{self.marker_size}\n' + output += f'Camera:\n{self.camera}\n' + output += f'Parameters:\n{self.parameters}\n' return output - @property - def parameters(self): - """ArUco marker detector parameters.""" - - return self.__parameters - def detect_markers(self, frame): """Detect all ArUco markers into a frame. @@ -214,7 +179,7 @@ class ArUcoDetector(): self.__detected_markers, self.__detected_markers_corners, self.__detected_markers_ids = {}, [], [] # Detect markers into gray picture - self.__detected_markers_corners, self.__detected_markers_ids, _ = aruco.detectMarkers(cv.cvtColor(frame, cv.COLOR_BGR2GRAY), self.dictionary.markers, parameters = self.__parameters.internal) + self.__detected_markers_corners, self.__detected_markers_ids, _ = aruco.detectMarkers(cv.cvtColor(frame, cv.COLOR_BGR2GRAY), self.dictionary.markers, parameters = self.parameters.internal) # Is there detected markers ? if len(self.__detected_markers_corners) > 0: @@ -306,7 +271,7 @@ class ArUcoDetector(): # detect markers from gray picture gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) - self.__detected_markers_corners, self.__detected_markers_ids, _ = aruco.detectMarkers(gray, self.dictionary.markers, parameters = self.__parameters.internal) + self.__detected_markers_corners, self.__detected_markers_ids, _ = aruco.detectMarkers(gray, self.dictionary.markers, parameters = self.parameters.internal) # if all board markers are detected if len(self.__detected_markers_corners) == expected_markers_number: -- cgit v1.1