Merge pull request #22368 from AleksandrPanov:move_contrib_aruco_to_main_objdetect

Megre together with https://github.com/opencv/opencv_contrib/pull/3325

1. Move aruco_detector, aruco_board, aruco_dictionary, aruco_utils to objdetect
1.1 add virtual Board::draw(), virtual ~Board()
1.2 move `testCharucoCornersCollinear` to Board classes (and rename to `checkCharucoCornersCollinear`)
1.3 add wrappers to keep the old api working
3. Reduce inludes
4. Fix java tests (add objdetect import)
5. Refactoring

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake

```
**WIP**
force_builders=linux,win64,docs,Linux x64 Debug,Custom
Xbuild_contrib:Docs=OFF

build_image:Custom=ubuntu:22.04
build_worker:Custom=linux-1
```
This commit is contained in:
Alexander Panov
2022-12-16 12:28:47 +03:00
committed by GitHub
parent 47fb79bd8c
commit b4b35cff15
27 changed files with 41433 additions and 11 deletions
@@ -851,5 +851,6 @@ protected:
#include "opencv2/objdetect/detection_based_tracker.hpp"
#include "opencv2/objdetect/face.hpp"
#include "opencv2/objdetect/aruco_detector.hpp"
#endif
@@ -0,0 +1,234 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_OBJDETECT_ARUCO_BOARD_HPP
#define OPENCV_OBJDETECT_ARUCO_BOARD_HPP
#include <opencv2/core.hpp>
namespace cv {
namespace aruco {
//! @addtogroup aruco
//! @{
class Dictionary;
/** @brief Board of ArUco markers
*
* A board is a set of markers in the 3D space with a common coordinate system.
* The common form of a board of marker is a planar (2D) board, however any 3D layout can be used.
* A Board object is composed by:
* - The object points of the marker corners, i.e. their coordinates respect to the board system.
* - The dictionary which indicates the type of markers of the board
* - The identifier of all the markers in the board.
*/
class CV_EXPORTS_W Board {
protected:
Board(); // use ::create()
public:
/** @brief Draw a planar board
*
* @param outSize size of the output image in pixels.
* @param img output image with the board. The size of this image will be outSize
* and the board will be on the center, keeping the board proportions.
* @param marginSize minimum margins (in pixels) of the board in the output image
* @param borderBits width of the marker borders.
*
* This function return the image of the GridBoard, ready to be printed.
*/
CV_WRAP virtual void generateImage(Size outSize, OutputArray img, int marginSize = 0, int borderBits = 1) const;
/** @brief Provide way to create Board by passing necessary data. Specially needed in Python.
*
* @param objPoints array of object points of all the marker corners in the board
* @param dictionary the dictionary of markers employed for this board
* @param ids vector of the identifiers of the markers in the board
*/
CV_WRAP static Ptr<Board> create(InputArrayOfArrays objPoints, const Dictionary &dictionary, InputArray ids);
/** @brief return the Dictionary of markers employed for this board
*/
CV_WRAP const Dictionary& getDictionary() const;
/** @brief return array of object points of all the marker corners in the board.
*
* Each marker include its 4 corners in this order:
* - objPoints[i][0] - left-top point of i-th marker
* - objPoints[i][1] - right-top point of i-th marker
* - objPoints[i][2] - right-bottom point of i-th marker
* - objPoints[i][3] - left-bottom point of i-th marker
*
* Markers are placed in a certain order - row by row, left to right in every row. For M markers, the size is Mx4.
*/
CV_WRAP const std::vector<std::vector<Point3f> >& getObjPoints() const;
/** @brief vector of the identifiers of the markers in the board (should be the same size as objPoints)
* @return vector of the identifiers of the markers
*/
CV_WRAP const std::vector<int>& getIds() const;
/** @brief get coordinate of the bottom right corner of the board, is set when calling the function create()
*/
CV_WRAP const Point3f& getRightBottomCorner() const;
/** @brief Given a board configuration and a set of detected markers, returns the corresponding
* image points and object points to call solvePnP
*
* @param detectedCorners List of detected marker corners of the board.
* @param detectedIds List of identifiers for each marker.
* @param objPoints Vector of vectors of board marker points in the board coordinate space.
* @param imgPoints Vector of vectors of the projections of board marker corner points.
*/
CV_WRAP void matchImagePoints(InputArrayOfArrays detectedCorners, InputArray detectedIds,
OutputArray objPoints, OutputArray imgPoints) const;
virtual ~Board();
protected:
struct BoardImpl;
Ptr<BoardImpl> boardImpl;
};
/** @brief Planar board with grid arrangement of markers
*
* More common type of board. All markers are placed in the same plane in a grid arrangement.
* The board image can be drawn using generateImage() method.
*/
class CV_EXPORTS_W GridBoard : public Board {
protected:
GridBoard();
public:
/** @brief Draw a GridBoard
*
* @param outSize size of the output image in pixels.
* @param img output image with the board. The size of this image will be outSize
* and the board will be on the center, keeping the board proportions.
* @param marginSize minimum margins (in pixels) of the board in the output image
* @param borderBits width of the marker borders.
*
* This function return the image of the GridBoard, ready to be printed.
*/
CV_WRAP void generateImage(Size outSize, OutputArray img, int marginSize = 0, int borderBits = 1) const CV_OVERRIDE;
/**
* @brief Create a GridBoard object
*
* @param markersX number of markers in X direction
* @param markersY number of markers in Y direction
* @param markerLength marker side length (normally in meters)
* @param markerSeparation separation between two markers (same unit as markerLength)
* @param dictionary dictionary of markers indicating the type of markers
* @param ids set marker ids in dictionary to use on board.
* @return the output GridBoard object
*
* This functions creates a GridBoard object given the number of markers in each direction and
* the marker size and marker separation.
*/
CV_WRAP static Ptr<GridBoard> create(int markersX, int markersY, float markerLength, float markerSeparation,
const Dictionary &dictionary, InputArray ids);
/**
* @overload
* @brief Create a GridBoard object
*
* @param markersX number of markers in X direction
* @param markersY number of markers in Y direction
* @param markerLength marker side length (normally in meters)
* @param markerSeparation separation between two markers (same unit as markerLength)
* @param dictionary dictionary of markers indicating the type of markers
* @param firstMarker id of first marker in dictionary to use on board.
* @return the output GridBoard object
*/
CV_WRAP static Ptr<GridBoard> create(int markersX, int markersY, float markerLength, float markerSeparation,
const Dictionary &dictionary, int firstMarker = 0);
CV_WRAP Size getGridSize() const;
CV_WRAP float getMarkerLength() const;
CV_WRAP float getMarkerSeparation() const;
protected:
struct GridImpl;
Ptr<GridImpl> gridImpl;
friend class CharucoBoard;
};
/**
* @brief ChArUco board is a planar chessboard where the markers are placed inside the white squares of a chessboard.
*
* The benefits of ChArUco boards is that they provide both, ArUco markers versatility and chessboard corner precision,
* which is important for calibration and pose estimation. The board image can be drawn using generateImage() method.
*/
class CV_EXPORTS_W CharucoBoard : public Board {
protected:
CharucoBoard();
public:
/** @brief Draw a ChArUco board
*
* @param outSize size of the output image in pixels.
* @param img output image with the board. The size of this image will be outSize
* and the board will be on the center, keeping the board proportions.
* @param marginSize minimum margins (in pixels) of the board in the output image
* @param borderBits width of the marker borders.
*
* This function return the image of the ChArUco board, ready to be printed.
*/
CV_WRAP void generateImage(Size outSize, OutputArray img, int marginSize = 0, int borderBits = 1) const CV_OVERRIDE;
/** @brief Create a CharucoBoard object
*
* @param squaresX number of chessboard squares in X direction
* @param squaresY number of chessboard squares in Y direction
* @param squareLength chessboard square side length (normally in meters)
* @param markerLength marker side length (same unit than squareLength)
* @param dictionary dictionary of markers indicating the type of markers.
* @param ids array of id used markers
* The first markers in the dictionary are used to fill the white chessboard squares.
* @return the output CharucoBoard object
*
* This functions creates a CharucoBoard object given the number of squares in each direction
* and the size of the markers and chessboard squares.
*/
CV_WRAP static Ptr<CharucoBoard> create(int squaresX, int squaresY, float squareLength, float markerLength,
const Dictionary &dictionary, InputArray ids = noArray());
CV_WRAP Size getChessboardSize() const;
CV_WRAP float getSquareLength() const;
CV_WRAP float getMarkerLength() const;
/** @brief get CharucoBoard::chessboardCorners
*/
CV_WRAP std::vector<Point3f> getChessboardCorners() const;
/** @brief get CharucoBoard::nearestMarkerIdx
*/
CV_PROP std::vector<std::vector<int> > getNearestMarkerIdx() const;
/** @brief get CharucoBoard::nearestMarkerCorners
*/
CV_PROP std::vector<std::vector<int> > getNearestMarkerCorners() const;
/** @brief check whether the ChArUco markers are collinear
*
* @param charucoIds list of identifiers for each corner in charucoCorners per frame.
* @return bool value, 1 (true) if detected corners form a line, 0 (false) if they do not.
* solvePnP, calibration functions will fail if the corners are collinear (true).
*
* The number of ids in charucoIDs should be <= the number of chessboard corners in the board.
* This functions checks whether the charuco corners are on a straight line (returns true, if so), or not (false).
* Axis parallel, as well as diagonal and other straight lines detected. Degenerate cases:
* for number of charucoIDs <= 2,the function returns true.
*/
CV_WRAP bool checkCharucoCornersCollinear(InputArray charucoIds) const;
protected:
struct CharucoImpl;
friend struct CharucoImpl;
Ptr<CharucoImpl> charucoImpl;
};
//! @}
}
}
#endif
@@ -0,0 +1,396 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_OBJDETECT_ARUCO_DETECTOR_HPP
#define OPENCV_OBJDETECT_ARUCO_DETECTOR_HPP
#include <opencv2/objdetect/aruco_dictionary.hpp>
#include <opencv2/objdetect/aruco_board.hpp>
namespace cv {
namespace aruco {
/** @defgroup aruco ArUco Marker Detection
* Square fiducial markers (also known as Augmented Reality Markers) are useful for easy,
* fast and robust camera pose estimation.
*
* The main functionality of ArucoDetector class is detection of markers in an image. There are even more
* functionalities implemented in the aruco contrib module (files aruco.hpp, charuco.hpp, aruco_calib.hpp):
* - Pose estimation from a single marker or from a board/set of markers
* - Detection of ChArUco board for high subpixel accuracy
* - Camera calibration from both, ArUco boards and ChArUco boards.
* - Detection of ChArUco diamond markers
* The functionalities from the aruco contrib module is planned to be transferred to the main repository.
*
* The implementation is based on the ArUco Library by R. Muñoz-Salinas and S. Garrido-Jurado @cite Aruco2014.
*
* Markers can also be detected based on the AprilTag 2 @cite wang2016iros fiducial detection method.
*
* @sa @cite Aruco2014
* This code has been originally developed by Sergio Garrido-Jurado as a project
* for Google Summer of Code 2015 (GSoC 15).
*/
//! @addtogroup aruco
//! @{
enum CornerRefineMethod{
CORNER_REFINE_NONE, ///< Tag and corners detection based on the ArUco approach
CORNER_REFINE_SUBPIX, ///< ArUco approach and refine the corners locations using corner subpixel accuracy
CORNER_REFINE_CONTOUR, ///< ArUco approach and refine the corners locations using the contour-points line fitting
CORNER_REFINE_APRILTAG, ///< Tag and corners detection based on the AprilTag 2 approach @cite wang2016iros
};
/** @brief struct DetectorParameters is used by ArucoDetector
*/
struct CV_EXPORTS_W_SIMPLE DetectorParameters {
CV_WRAP DetectorParameters() {
adaptiveThreshWinSizeMin = 3;
adaptiveThreshWinSizeMax = 23;
adaptiveThreshWinSizeStep = 10;
adaptiveThreshConstant = 7;
minMarkerPerimeterRate = 0.03;
maxMarkerPerimeterRate = 4.;
polygonalApproxAccuracyRate = 0.03;
minCornerDistanceRate = 0.05;
minDistanceToBorder = 3;
minMarkerDistanceRate = 0.05;
cornerRefinementMethod = CORNER_REFINE_NONE;
cornerRefinementWinSize = 5;
cornerRefinementMaxIterations = 30;
cornerRefinementMinAccuracy = 0.1;
markerBorderBits = 1;
perspectiveRemovePixelPerCell = 4;
perspectiveRemoveIgnoredMarginPerCell = 0.13;
maxErroneousBitsInBorderRate = 0.35;
minOtsuStdDev = 5.0;
errorCorrectionRate = 0.6;
aprilTagQuadDecimate = 0.0;
aprilTagQuadSigma = 0.0;
aprilTagMinClusterPixels = 5;
aprilTagMaxNmaxima = 10;
aprilTagCriticalRad = (float)(10* CV_PI /180);
aprilTagMaxLineFitMse = 10.0;
aprilTagMinWhiteBlackDiff = 5;
aprilTagDeglitch = 0;
detectInvertedMarker = false;
useAruco3Detection = false;
minSideLengthCanonicalImg = 32;
minMarkerLengthRatioOriginalImg = 0.0;
};
/** @brief Read a new set of DetectorParameters from FileNode (use FileStorage.root()).
*/
CV_WRAP bool readDetectorParameters(const FileNode& fn);
/** @brief Write a set of DetectorParameters to FileStorage
*/
bool writeDetectorParameters(FileStorage& fs);
/** @brief simplified API for language bindings
*/
CV_WRAP bool writeDetectorParameters(const Ptr<FileStorage>& fs, const String& name = String());
/// minimum window size for adaptive thresholding before finding contours (default 3).
CV_PROP_RW int adaptiveThreshWinSizeMin;
/// maximum window size for adaptive thresholding before finding contours (default 23).
CV_PROP_RW int adaptiveThreshWinSizeMax;
/// increments from adaptiveThreshWinSizeMin to adaptiveThreshWinSizeMax during the thresholding (default 10).
CV_PROP_RW int adaptiveThreshWinSizeStep;
/// constant for adaptive thresholding before finding contours (default 7)
CV_PROP_RW double adaptiveThreshConstant;
/** @brief determine minimum perimeter for marker contour to be detected.
*
* This is defined as a rate respect to the maximum dimension of the input image (default 0.03).
*/
CV_PROP_RW double minMarkerPerimeterRate;
/** @brief determine maximum perimeter for marker contour to be detected.
*
* This is defined as a rate respect to the maximum dimension of the input image (default 4.0).
*/
CV_PROP_RW double maxMarkerPerimeterRate;
/// minimum accuracy during the polygonal approximation process to determine which contours are squares. (default 0.03)
CV_PROP_RW double polygonalApproxAccuracyRate;
/// minimum distance between corners for detected markers relative to its perimeter (default 0.05)
CV_PROP_RW double minCornerDistanceRate;
/// minimum distance of any corner to the image border for detected markers (in pixels) (default 3)
CV_PROP_RW int minDistanceToBorder;
/** @brief minimum mean distance beetween two marker corners to be considered imilar, so that the smaller one is removed.
*
* The rate is relative to the smaller perimeter of the two markers (default 0.05).
*/
CV_PROP_RW double minMarkerDistanceRate;
/** @brief default value CORNER_REFINE_NONE */
CV_PROP_RW CornerRefineMethod cornerRefinementMethod;
/// window size for the corner refinement process (in pixels) (default 5).
CV_PROP_RW int cornerRefinementWinSize;
/// maximum number of iterations for stop criteria of the corner refinement process (default 30).
CV_PROP_RW int cornerRefinementMaxIterations;
/// minimum error for the stop cristeria of the corner refinement process (default: 0.1)
CV_PROP_RW double cornerRefinementMinAccuracy;
/// number of bits of the marker border, i.e. marker border width (default 1).
CV_PROP_RW int markerBorderBits;
/// number of bits (per dimension) for each cell of the marker when removing the perspective (default 4).
CV_PROP_RW int perspectiveRemovePixelPerCell;
/** @brief width of the margin of pixels on each cell not considered for the determination of the cell bit.
*
* Represents the rate respect to the total size of the cell, i.e. perspectiveRemovePixelPerCell (default 0.13)
*/
CV_PROP_RW double perspectiveRemoveIgnoredMarginPerCell;
/** @brief maximum number of accepted erroneous bits in the border (i.e. number of allowed white bits in the border).
*
* Represented as a rate respect to the total number of bits per marker (default 0.35).
*/
CV_PROP_RW double maxErroneousBitsInBorderRate;
/** @brief minimun standard deviation in pixels values during the decodification step to apply Otsu
* thresholding (otherwise, all the bits are set to 0 or 1 depending on mean higher than 128 or not) (default 5.0)
*/
CV_PROP_RW double minOtsuStdDev;
/// error correction rate respect to the maximun error correction capability for each dictionary (default 0.6).
CV_PROP_RW double errorCorrectionRate;
/** @brief April :: User-configurable parameters.
*
* Detection of quads can be done on a lower-resolution image, improving speed at a cost of
* pose accuracy and a slight decrease in detection rate. Decoding the binary payload is still
*/
CV_PROP_RW float aprilTagQuadDecimate;
/// what Gaussian blur should be applied to the segmented image (used for quad detection?)
CV_PROP_RW float aprilTagQuadSigma;
// April :: Internal variables
/// reject quads containing too few pixels (default 5).
CV_PROP_RW int aprilTagMinClusterPixels;
/// how many corner candidates to consider when segmenting a group of pixels into a quad (default 10).
CV_PROP_RW int aprilTagMaxNmaxima;
/** @brief reject quads where pairs of edges have angles that are close to straight or close to 180 degrees.
*
* Zero means that no quads are rejected. (In radians) (default 10*PI/180)
*/
CV_PROP_RW float aprilTagCriticalRad;
/// when fitting lines to the contours, what is the maximum mean squared error
CV_PROP_RW float aprilTagMaxLineFitMse;
/** @brief add an extra check that the white model must be (overall) brighter than the black model.
*
* When we build our model of black & white pixels, we add an extra check that the white model must be (overall)
* brighter than the black model. How much brighter? (in pixel values, [0,255]), (default 5)
*/
CV_PROP_RW int aprilTagMinWhiteBlackDiff;
/// should the thresholded image be deglitched? Only useful for very noisy images (default 0).
CV_PROP_RW int aprilTagDeglitch;
/** @brief to check if there is a white marker.
*
* In order to generate a "white" marker just invert a normal marker by using a tilde, ~markerImage. (default false)
*/
CV_PROP_RW bool detectInvertedMarker;
/** @brief enable the new and faster Aruco detection strategy.
*
* Proposed in the paper:
* Romero-Ramirez et al: Speeded up detection of squared fiducial markers (2018)
* https://www.researchgate.net/publication/325787310_Speeded_Up_Detection_of_Squared_Fiducial_Markers
*/
CV_PROP_RW bool useAruco3Detection;
/// minimum side length of a marker in the canonical image. Latter is the binarized image in which contours are searched.
CV_PROP_RW int minSideLengthCanonicalImg;
/// range [0,1], eq (2) from paper. The parameter tau_i has a direct influence on the processing speed.
CV_PROP_RW float minMarkerLengthRatioOriginalImg;
};
/** @brief struct RefineParameters is used by ArucoDetector
*/
struct CV_EXPORTS_W_SIMPLE RefineParameters {
CV_WRAP RefineParameters(float minRepDistance = 10.f, float errorCorrectionRate = 3.f, bool checkAllOrders = true);
/** @brief Read a new set of RefineParameters from FileNode (use FileStorage.root()).
*/
CV_WRAP bool readRefineParameters(const FileNode& fn);
/** @brief Write a set of RefineParameters to FileStorage
*/
bool writeRefineParameters(FileStorage& fs);
/** @brief simplified API for language bindings
*/
CV_WRAP bool writeRefineParameters(const Ptr<FileStorage>& fs, const String& name = String());
/** @brief minRepDistance minimum distance between the corners of the rejected candidate and the reprojected marker
in order to consider it as a correspondence.
*/
CV_PROP_RW float minRepDistance;
/** @brief minRepDistance rate of allowed erroneous bits respect to the error correction capability of the used dictionary.
*
* -1 ignores the error correction step.
*/
CV_PROP_RW float errorCorrectionRate;
/** @brief checkAllOrders consider the four posible corner orders in the rejectedCorners array.
*
* If it set to false, only the provided corner order is considered (default true).
*/
CV_PROP_RW bool checkAllOrders;
};
/** @brief The main functionality of ArucoDetector class is detection of markers in an image with detectMarkers() method.
*
* After detecting some markers in the image, you can try to find undetected markers from this dictionary with
* refineDetectedMarkers() method.
*
* @see DetectorParameters, RefineParameters
*/
class CV_EXPORTS_W ArucoDetector : public Algorithm
{
public:
/** @brief Basic ArucoDetector constructor
*
* @param dictionary indicates the type of markers that will be searched
* @param detectorParams marker detection parameters
* @param refineParams marker refine detection parameters
*/
CV_WRAP ArucoDetector(const Dictionary &dictionary = getPredefinedDictionary(cv::aruco::DICT_4X4_50),
const DetectorParameters &detectorParams = DetectorParameters(),
const RefineParameters& refineParams = RefineParameters());
/** @brief Basic marker detection
*
* @param image input image
* @param corners vector of detected marker corners. For each marker, its four corners
* are provided, (e.g std::vector<std::vector<cv::Point2f> > ). For N detected markers,
* the dimensions of this array is Nx4. The order of the corners is clockwise.
* @param ids vector of identifiers of the detected markers. The identifier is of type int
* (e.g. std::vector<int>). For N detected markers, the size of ids is also N.
* The identifiers have the same order than the markers in the imgPoints array.
* @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a
* correct codification. Useful for debugging purposes.
*
* Performs marker detection in the input image. Only markers included in the specific dictionary
* are searched. For each detected marker, it returns the 2D position of its corner in the image
* and its corresponding identifier.
* Note that this function does not perform pose estimation.
* @note The function does not correct lens distortion or takes it into account. It's recommended to undistort
* input image with corresponging camera model, if camera parameters are known
* @sa undistort, estimatePoseSingleMarkers, estimatePoseBoard
*/
CV_WRAP void detectMarkers(InputArray image, OutputArrayOfArrays corners, OutputArray ids,
OutputArrayOfArrays rejectedImgPoints = noArray());
/** @brief Refind not detected markers based on the already detected and the board layout
*
* @param image input image
* @param board layout of markers in the board.
* @param detectedCorners vector of already detected marker corners.
* @param detectedIds vector of already detected marker identifiers.
* @param rejectedCorners vector of rejected candidates during the marker detection process.
* @param cameraMatrix optional input 3x3 floating-point camera matrix
* \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$
* @param distCoeffs optional vector of distortion coefficients
* \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
* @param recoveredIdxs Optional array to returns the indexes of the recovered candidates in the
* original rejectedCorners array.
*
* This function tries to find markers that were not detected in the basic detecMarkers function.
* First, based on the current detected marker and the board layout, the function interpolates
* the position of the missing markers. Then it tries to find correspondence between the reprojected
* markers and the rejected candidates based on the minRepDistance and errorCorrectionRate parameters.
* If camera parameters and distortion coefficients are provided, missing markers are reprojected
* using projectPoint function. If not, missing marker projections are interpolated using global
* homography, and all the marker corners in the board must have the same Z coordinate.
*/
CV_WRAP void refineDetectedMarkers(InputArray image, const Ptr<Board> &board,
InputOutputArrayOfArrays detectedCorners,
InputOutputArray detectedIds, InputOutputArrayOfArrays rejectedCorners,
InputArray cameraMatrix = noArray(), InputArray distCoeffs = noArray(),
OutputArray recoveredIdxs = noArray());
CV_WRAP const Dictionary& getDictionary() const;
CV_WRAP void setDictionary(const Dictionary& dictionary);
CV_WRAP const DetectorParameters& getDetectorParameters() const;
CV_WRAP void setDetectorParameters(const DetectorParameters& detectorParameters);
CV_WRAP const RefineParameters& getRefineParameters() const;
CV_WRAP void setRefineParameters(const RefineParameters& refineParameters);
/** @brief Stores algorithm parameters in a file storage
*/
virtual void write(FileStorage& fs) const override;
/** @brief simplified API for language bindings
*/
CV_WRAP inline void write(const Ptr<FileStorage>& fs, const String& name = String()) { Algorithm::write(fs, name); }
/** @brief Reads algorithm parameters from a file storage
*/
CV_WRAP virtual void read(const FileNode& fn) override;
protected:
struct ArucoDetectorImpl;
Ptr<ArucoDetectorImpl> arucoDetectorImpl;
};
/** @brief Draw detected markers in image
*
* @param image input/output image. It must have 1 or 3 channels. The number of channels is not altered.
* @param corners positions of marker corners on input image.
* (e.g std::vector<std::vector<cv::Point2f> > ). For N detected markers, the dimensions of
* this array should be Nx4. The order of the corners should be clockwise.
* @param ids vector of identifiers for markers in markersCorners .
* Optional, if not provided, ids are not painted.
* @param borderColor color of marker borders. Rest of colors (text color and first corner color)
* are calculated based on this one to improve visualization.
*
* Given an array of detected marker corners and its corresponding ids, this functions draws
* the markers in the image. The marker borders are painted and the markers identifiers if provided.
* Useful for debugging purposes.
*/
CV_EXPORTS_W void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays corners,
InputArray ids = noArray(), Scalar borderColor = Scalar(0, 255, 0));
/** @brief Generate a canonical marker image
*
* @param dictionary dictionary of markers indicating the type of markers
* @param id identifier of the marker that will be returned. It has to be a valid id in the specified dictionary.
* @param sidePixels size of the image in pixels
* @param img output image with the marker
* @param borderBits width of the marker border.
*
* This function returns a marker image in its canonical form (i.e. ready to be printed)
*/
CV_EXPORTS_W void generateImageMarker(const Dictionary &dictionary, int id, int sidePixels, OutputArray img,
int borderBits = 1);
//! @}
}
}
#endif
@@ -0,0 +1,151 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_OBJDETECT_DICTIONARY_HPP
#define OPENCV_OBJDETECT_DICTIONARY_HPP
#include <opencv2/core.hpp>
namespace cv {
namespace aruco {
//! @addtogroup aruco
//! @{
/** @brief Dictionary/Set of markers, it contains the inner codification
*
* BytesList contains the marker codewords where:
* - bytesList.rows is the dictionary size
* - each marker is encoded using `nbytes = ceil(markerSize*markerSize/8.)`
* - each row contains all 4 rotations of the marker, so its length is `4*nbytes`
*
* `bytesList.ptr(i)[k*nbytes + j]` is then the j-th byte of i-th marker, in its k-th rotation.
*/
class CV_EXPORTS_W_SIMPLE Dictionary {
public:
CV_PROP_RW Mat bytesList; // marker code information
CV_PROP_RW int markerSize; // number of bits per dimension
CV_PROP_RW int maxCorrectionBits; // maximum number of bits that can be corrected
CV_WRAP Dictionary();
CV_WRAP Dictionary(const Mat &bytesList, int _markerSize, int maxcorr = 0);
/** @brief Read a new dictionary from FileNode.
*
* Dictionary format:\n
* nmarkers: 35\n
* markersize: 6\n
* maxCorrectionBits: 5\n
* marker_0: "101011111011111001001001101100000000"\n
* ...\n
* marker_34: "011111010000111011111110110101100101"
*/
CV_WRAP bool readDictionary(const cv::FileNode& fn);
/** @brief Write a dictionary to FileStorage, format is the same as in readDictionary().
*/
void writeDictionary(FileStorage& fs);
/** @brief simplified API for language bindings
*/
CV_WRAP void writeDictionary(Ptr<FileStorage>& fs, const String& name = String());
/** @brief Given a matrix of bits. Returns whether if marker is identified or not.
*
* It returns by reference the correct id (if any) and the correct rotation
*/
CV_WRAP bool identify(const Mat &onlyBits, CV_OUT int &idx, CV_OUT int &rotation, double maxCorrectionRate) const;
/** @brief Returns the distance of the input bits to the specific id.
*
* If allRotations is true, the four posible bits rotation are considered
*/
CV_WRAP int getDistanceToId(InputArray bits, int id, bool allRotations = true) const;
/** @brief Generate a canonical marker image
*/
CV_WRAP void generateImageMarker(int id, int sidePixels, OutputArray _img, int borderBits = 1) const;
/** @brief Transform matrix of bits to list of bytes in the 4 rotations
*/
CV_WRAP static Mat getByteListFromBits(const Mat &bits);
/** @brief Transform list of bytes to matrix of bits
*/
CV_WRAP static Mat getBitsFromByteList(const Mat &byteList, int markerSize);
};
/** @brief Predefined markers dictionaries/sets
*
* Each dictionary indicates the number of bits and the number of markers contained
* - DICT_ARUCO_ORIGINAL: standard ArUco Library Markers. 1024 markers, 5x5 bits, 0 minimum
distance
*/
enum PredefinedDictionaryType {
DICT_4X4_50 = 0, ///< 4x4 bits, minimum hamming distance between any two codes = 4, 50 codes
DICT_4X4_100, ///< 4x4 bits, minimum hamming distance between any two codes = 3, 100 codes
DICT_4X4_250, ///< 4x4 bits, minimum hamming distance between any two codes = 3, 250 codes
DICT_4X4_1000, ///< 4x4 bits, minimum hamming distance between any two codes = 2, 1000 codes
DICT_5X5_50, ///< 5x5 bits, minimum hamming distance between any two codes = 8, 50 codes
DICT_5X5_100, ///< 5x5 bits, minimum hamming distance between any two codes = 7, 100 codes
DICT_5X5_250, ///< 5x5 bits, minimum hamming distance between any two codes = 6, 250 codes
DICT_5X5_1000, ///< 5x5 bits, minimum hamming distance between any two codes = 5, 1000 codes
DICT_6X6_50, ///< 6x6 bits, minimum hamming distance between any two codes = 13, 50 codes
DICT_6X6_100, ///< 6x6 bits, minimum hamming distance between any two codes = 12, 100 codes
DICT_6X6_250, ///< 6x6 bits, minimum hamming distance between any two codes = 11, 250 codes
DICT_6X6_1000, ///< 6x6 bits, minimum hamming distance between any two codes = 9, 1000 codes
DICT_7X7_50, ///< 7x7 bits, minimum hamming distance between any two codes = 19, 50 codes
DICT_7X7_100, ///< 7x7 bits, minimum hamming distance between any two codes = 18, 100 codes
DICT_7X7_250, ///< 7x7 bits, minimum hamming distance between any two codes = 17, 250 codes
DICT_7X7_1000, ///< 7x7 bits, minimum hamming distance between any two codes = 14, 1000 codes
DICT_ARUCO_ORIGINAL, ///< 6x6 bits, minimum hamming distance between any two codes = 3, 1024 codes
DICT_APRILTAG_16h5, ///< 4x4 bits, minimum hamming distance between any two codes = 5, 30 codes
DICT_APRILTAG_25h9, ///< 5x5 bits, minimum hamming distance between any two codes = 9, 35 codes
DICT_APRILTAG_36h10, ///< 6x6 bits, minimum hamming distance between any two codes = 10, 2320 codes
DICT_APRILTAG_36h11 ///< 6x6 bits, minimum hamming distance between any two codes = 11, 587 codes
};
/** @brief Returns one of the predefined dictionaries defined in PredefinedDictionaryType
*/
CV_EXPORTS Dictionary getPredefinedDictionary(PredefinedDictionaryType name);
/** @brief Returns one of the predefined dictionaries referenced by DICT_*.
*/
CV_EXPORTS_W Dictionary getPredefinedDictionary(int dict);
/** @brief Extend base dictionary by new nMarkers
*
* @param nMarkers number of markers in the dictionary
* @param markerSize number of bits per dimension of each markers
* @param baseDictionary Include the markers in this dictionary at the beginning (optional)
* @param randomSeed a user supplied seed for theRNG()
*
* This function creates a new dictionary composed by nMarkers markers and each markers composed
* by markerSize x markerSize bits. If baseDictionary is provided, its markers are directly
* included and the rest are generated based on them. If the size of baseDictionary is higher
* than nMarkers, only the first nMarkers in baseDictionary are taken and no new marker is added.
*/
CV_EXPORTS_W Dictionary extendDictionary(int nMarkers, int markerSize, const Dictionary &baseDictionary = Dictionary(),
int randomSeed=0);
//! @}
}
}
#endif