aruco_detector.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html
  4. #ifndef OPENCV_OBJDETECT_ARUCO_DETECTOR_HPP
  5. #define OPENCV_OBJDETECT_ARUCO_DETECTOR_HPP
  6. #include <opencv2/objdetect/aruco_dictionary.hpp>
  7. #include <opencv2/objdetect/aruco_board.hpp>
  8. namespace cv {
  9. namespace aruco {
  10. //! @addtogroup objdetect_aruco
  11. //! @{
  12. enum CornerRefineMethod{
  13. CORNER_REFINE_NONE, ///< Tag and corners detection based on the ArUco approach
  14. CORNER_REFINE_SUBPIX, ///< ArUco approach and refine the corners locations using corner subpixel accuracy
  15. CORNER_REFINE_CONTOUR, ///< ArUco approach and refine the corners locations using the contour-points line fitting
  16. CORNER_REFINE_APRILTAG, ///< Tag and corners detection based on the AprilTag 2 approach @cite wang2016iros
  17. };
  18. /** @brief struct DetectorParameters is used by ArucoDetector
  19. */
  20. struct CV_EXPORTS_W_SIMPLE DetectorParameters {
  21. CV_WRAP DetectorParameters() {
  22. adaptiveThreshWinSizeMin = 3;
  23. adaptiveThreshWinSizeMax = 23;
  24. adaptiveThreshWinSizeStep = 10;
  25. adaptiveThreshConstant = 7;
  26. minMarkerPerimeterRate = 0.03;
  27. maxMarkerPerimeterRate = 4.;
  28. polygonalApproxAccuracyRate = 0.03;
  29. minCornerDistanceRate = 0.05;
  30. minDistanceToBorder = 3;
  31. minMarkerDistanceRate = 0.125;
  32. cornerRefinementMethod = (int)CORNER_REFINE_NONE;
  33. cornerRefinementWinSize = 5;
  34. relativeCornerRefinmentWinSize = 0.3f;
  35. cornerRefinementMaxIterations = 30;
  36. cornerRefinementMinAccuracy = 0.1;
  37. markerBorderBits = 1;
  38. perspectiveRemovePixelPerCell = 4;
  39. perspectiveRemoveIgnoredMarginPerCell = 0.13;
  40. maxErroneousBitsInBorderRate = 0.35;
  41. minOtsuStdDev = 5.0;
  42. errorCorrectionRate = 0.6;
  43. aprilTagQuadDecimate = 0.0;
  44. aprilTagQuadSigma = 0.0;
  45. aprilTagMinClusterPixels = 5;
  46. aprilTagMaxNmaxima = 10;
  47. aprilTagCriticalRad = (float)(10* CV_PI /180);
  48. aprilTagMaxLineFitMse = 10.0;
  49. aprilTagMinWhiteBlackDiff = 5;
  50. aprilTagDeglitch = 0;
  51. detectInvertedMarker = false;
  52. useAruco3Detection = false;
  53. minSideLengthCanonicalImg = 32;
  54. minMarkerLengthRatioOriginalImg = 0.0;
  55. }
  56. /** @brief Read a new set of DetectorParameters from FileNode (use FileStorage.root()).
  57. */
  58. CV_WRAP bool readDetectorParameters(const FileNode& fn);
  59. /** @brief Write a set of DetectorParameters to FileStorage
  60. */
  61. CV_WRAP bool writeDetectorParameters(FileStorage& fs, const String& name = String());
  62. /// minimum window size for adaptive thresholding before finding contours (default 3).
  63. CV_PROP_RW int adaptiveThreshWinSizeMin;
  64. /// maximum window size for adaptive thresholding before finding contours (default 23).
  65. CV_PROP_RW int adaptiveThreshWinSizeMax;
  66. /// increments from adaptiveThreshWinSizeMin to adaptiveThreshWinSizeMax during the thresholding (default 10).
  67. CV_PROP_RW int adaptiveThreshWinSizeStep;
  68. /// constant for adaptive thresholding before finding contours (default 7)
  69. CV_PROP_RW double adaptiveThreshConstant;
  70. /** @brief determine minimum perimeter for marker contour to be detected.
  71. *
  72. * This is defined as a rate respect to the maximum dimension of the input image (default 0.03).
  73. */
  74. CV_PROP_RW double minMarkerPerimeterRate;
  75. /** @brief determine maximum perimeter for marker contour to be detected.
  76. *
  77. * This is defined as a rate respect to the maximum dimension of the input image (default 4.0).
  78. */
  79. CV_PROP_RW double maxMarkerPerimeterRate;
  80. /// minimum accuracy during the polygonal approximation process to determine which contours are squares. (default 0.03)
  81. CV_PROP_RW double polygonalApproxAccuracyRate;
  82. /// minimum distance between corners for detected markers relative to its perimeter (default 0.05)
  83. CV_PROP_RW double minCornerDistanceRate;
  84. /// minimum distance of any corner to the image border for detected markers (in pixels) (default 3)
  85. CV_PROP_RW int minDistanceToBorder;
  86. /** @brief minimum average distance between the corners of the two markers to be grouped (default 0.125).
  87. *
  88. * The rate is relative to the smaller perimeter of the two markers.
  89. * Two markers are grouped if average distance between the corners of the two markers is less than
  90. * min(MarkerPerimeter1, MarkerPerimeter2)*minMarkerDistanceRate.
  91. *
  92. * default value is 0.125 because 0.125*MarkerPerimeter = (MarkerPerimeter / 4) * 0.5 = half the side of the marker.
  93. *
  94. * @note default value was changed from 0.05 after 4.8.1 release, because the filtering algorithm has been changed.
  95. * Now a few candidates from the same group can be added to the list of candidates if they are far from each other.
  96. * @sa minGroupDistance.
  97. */
  98. CV_PROP_RW double minMarkerDistanceRate;
  99. /** @brief minimum average distance between the corners of the two markers in group to add them to the list of candidates
  100. *
  101. * The average distance between the corners of the two markers is calculated relative to its module size (default 0.21).
  102. */
  103. CV_PROP_RW float minGroupDistance = 0.21f;
  104. /** @brief default value CORNER_REFINE_NONE */
  105. CV_PROP_RW int cornerRefinementMethod;
  106. /** @brief maximum window size for the corner refinement process (in pixels) (default 5).
  107. *
  108. * The window size may decrease if the ArUco marker is too small, check relativeCornerRefinmentWinSize.
  109. * The final window size is calculated as:
  110. * min(cornerRefinementWinSize, averageArucoModuleSize*relativeCornerRefinmentWinSize),
  111. * where averageArucoModuleSize is average module size of ArUco marker in pixels.
  112. * (ArUco marker is composed of black and white modules)
  113. */
  114. CV_PROP_RW int cornerRefinementWinSize;
  115. /** @brief Dynamic window size for corner refinement relative to Aruco module size (default 0.3).
  116. *
  117. * The final window size is calculated as:
  118. * min(cornerRefinementWinSize, averageArucoModuleSize*relativeCornerRefinmentWinSize),
  119. * where averageArucoModuleSize is average module size of ArUco marker in pixels.
  120. * (ArUco marker is composed of black and white modules)
  121. * In the case of markers located far from each other, it may be useful to increase the value of the parameter to 0.4-0.5.
  122. * In the case of markers located close to each other, it may be useful to decrease the parameter value to 0.1-0.2.
  123. */
  124. CV_PROP_RW float relativeCornerRefinmentWinSize;
  125. /// maximum number of iterations for stop criteria of the corner refinement process (default 30).
  126. CV_PROP_RW int cornerRefinementMaxIterations;
  127. /// minimum error for the stop cristeria of the corner refinement process (default: 0.1)
  128. CV_PROP_RW double cornerRefinementMinAccuracy;
  129. /// number of bits of the marker border, i.e. marker border width (default 1).
  130. CV_PROP_RW int markerBorderBits;
  131. /// number of bits (per dimension) for each cell of the marker when removing the perspective (default 4).
  132. CV_PROP_RW int perspectiveRemovePixelPerCell;
  133. /** @brief width of the margin of pixels on each cell not considered for the determination of the cell bit.
  134. *
  135. * Represents the rate respect to the total size of the cell, i.e. perspectiveRemovePixelPerCell (default 0.13)
  136. */
  137. CV_PROP_RW double perspectiveRemoveIgnoredMarginPerCell;
  138. /** @brief maximum number of accepted erroneous bits in the border (i.e. number of allowed white bits in the border).
  139. *
  140. * Represented as a rate respect to the total number of bits per marker (default 0.35).
  141. */
  142. CV_PROP_RW double maxErroneousBitsInBorderRate;
  143. /** @brief minimun standard deviation in pixels values during the decodification step to apply Otsu
  144. * thresholding (otherwise, all the bits are set to 0 or 1 depending on mean higher than 128 or not) (default 5.0)
  145. */
  146. CV_PROP_RW double minOtsuStdDev;
  147. /// error correction rate respect to the maximun error correction capability for each dictionary (default 0.6).
  148. CV_PROP_RW double errorCorrectionRate;
  149. /** @brief April :: User-configurable parameters.
  150. *
  151. * Detection of quads can be done on a lower-resolution image, improving speed at a cost of
  152. * pose accuracy and a slight decrease in detection rate. Decoding the binary payload is still
  153. */
  154. CV_PROP_RW float aprilTagQuadDecimate;
  155. /// what Gaussian blur should be applied to the segmented image (used for quad detection?)
  156. CV_PROP_RW float aprilTagQuadSigma;
  157. // April :: Internal variables
  158. /// reject quads containing too few pixels (default 5).
  159. CV_PROP_RW int aprilTagMinClusterPixels;
  160. /// how many corner candidates to consider when segmenting a group of pixels into a quad (default 10).
  161. CV_PROP_RW int aprilTagMaxNmaxima;
  162. /** @brief reject quads where pairs of edges have angles that are close to straight or close to 180 degrees.
  163. *
  164. * Zero means that no quads are rejected. (In radians) (default 10*PI/180)
  165. */
  166. CV_PROP_RW float aprilTagCriticalRad;
  167. /// when fitting lines to the contours, what is the maximum mean squared error
  168. CV_PROP_RW float aprilTagMaxLineFitMse;
  169. /** @brief add an extra check that the white model must be (overall) brighter than the black model.
  170. *
  171. * When we build our model of black & white pixels, we add an extra check that the white model must be (overall)
  172. * brighter than the black model. How much brighter? (in pixel values, [0,255]), (default 5)
  173. */
  174. CV_PROP_RW int aprilTagMinWhiteBlackDiff;
  175. /// should the thresholded image be deglitched? Only useful for very noisy images (default 0).
  176. CV_PROP_RW int aprilTagDeglitch;
  177. /** @brief to check if there is a white marker.
  178. *
  179. * In order to generate a "white" marker just invert a normal marker by using a tilde, ~markerImage. (default false)
  180. */
  181. CV_PROP_RW bool detectInvertedMarker;
  182. /** @brief enable the new and faster Aruco detection strategy.
  183. *
  184. * Proposed in the paper:
  185. * Romero-Ramirez et al: Speeded up detection of squared fiducial markers (2018)
  186. * https://www.researchgate.net/publication/325787310_Speeded_Up_Detection_of_Squared_Fiducial_Markers
  187. */
  188. CV_PROP_RW bool useAruco3Detection;
  189. /// minimum side length of a marker in the canonical image. Latter is the binarized image in which contours are searched.
  190. CV_PROP_RW int minSideLengthCanonicalImg;
  191. /// range [0,1], eq (2) from paper. The parameter tau_i has a direct influence on the processing speed.
  192. CV_PROP_RW float minMarkerLengthRatioOriginalImg;
  193. };
  194. /** @brief struct RefineParameters is used by ArucoDetector
  195. */
  196. struct CV_EXPORTS_W_SIMPLE RefineParameters {
  197. CV_WRAP RefineParameters(float minRepDistance = 10.f, float errorCorrectionRate = 3.f, bool checkAllOrders = true);
  198. /** @brief Read a new set of RefineParameters from FileNode (use FileStorage.root()).
  199. */
  200. CV_WRAP bool readRefineParameters(const FileNode& fn);
  201. /** @brief Write a set of RefineParameters to FileStorage
  202. */
  203. CV_WRAP bool writeRefineParameters(FileStorage& fs, const String& name = String());
  204. /** @brief minRepDistance minimum distance between the corners of the rejected candidate and the reprojected marker
  205. in order to consider it as a correspondence.
  206. */
  207. CV_PROP_RW float minRepDistance;
  208. /** @brief errorCorrectionRate rate of allowed erroneous bits respect to the error correction capability of the used dictionary.
  209. *
  210. * -1 ignores the error correction step.
  211. */
  212. CV_PROP_RW float errorCorrectionRate;
  213. /** @brief checkAllOrders consider the four posible corner orders in the rejectedCorners array.
  214. *
  215. * If it set to false, only the provided corner order is considered (default true).
  216. */
  217. CV_PROP_RW bool checkAllOrders;
  218. };
  219. /** @brief The main functionality of ArucoDetector class is detection of markers in an image with detectMarkers() method.
  220. *
  221. * After detecting some markers in the image, you can try to find undetected markers from this dictionary with
  222. * refineDetectedMarkers() method.
  223. *
  224. * @see DetectorParameters, RefineParameters
  225. */
  226. class CV_EXPORTS_W ArucoDetector : public Algorithm
  227. {
  228. public:
  229. /** @brief Basic ArucoDetector constructor
  230. *
  231. * @param dictionary indicates the type of markers that will be searched
  232. * @param detectorParams marker detection parameters
  233. * @param refineParams marker refine detection parameters
  234. */
  235. CV_WRAP ArucoDetector(const Dictionary &dictionary = getPredefinedDictionary(cv::aruco::DICT_4X4_50),
  236. const DetectorParameters &detectorParams = DetectorParameters(),
  237. const RefineParameters& refineParams = RefineParameters());
  238. /** @brief Basic marker detection
  239. *
  240. * @param image input image
  241. * @param corners vector of detected marker corners. For each marker, its four corners
  242. * are provided, (e.g std::vector<std::vector<cv::Point2f> > ). For N detected markers,
  243. * the dimensions of this array is Nx4. The order of the corners is clockwise.
  244. * @param ids vector of identifiers of the detected markers. The identifier is of type int
  245. * (e.g. std::vector<int>). For N detected markers, the size of ids is also N.
  246. * The identifiers have the same order than the markers in the imgPoints array.
  247. * @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a
  248. * correct codification. Useful for debugging purposes.
  249. *
  250. * Performs marker detection in the input image. Only markers included in the specific dictionary
  251. * are searched. For each detected marker, it returns the 2D position of its corner in the image
  252. * and its corresponding identifier.
  253. * Note that this function does not perform pose estimation.
  254. * @note The function does not correct lens distortion or takes it into account. It's recommended to undistort
  255. * input image with corresponding camera model, if camera parameters are known
  256. * @sa undistort, estimatePoseSingleMarkers, estimatePoseBoard
  257. */
  258. CV_WRAP void detectMarkers(InputArray image, OutputArrayOfArrays corners, OutputArray ids,
  259. OutputArrayOfArrays rejectedImgPoints = noArray()) const;
  260. /** @brief Refine not detected markers based on the already detected and the board layout
  261. *
  262. * @param image input image
  263. * @param board layout of markers in the board.
  264. * @param detectedCorners vector of already detected marker corners.
  265. * @param detectedIds vector of already detected marker identifiers.
  266. * @param rejectedCorners vector of rejected candidates during the marker detection process.
  267. * @param cameraMatrix optional input 3x3 floating-point camera matrix
  268. * \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$
  269. * @param distCoeffs optional vector of distortion coefficients
  270. * \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements
  271. * @param recoveredIdxs Optional array to returns the indexes of the recovered candidates in the
  272. * original rejectedCorners array.
  273. *
  274. * This function tries to find markers that were not detected in the basic detecMarkers function.
  275. * First, based on the current detected marker and the board layout, the function interpolates
  276. * the position of the missing markers. Then it tries to find correspondence between the reprojected
  277. * markers and the rejected candidates based on the minRepDistance and errorCorrectionRate parameters.
  278. * If camera parameters and distortion coefficients are provided, missing markers are reprojected
  279. * using projectPoint function. If not, missing marker projections are interpolated using global
  280. * homography, and all the marker corners in the board must have the same Z coordinate.
  281. */
  282. CV_WRAP void refineDetectedMarkers(InputArray image, const Board &board,
  283. InputOutputArrayOfArrays detectedCorners,
  284. InputOutputArray detectedIds, InputOutputArrayOfArrays rejectedCorners,
  285. InputArray cameraMatrix = noArray(), InputArray distCoeffs = noArray(),
  286. OutputArray recoveredIdxs = noArray()) const;
  287. CV_WRAP const Dictionary& getDictionary() const;
  288. CV_WRAP void setDictionary(const Dictionary& dictionary);
  289. CV_WRAP const DetectorParameters& getDetectorParameters() const;
  290. CV_WRAP void setDetectorParameters(const DetectorParameters& detectorParameters);
  291. CV_WRAP const RefineParameters& getRefineParameters() const;
  292. CV_WRAP void setRefineParameters(const RefineParameters& refineParameters);
  293. /** @brief Stores algorithm parameters in a file storage
  294. */
  295. virtual void write(FileStorage& fs) const override;
  296. /** @brief simplified API for language bindings
  297. */
  298. CV_WRAP inline void write(FileStorage& fs, const String& name) { Algorithm::write(fs, name); }
  299. /** @brief Reads algorithm parameters from a file storage
  300. */
  301. CV_WRAP virtual void read(const FileNode& fn) override;
  302. protected:
  303. struct ArucoDetectorImpl;
  304. Ptr<ArucoDetectorImpl> arucoDetectorImpl;
  305. };
  306. /** @brief Draw detected markers in image
  307. *
  308. * @param image input/output image. It must have 1 or 3 channels. The number of channels is not altered.
  309. * @param corners positions of marker corners on input image.
  310. * (e.g std::vector<std::vector<cv::Point2f> > ). For N detected markers, the dimensions of
  311. * this array should be Nx4. The order of the corners should be clockwise.
  312. * @param ids vector of identifiers for markers in markersCorners .
  313. * Optional, if not provided, ids are not painted.
  314. * @param borderColor color of marker borders. Rest of colors (text color and first corner color)
  315. * are calculated based on this one to improve visualization.
  316. *
  317. * Given an array of detected marker corners and its corresponding ids, this functions draws
  318. * the markers in the image. The marker borders are painted and the markers identifiers if provided.
  319. * Useful for debugging purposes.
  320. */
  321. CV_EXPORTS_W void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays corners,
  322. InputArray ids = noArray(), Scalar borderColor = Scalar(0, 255, 0));
  323. /** @brief Generate a canonical marker image
  324. *
  325. * @param dictionary dictionary of markers indicating the type of markers
  326. * @param id identifier of the marker that will be returned. It has to be a valid id in the specified dictionary.
  327. * @param sidePixels size of the image in pixels
  328. * @param img output image with the marker
  329. * @param borderBits width of the marker border.
  330. *
  331. * This function returns a marker image in its canonical form (i.e. ready to be printed)
  332. */
  333. CV_EXPORTS_W void generateImageMarker(const Dictionary &dictionary, int id, int sidePixels, OutputArray img,
  334. int borderBits = 1);
  335. //! @}
  336. }
  337. }
  338. #endif