aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/argaze/ArUcoMarker/ArUcoDetector.py101
1 files changed, 27 insertions, 74 deletions
diff --git a/src/argaze/ArUcoMarker/ArUcoDetector.py b/src/argaze/ArUcoMarker/ArUcoDetector.py
index 50da144..8ff840b 100644
--- a/src/argaze/ArUcoMarker/ArUcoDetector.py
+++ b/src/argaze/ArUcoMarker/ArUcoDetector.py
@@ -21,110 +21,63 @@ import json
from collections import Counter
from typing import Self
-import cv2 as cv
+import cv2
import numpy
-from cv2 import aruco
from argaze import DataFeatures
from argaze.ArUcoMarker import ArUcoMarkerDictionary, ArUcoMarker, ArUcoOpticCalibrator, ArUcoMarkerGroup
-class DetectorParameters():
- """Wrapper class around ArUco marker detector parameters.
+class DetectorParameters(cv2.aruco.DetectorParameters):
+ """OpenCV DetectorParameters wrapper.
!!! note
More details on [opencv page](https://docs.opencv.org/4.x/d1/dcd/structcv_1_1aruco_1_1DetectorParameters.html)
"""
- __parameters = aruco.DetectorParameters()
- __parameters_names = [
- 'adaptiveThreshConstant',
- 'adaptiveThreshWinSizeMax',
- 'adaptiveThreshWinSizeMin',
- 'adaptiveThreshWinSizeStep',
- 'aprilTagCriticalRad',
- 'aprilTagDeglitch',
- 'aprilTagMaxLineFitMse',
- 'aprilTagMaxNmaxima',
- 'aprilTagMinClusterPixels',
- 'aprilTagMinWhiteBlackDiff',
- 'aprilTagQuadDecimate',
- 'aprilTagQuadSigma',
- 'cornerRefinementMaxIterations',
- 'cornerRefinementMethod',
- 'cornerRefinementMinAccuracy',
- 'cornerRefinementWinSize',
- 'markerBorderBits',
- 'minMarkerPerimeterRate',
- 'maxMarkerPerimeterRate',
- 'minMarkerDistanceRate',
- 'detectInvertedMarker',
- 'errorCorrectionRate',
- 'maxErroneousBitsInBorderRate',
- 'minCornerDistanceRate',
- 'minDistanceToBorder',
- 'minOtsuStdDev',
- 'perspectiveRemoveIgnoredMarginPerCell',
- 'perspectiveRemovePixelPerCell',
- 'polygonalApproxAccuracyRate',
- 'useAruco3Detection'
- ]
-
def __init__(self, **kwargs):
- for parameter, value in kwargs.items():
- setattr(self.__parameters, parameter, value)
-
- self.__dict__.update(kwargs)
-
- def __setattr__(self, parameter, value):
+ super().__init__()
- setattr(self.__parameters, parameter, value)
+ self.__modified = []
- def __getattr__(self, parameter):
+ self.__parameters_names = [name for name in dir(self) if not name.startswith('_')]
+ self.__parameters_names.remove('from_json')
+ self.__parameters_names.remove('readDetectorParameters')
+ self.__parameters_names.remove('writeDetectorParameters')
+
+ for parameter, value in kwargs.items():
- return getattr(self.__parameters, parameter)
+ setattr(self, parameter, value)
+ self.__modified.append(parameter)
@classmethod
def from_json(cls, json_filepath) -> Self:
"""Load detector parameters from .json file."""
with open(json_filepath) as configuration_file:
+
return DetectorParameters(**json.load(configuration_file))
def __str__(self) -> str:
"""Detector parameters string representation."""
- return f'{self}'
-
- def __format__(self, spec: str) -> str:
- """Formated detector parameters string representation.
-
- Parameters:
- spec: 'modified' to get only modified parameters.
- """
-
output = ''
for parameter in self.__parameters_names:
- if parameter in self.__dict__.keys():
+ if parameter in self.__modified:
- output += f'\t*{parameter}: {getattr(self.__parameters, parameter)}\n'
+ output += f'\t*{parameter}: {getattr(self, parameter)}\n'
- elif spec == "":
+ else:
- output += f'\t{parameter}: {getattr(self.__parameters, parameter)}\n'
+ output += f'\t{parameter}: {getattr(self, parameter)}\n'
return output
- @property
- def internal(self):
- return self.__parameters
-
-
class ArUcoDetector(DataFeatures.PipelineStepObject):
- """OpenCV ArUco library wrapper."""
+ """OpenCV ArucoDetector wrapper."""
# noinspection PyMissingConstructor
@DataFeatures.PipelineStepInit
@@ -201,7 +154,7 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
self.__detected_markers, detected_markers_corners, detected_markers_ids = {}, [], []
# Detect markers into gray picture
- detected_markers_corners, detected_markers_ids, _ = aruco.detectMarkers(cv.cvtColor(image, cv.COLOR_BGR2GRAY), self.__dictionary.markers, parameters=self.__parameters.internal if self.__parameters else None)
+ detected_markers_corners, detected_markers_ids, _ = cv2.aruco.detectMarkers(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), self.__dictionary.markers, parameters=self.__parameters)
# Is there detected markers ?
if len(detected_markers_corners) > 0:
@@ -272,7 +225,7 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
if len(ids) == 0:
ids = self.__detected_markers.keys()
- # Prepare data for aruco.estimatePoseSingleMarkers function
+ # Prepare data for cv2.aruco.estimatePoseSingleMarkers function
selected_markers_corners = tuple()
selected_markers_ids = []
@@ -286,14 +239,14 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
# Estimate pose of selected markers
if len(selected_markers_corners) > 0:
- markers_rvecs, markers_tvecs, markers_points = aruco.estimatePoseSingleMarkers(selected_markers_corners, size, numpy.array(self.__optic_parameters.K), numpy.array(self.__optic_parameters.D))
+ markers_rvecs, markers_tvecs, markers_points = cv2.aruco.estimatePoseSingleMarkers(selected_markers_corners, size, numpy.array(self.__optic_parameters.K), numpy.array(self.__optic_parameters.D))
for i, marker_id in enumerate(selected_markers_ids):
marker = self.__detected_markers[marker_id]
marker.translation = markers_tvecs[i][0]
- marker.rotation, _ = cv.Rodrigues(markers_rvecs[i][0])
+ marker.rotation, _ = cv2.Rodrigues(markers_rvecs[i][0])
marker.size = size
marker.points = markers_points.reshape(4, 3).dot(marker.rotation) - marker.translation
@@ -328,15 +281,15 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
"""
# detect markers from gray picture
- gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
- detected_markers_corners, detected_markers_ids, _ = aruco.detectMarkers(gray, self.__dictionary.markers,
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
+ detected_markers_corners, detected_markers_ids, _ = cv2.aruco.detectMarkers(gray, self.__dictionary.markers,
parameters=self.__parameters.internal)
# if all board markers are detected
if len(detected_markers_corners) == expected_markers_number:
self.__board = board
- self.__board_corners_number, self.__board_corners, self.__board_corners_ids = aruco.interpolateCornersCharuco(
+ self.__board_corners_number, self.__board_corners, self.__board_corners_ids = cv2.aruco.interpolateCornersCharuco(
detected_markers_corners, detected_markers_ids, gray, self.__board.model)
else:
@@ -350,7 +303,7 @@ class ArUcoDetector(DataFeatures.PipelineStepObject):
"""Draw detected board corners in image."""
if self.__board is not None:
- cv.drawChessboardCorners(image, ((self.__board.size[0] - 1), (self.__board.size[1] - 1)),
+ cv2.drawChessboardCorners(image, ((self.__board.size[0] - 1), (self.__board.size[1] - 1)),
self.__board_corners, True)
def board_corners_number(self) -> int: