Merge pull request #505 from jfolz:aruco-python

pull/519/head
Alexander Alekhin 9 years ago
commit f8205a7de5
  1. 109
      modules/aruco/include/opencv2/aruco.hpp
  2. 51
      modules/aruco/include/opencv2/aruco/charuco.hpp
  3. 61
      modules/aruco/include/opencv2/aruco/dictionary.hpp
  4. 51
      modules/aruco/samples/calibrate_camera.cpp
  5. 57
      modules/aruco/samples/calibrate_camera_charuco.cpp
  6. 6
      modules/aruco/samples/create_board.cpp
  7. 6
      modules/aruco/samples/create_board_charuco.cpp
  8. 2
      modules/aruco/samples/create_diamond.cpp
  9. 2
      modules/aruco/samples/create_marker.cpp
  10. 51
      modules/aruco/samples/detect_board.cpp
  11. 53
      modules/aruco/samples/detect_board_charuco.cpp
  12. 46
      modules/aruco/samples/detect_diamonds.cpp
  13. 48
      modules/aruco/samples/detect_markers.cpp
  14. 293
      modules/aruco/src/aruco.cpp
  15. 133
      modules/aruco/src/charuco.cpp
  16. 119
      modules/aruco/src/dictionary.cpp
  17. 55
      modules/aruco/test/test_arucodetection.cpp
  18. 50
      modules/aruco/test/test_boarddetection.cpp
  19. 56
      modules/aruco/test/test_charucodetection.cpp

@ -121,30 +121,32 @@ namespace aruco {
* - errorCorrectionRate error correction rate respect to the maximun error correction capability
* for each dictionary. (default 0.6).
*/
struct CV_EXPORTS DetectorParameters {
struct CV_EXPORTS_W DetectorParameters {
DetectorParameters();
int adaptiveThreshWinSizeMin;
int adaptiveThreshWinSizeMax;
int adaptiveThreshWinSizeStep;
double adaptiveThreshConstant;
double minMarkerPerimeterRate;
double maxMarkerPerimeterRate;
double polygonalApproxAccuracyRate;
double minCornerDistanceRate;
int minDistanceToBorder;
double minMarkerDistanceRate;
bool doCornerRefinement;
int cornerRefinementWinSize;
int cornerRefinementMaxIterations;
double cornerRefinementMinAccuracy;
int markerBorderBits;
int perspectiveRemovePixelPerCell;
double perspectiveRemoveIgnoredMarginPerCell;
double maxErroneousBitsInBorderRate;
double minOtsuStdDev;
double errorCorrectionRate;
CV_WRAP static Ptr<DetectorParameters> create();
CV_PROP_RW int adaptiveThreshWinSizeMin;
CV_PROP_RW int adaptiveThreshWinSizeMax;
CV_PROP_RW int adaptiveThreshWinSizeStep;
CV_PROP_RW double adaptiveThreshConstant;
CV_PROP_RW double minMarkerPerimeterRate;
CV_PROP_RW double maxMarkerPerimeterRate;
CV_PROP_RW double polygonalApproxAccuracyRate;
CV_PROP_RW double minCornerDistanceRate;
CV_PROP_RW int minDistanceToBorder;
CV_PROP_RW double minMarkerDistanceRate;
CV_PROP_RW bool doCornerRefinement;
CV_PROP_RW int cornerRefinementWinSize;
CV_PROP_RW int cornerRefinementMaxIterations;
CV_PROP_RW double cornerRefinementMinAccuracy;
CV_PROP_RW int markerBorderBits;
CV_PROP_RW int perspectiveRemovePixelPerCell;
CV_PROP_RW double perspectiveRemoveIgnoredMarginPerCell;
CV_PROP_RW double maxErroneousBitsInBorderRate;
CV_PROP_RW double minOtsuStdDev;
CV_PROP_RW double errorCorrectionRate;
};
@ -171,9 +173,9 @@ struct CV_EXPORTS DetectorParameters {
* @sa estimatePoseSingleMarkers, estimatePoseBoard
*
*/
CV_EXPORTS void detectMarkers(InputArray image, Dictionary dictionary, OutputArrayOfArrays corners,
OutputArray ids, DetectorParameters parameters = DetectorParameters(),
OutputArrayOfArrays rejectedImgPoints = noArray());
CV_EXPORTS_W void detectMarkers(InputArray image, Ptr<Dictionary> &dictionary, OutputArrayOfArrays corners,
OutputArray ids, const Ptr<DetectorParameters> &parameters = DetectorParameters::create(),
OutputArrayOfArrays rejectedImgPoints = noArray());
@ -205,9 +207,9 @@ CV_EXPORTS void detectMarkers(InputArray image, Dictionary dictionary, OutputArr
* (-markerLength/2, markerLength/2, 0), (markerLength/2, markerLength/2, 0),
* (markerLength/2, -markerLength/2, 0), (-markerLength/2, -markerLength/2, 0)
*/
CV_EXPORTS void estimatePoseSingleMarkers(InputArrayOfArrays corners, float markerLength,
InputArray cameraMatrix, InputArray distCoeffs,
OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs);
CV_EXPORTS_W void estimatePoseSingleMarkers(InputArrayOfArrays corners, float markerLength,
InputArray cameraMatrix, InputArray distCoeffs,
OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs);
@ -221,7 +223,7 @@ CV_EXPORTS void estimatePoseSingleMarkers(InputArrayOfArrays corners, float mark
* - The dictionary which indicates the type of markers of the board
* - The identifier of all the markers in the board.
*/
class CV_EXPORTS Board {
class CV_EXPORTS_W Board {
public:
// array of object points of all the marker corners in the board
@ -229,7 +231,7 @@ class CV_EXPORTS Board {
std::vector< std::vector< Point3f > > objPoints;
// the dictionary of markers employed for this board
Dictionary dictionary;
Ptr<Dictionary> dictionary;
// vector of the identifiers of the markers in the board (same size than objPoints)
// The identifiers refers to the board dictionary
@ -243,7 +245,7 @@ class CV_EXPORTS Board {
* More common type of board. All markers are placed in the same plane in a grid arrangment.
* The board can be drawn using drawPlanarBoard() function (@sa drawPlanarBoard)
*/
class CV_EXPORTS GridBoard : public Board {
class CV_EXPORTS_W GridBoard : public Board {
public:
/**
@ -274,8 +276,8 @@ class CV_EXPORTS GridBoard : public Board {
* This functions creates a GridBoard object given the number of markers in each direction and
* the marker size and marker separation.
*/
static GridBoard create(int markersX, int markersY, float markerLength, float markerSeparation,
Dictionary dictionary);
CV_WRAP static Ptr<GridBoard> create(int markersX, int markersY, float markerLength,
float markerSeparation, Ptr<Dictionary> &dictionary);
/**
*
@ -332,9 +334,9 @@ class CV_EXPORTS GridBoard : public Board {
* The function returns the number of markers from the input employed for the board pose estimation.
* Note that returning a 0 means the pose has not been estimated.
*/
CV_EXPORTS int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, const Board &board,
InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec,
OutputArray tvec);
CV_EXPORTS_W int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, Ptr<Board> &board,
InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec,
OutputArray tvec);
@ -370,12 +372,12 @@ CV_EXPORTS int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, con
* 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_EXPORTS void refineDetectedMarkers(
InputArray image, const Board &board, InputOutputArrayOfArrays detectedCorners,
CV_EXPORTS_W void refineDetectedMarkers(
InputArray image, Ptr<Board> &board, InputOutputArrayOfArrays detectedCorners,
InputOutputArray detectedIds, InputOutputArray rejectedCorners,
InputArray cameraMatrix = noArray(), InputArray distCoeffs = noArray(),
float minRepDistance = 10.f, float errorCorrectionRate = 3.f, bool checkAllOrders = true,
OutputArray recoveredIdxs = noArray(), DetectorParameters parameters = DetectorParameters());
OutputArray recoveredIdxs = noArray(), const Ptr<DetectorParameters> &parameters = DetectorParameters::create());
@ -396,9 +398,9 @@ CV_EXPORTS void refineDetectedMarkers(
* the markers in the image. The marker borders are painted and the markers identifiers if provided.
* Useful for debugging purposes.
*/
CV_EXPORTS void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays corners,
InputArray ids = noArray(),
Scalar borderColor = Scalar(0, 255, 0));
CV_EXPORTS_W void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays corners,
InputArray ids = noArray(),
Scalar borderColor = Scalar(0, 255, 0));
@ -418,8 +420,8 @@ CV_EXPORTS void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays c
* Given the pose estimation of a marker or board, this function draws the axis of the world
* coordinate system, i.e. the system centered on the marker/board. Useful for debugging purposes.
*/
CV_EXPORTS void drawAxis(InputOutputArray image, InputArray cameraMatrix, InputArray distCoeffs,
InputArray rvec, InputArray tvec, float length);
CV_EXPORTS_W void drawAxis(InputOutputArray image, InputArray cameraMatrix, InputArray distCoeffs,
InputArray rvec, InputArray tvec, float length);
@ -435,13 +437,14 @@ CV_EXPORTS void drawAxis(InputOutputArray image, InputArray cameraMatrix, InputA
*
* This function returns a marker image in its canonical form (i.e. ready to be printed)
*/
CV_EXPORTS void drawMarker(Dictionary dictionary, int id, int sidePixels, OutputArray img,
int borderBits = 1);
CV_EXPORTS_W void drawMarker(Ptr<Dictionary> &dictionary, int id, int sidePixels, OutputArray img,
int borderBits = 1);
/**
* @brief Draw a planar board
* @sa _drawPlanarBoardImpl
*
* @param board layout of the board that will be drawn. The board should be planar,
* z coordinate is ignored
@ -454,8 +457,16 @@ CV_EXPORTS void drawMarker(Dictionary dictionary, int id, int sidePixels, Output
* This function return the image of a planar board, ready to be printed. It assumes
* the Board layout specified is planar by ignoring the z coordinates of the object points.
*/
CV_EXPORTS void drawPlanarBoard(const Board &board, Size outSize, OutputArray img,
int marginSize = 0, int borderBits = 1);
CV_EXPORTS_W void drawPlanarBoard(Ptr<Board> &board, Size outSize, OutputArray img,
int marginSize = 0, int borderBits = 1);
/**
* @brief Implementation of drawPlanarBoard that accepts a raw Board pointer.
*/
void _drawPlanarBoardImpl(Board *board, Size outSize, OutputArray img,
int marginSize = 0, int borderBits = 1);
@ -487,8 +498,8 @@ CV_EXPORTS void drawPlanarBoard(const Board &board, Size outSize, OutputArray im
* detected markers from several views of the Board. The process is similar to the chessboard
* calibration in calibrateCamera(). The function returns the final re-projection error.
*/
CV_EXPORTS double calibrateCameraAruco(
InputArrayOfArrays corners, InputArray ids, InputArray counter, const Board &board,
CV_EXPORTS_W double calibrateCameraAruco(
InputArrayOfArrays corners, InputArray ids, InputArray counter, Ptr<Board> &board,
Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(), int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON));

@ -59,7 +59,7 @@ namespace aruco {
* calibration and pose estimation.
* This class also allows the easy creation and drawing of ChArUco boards.
*/
class CV_EXPORTS CharucoBoard : public Board {
class CV_EXPORTS_W CharucoBoard : public Board {
public:
// vector of chessboard 3D corners precalculated
@ -97,8 +97,8 @@ class CV_EXPORTS CharucoBoard : public Board {
* This functions creates a CharucoBoard object given the number of squares in each direction
* and the size of the markers and chessboard squares.
*/
static CharucoBoard create(int squaresX, int squaresY, float squareLength, float markerLength,
Dictionary dictionary);
CV_WRAP static Ptr<CharucoBoard> create(int squaresX, int squaresY, float squareLength,
float markerLength, Ptr<Dictionary> &dictionary);
/**
*
@ -154,11 +154,11 @@ class CV_EXPORTS CharucoBoard : public Board {
* also returned in charucoIds.
* The function returns the number of interpolated corners.
*/
CV_EXPORTS int interpolateCornersCharuco(InputArrayOfArrays markerCorners, InputArray markerIds,
InputArray image, const CharucoBoard &board,
OutputArray charucoCorners, OutputArray charucoIds,
InputArray cameraMatrix = noArray(),
InputArray distCoeffs = noArray());
CV_EXPORTS_W int interpolateCornersCharuco(InputArrayOfArrays markerCorners, InputArray markerIds,
InputArray image, Ptr<CharucoBoard> &board,
OutputArray charucoCorners, OutputArray charucoIds,
InputArray cameraMatrix = noArray(),
InputArray distCoeffs = noArray());
@ -180,9 +180,9 @@ CV_EXPORTS int interpolateCornersCharuco(InputArrayOfArrays markerCorners, Input
* The function checks if the input corners are enough and valid to perform pose estimation.
* If pose estimation is valid, returns true, else returns false.
*/
CV_EXPORTS bool estimatePoseCharucoBoard(InputArray charucoCorners, InputArray charucoIds,
CharucoBoard &board, InputArray cameraMatrix,
InputArray distCoeffs, OutputArray rvec, OutputArray tvec);
CV_EXPORTS_W bool estimatePoseCharucoBoard(InputArray charucoCorners, InputArray charucoIds,
Ptr<CharucoBoard> &board, InputArray cameraMatrix,
InputArray distCoeffs, OutputArray rvec, OutputArray tvec);
@ -198,9 +198,9 @@ CV_EXPORTS bool estimatePoseCharucoBoard(InputArray charucoCorners, InputArray c
* This function draws a set of detected Charuco corners. If identifiers vector is provided, it also
* draws the id of each corner.
*/
CV_EXPORTS void drawDetectedCornersCharuco(InputOutputArray image, InputArray charucoCorners,
InputArray charucoIds = noArray(),
Scalar cornerColor = Scalar(255, 0, 0));
CV_EXPORTS_W void drawDetectedCornersCharuco(InputOutputArray image, InputArray charucoCorners,
InputArray charucoIds = noArray(),
Scalar cornerColor = Scalar(255, 0, 0));
@ -230,8 +230,8 @@ CV_EXPORTS void drawDetectedCornersCharuco(InputOutputArray image, InputArray ch
* receives a list of detected corners and its identifiers from several views of the Board.
* The function returns the final re-projection error.
*/
CV_EXPORTS double calibrateCameraCharuco(
InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds, const CharucoBoard &board,
CV_EXPORTS_W double calibrateCameraCharuco(
InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds, Ptr<CharucoBoard> &board,
Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(), int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON));
@ -261,11 +261,11 @@ CV_EXPORTS double calibrateCameraCharuco(
* are provided, the diamond search is based on reprojection. If not, diamond search is based on
* homography. Homography is faster than reprojection but can slightly reduce the detection rate.
*/
CV_EXPORTS void detectCharucoDiamond(InputArray image, InputArrayOfArrays markerCorners,
InputArray markerIds, float squareMarkerLengthRate,
OutputArrayOfArrays diamondCorners, OutputArray diamondIds,
InputArray cameraMatrix = noArray(),
InputArray distCoeffs = noArray());
CV_EXPORTS_W void detectCharucoDiamond(InputArray image, InputArrayOfArrays markerCorners,
InputArray markerIds, float squareMarkerLengthRate,
OutputArrayOfArrays diamondCorners, OutputArray diamondIds,
InputArray cameraMatrix = noArray(),
InputArray distCoeffs = noArray());
@ -287,9 +287,9 @@ CV_EXPORTS void detectCharucoDiamond(InputArray image, InputArrayOfArrays marker
* are painted and the markers identifiers if provided.
* Useful for debugging purposes.
*/
CV_EXPORTS void drawDetectedDiamonds(InputOutputArray image, InputArrayOfArrays diamondCorners,
InputArray diamondIds = noArray(),
Scalar borderColor = Scalar(0, 0, 255));
CV_EXPORTS_W void drawDetectedDiamonds(InputOutputArray image, InputArrayOfArrays diamondCorners,
InputArray diamondIds = noArray(),
Scalar borderColor = Scalar(0, 0, 255));
@ -308,7 +308,8 @@ CV_EXPORTS void drawDetectedDiamonds(InputOutputArray image, InputArrayOfArrays
*
* This function return the image of a ChArUco marker, ready to be printed.
*/
CV_EXPORTS void drawCharucoDiamond(Dictionary dictionary, Vec4i ids, int squareLength,
// TODO cannot be exported yet; conversion from/to Vec4i is not wrapped in core
CV_EXPORTS void drawCharucoDiamond(Ptr<Dictionary> &dictionary, Vec4i ids, int squareLength,
int markerLength, OutputArray img, int marginSize = 0,
int borderBits = 1);

@ -58,12 +58,12 @@ namespace aruco {
*
* `bytesList.ptr(i)[k*nbytes + j]` is then the j-th byte of i-th marker, in its k-th rotation.
*/
class CV_EXPORTS Dictionary {
class CV_EXPORTS_W Dictionary {
public:
Mat bytesList; // marker code information
int markerSize; // number of bits per dimension
int maxCorrectionBits; // maximum number of bits that can be corrected
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
/**
@ -71,6 +71,32 @@ class CV_EXPORTS Dictionary {
Dictionary(const Mat &_bytesList = Mat(), int _markerSize = 0, int _maxcorr = 0);
/**
Dictionary(const Dictionary &_dictionary);
*/
/**
*/
Dictionary(const Ptr<Dictionary> &_dictionary);
/**
* @see generateCustomDictionary
*/
CV_WRAP_AS(create) static Ptr<Dictionary> create(int nMarkers, int markerSize);
/**
* @see generateCustomDictionary
*/
CV_WRAP_AS(create_from) static Ptr<Dictionary> create(int nMarkers, int markerSize,
Ptr<Dictionary> &baseDictionary);
/**
* @see getPredefinedDictionary
*/
CV_WRAP static Ptr<Dictionary> get(int dict);
/**
* @brief Given a matrix of bits. Returns whether if marker is identified or not.
@ -109,9 +135,10 @@ class CV_EXPORTS Dictionary {
/**
* @brief Predefined markers dictionaries/sets
* Each dictionary indicates the number of bits and the number of markers contained
* - DICT_ARUCO: standard ArUco Library Markers. 1024 markers, 5x5 bits, 0 minimum distance
* - DICT_ARUCO_ORIGINAL: standard ArUco Library Markers. 1024 markers, 5x5 bits, 0 minimum
distance
*/
enum PREDEFINED_DICTIONARY_NAME {
enum CV_EXPORTS_W_SIMPLE PREDEFINED_DICTIONARY_NAME {
DICT_4X4_50 = 0,
DICT_4X4_100,
DICT_4X4_250,
@ -135,7 +162,21 @@ enum PREDEFINED_DICTIONARY_NAME {
/**
* @brief Returns one of the predefined dictionaries defined in PREDEFINED_DICTIONARY_NAME
*/
CV_EXPORTS const Dictionary &getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name);
CV_EXPORTS Ptr<Dictionary> getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name);
/**
* @brief Returns one of the predefined dictionaries referenced by DICT_*.
*/
CV_EXPORTS_W Ptr<Dictionary> getPredefinedDictionary(int dict);
/**
* @see generateCustomDictionary
*/
CV_EXPORTS_AS(custom_dictionary) Ptr<Dictionary> generateCustomDictionary(
int nMarkers,
int markerSize);
/**
@ -150,8 +191,10 @@ CV_EXPORTS const Dictionary &getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME
* 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 Dictionary generateCustomDictionary(int nMarkers, int markerSize,
const Dictionary &baseDictionary = Dictionary());
CV_EXPORTS_AS(custom_dictionary_from) Ptr<Dictionary> generateCustomDictionary(
int nMarkers,
int markerSize,
Ptr<Dictionary> &baseDictionary);

@ -76,30 +76,30 @@ const char* keys =
/**
*/
static bool readDetectorParameters(string filename, aruco::DetectorParameters &params) {
static bool readDetectorParameters(string filename, Ptr<aruco::DetectorParameters> &params) {
FileStorage fs(filename, FileStorage::READ);
if(!fs.isOpened())
return false;
fs["adaptiveThreshWinSizeMin"] >> params.adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params.adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params.adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params.adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params.minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params.maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params.polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params.minCornerDistanceRate;
fs["minDistanceToBorder"] >> params.minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params.minMarkerDistanceRate;
fs["doCornerRefinement"] >> params.doCornerRefinement;
fs["cornerRefinementWinSize"] >> params.cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params.cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params.cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params.markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params.perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params.perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params.maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params.minOtsuStdDev;
fs["errorCorrectionRate"] >> params.errorCorrectionRate;
fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;
fs["minDistanceToBorder"] >> params->minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;
fs["doCornerRefinement"] >> params->doCornerRefinement;
fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params->markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params->minOtsuStdDev;
fs["errorCorrectionRate"] >> params->errorCorrectionRate;
return true;
}
@ -173,7 +173,7 @@ int main(int argc, char *argv[]) {
if(parser.get<bool>("zt")) calibrationFlags |= CALIB_ZERO_TANGENT_DIST;
if(parser.get<bool>("pc")) calibrationFlags |= CALIB_FIX_PRINCIPAL_POINT;
aruco::DetectorParameters detectorParams;
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
if(parser.has("dp")) {
bool readOk = readDetectorParameters(parser.get<string>("dp"), detectorParams);
if(!readOk) {
@ -205,12 +205,13 @@ int main(int argc, char *argv[]) {
waitTime = 10;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
// create board object
aruco::GridBoard board =
aruco::GridBoard::create(markersX, markersY, markerLength, markerSeparation, dictionary);
Ptr<aruco::GridBoard> gridboard =
aruco::GridBoard::create(markersX, markersY, markerLength, markerSeparation, dictionary);
Ptr<aruco::Board> board = gridboard.staticCast<aruco::Board>();
// collected frames for calibration
vector< vector< vector< Point2f > > > allCorners;

@ -76,30 +76,30 @@ const char* keys =
/**
*/
static bool readDetectorParameters(string filename, aruco::DetectorParameters &params) {
static bool readDetectorParameters(string filename, Ptr<aruco::DetectorParameters> &params) {
FileStorage fs(filename, FileStorage::READ);
if(!fs.isOpened())
return false;
fs["adaptiveThreshWinSizeMin"] >> params.adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params.adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params.adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params.adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params.minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params.maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params.polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params.minCornerDistanceRate;
fs["minDistanceToBorder"] >> params.minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params.minMarkerDistanceRate;
fs["doCornerRefinement"] >> params.doCornerRefinement;
fs["cornerRefinementWinSize"] >> params.cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params.cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params.cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params.markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params.perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params.perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params.maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params.minOtsuStdDev;
fs["errorCorrectionRate"] >> params.errorCorrectionRate;
fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;
fs["minDistanceToBorder"] >> params->minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;
fs["doCornerRefinement"] >> params->doCornerRefinement;
fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params->markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params->minOtsuStdDev;
fs["errorCorrectionRate"] >> params->errorCorrectionRate;
return true;
}
@ -175,7 +175,7 @@ int main(int argc, char *argv[]) {
if(parser.get<bool>("zt")) calibrationFlags |= CALIB_ZERO_TANGENT_DIST;
if(parser.get<bool>("pc")) calibrationFlags |= CALIB_FIX_PRINCIPAL_POINT;
aruco::DetectorParameters detectorParams;
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
if(parser.has("dp")) {
bool readOk = readDetectorParameters(parser.get<string>("dp"), detectorParams);
if(!readOk) {
@ -207,12 +207,13 @@ int main(int argc, char *argv[]) {
waitTime = 10;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
// create charuco board object
aruco::CharucoBoard board =
aruco::CharucoBoard::create(squaresX, squaresY, squareLength, markerLength, dictionary);
Ptr<aruco::CharucoBoard> charucoboard =
aruco::CharucoBoard::create(squaresX, squaresY, squareLength, markerLength, dictionary);
Ptr<aruco::Board> board = charucoboard.staticCast<aruco::Board>();
// collect data from each frame
vector< vector< vector< Point2f > > > allCorners;
@ -236,7 +237,7 @@ int main(int argc, char *argv[]) {
// interpolate charuco corners
Mat currentCharucoCorners, currentCharucoIds;
if(ids.size() > 0)
aruco::interpolateCornersCharuco(corners, ids, image, board, currentCharucoCorners,
aruco::interpolateCornersCharuco(corners, ids, image, charucoboard, currentCharucoCorners,
currentCharucoIds);
// draw results
@ -305,7 +306,7 @@ int main(int argc, char *argv[]) {
for(int i = 0; i < nFrames; i++) {
// interpolate using camera parameters
Mat currentCharucoCorners, currentCharucoIds;
aruco::interpolateCornersCharuco(allCorners[i], allIds[i], allImgs[i], board,
aruco::interpolateCornersCharuco(allCorners[i], allIds[i], allImgs[i], charucoboard,
currentCharucoCorners, currentCharucoIds, cameraMatrix,
distCoeffs);
@ -321,7 +322,7 @@ int main(int argc, char *argv[]) {
// calibrate camera using charuco
repError =
aruco::calibrateCameraCharuco(allCharucoCorners, allCharucoIds, board, imgSize,
aruco::calibrateCameraCharuco(allCharucoCorners, allCharucoIds, charucoboard, imgSize,
cameraMatrix, distCoeffs, rvecs, tvecs, calibrationFlags);
bool saveOk = saveCameraParams(outputFile, imgSize, aspectRatio, calibrationFlags,

@ -93,15 +93,15 @@ int main(int argc, char *argv[]) {
imageSize.height =
markersY * (markerLength + markerSeparation) - markerSeparation + 2 * margins;
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
aruco::GridBoard board = aruco::GridBoard::create(markersX, markersY, float(markerLength),
Ptr<aruco::GridBoard> board = aruco::GridBoard::create(markersX, markersY, float(markerLength),
float(markerSeparation), dictionary);
// show created board
Mat boardImage;
board.draw(imageSize, boardImage, margins, borderBits);
board->draw(imageSize, boardImage, margins, borderBits);
if(showImage) {
imshow("board", boardImage);

@ -88,19 +88,19 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
Size imageSize;
imageSize.width = squaresX * squareLength + 2 * margins;
imageSize.height = squaresY * squareLength + 2 * margins;
aruco::CharucoBoard board = aruco::CharucoBoard::create(squaresX, squaresY, (float)squareLength,
Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create(squaresX, squaresY, (float)squareLength,
(float)markerLength, dictionary);
// show created board
Mat boardImage;
board.draw(imageSize, boardImage, margins, borderBits);
board->draw(imageSize, boardImage, margins, borderBits);
if(showImage) {
imshow("board", boardImage);

@ -86,7 +86,7 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
istringstream ss(idsString);

@ -79,7 +79,7 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
Mat markerImg;

@ -79,30 +79,30 @@ static bool readCameraParameters(string filename, Mat &camMatrix, Mat &distCoeff
/**
*/
static bool readDetectorParameters(string filename, aruco::DetectorParameters &params) {
static bool readDetectorParameters(string filename, Ptr<aruco::DetectorParameters> &params) {
FileStorage fs(filename, FileStorage::READ);
if(!fs.isOpened())
return false;
fs["adaptiveThreshWinSizeMin"] >> params.adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params.adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params.adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params.adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params.minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params.maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params.polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params.minCornerDistanceRate;
fs["minDistanceToBorder"] >> params.minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params.minMarkerDistanceRate;
fs["doCornerRefinement"] >> params.doCornerRefinement;
fs["cornerRefinementWinSize"] >> params.cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params.cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params.cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params.markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params.perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params.perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params.maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params.minOtsuStdDev;
fs["errorCorrectionRate"] >> params.errorCorrectionRate;
fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;
fs["minDistanceToBorder"] >> params->minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;
fs["doCornerRefinement"] >> params->doCornerRefinement;
fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params->markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params->minOtsuStdDev;
fs["errorCorrectionRate"] >> params->errorCorrectionRate;
return true;
}
@ -137,7 +137,7 @@ int main(int argc, char *argv[]) {
}
}
aruco::DetectorParameters detectorParams;
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
if(parser.has("dp")) {
bool readOk = readDetectorParameters(parser.get<string>("dp"), detectorParams);
if(!readOk) {
@ -145,7 +145,7 @@ int main(int argc, char *argv[]) {
return 0;
}
}
detectorParams.doCornerRefinement = true; // do corner refinement in markers
detectorParams->doCornerRefinement = true; // do corner refinement in markers
String video;
if(parser.has("v")) {
@ -157,7 +157,7 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
VideoCapture inputVideo;
@ -174,8 +174,9 @@ int main(int argc, char *argv[]) {
markerSeparation);
// create board object
aruco::GridBoard board =
Ptr<aruco::GridBoard> gridboard =
aruco::GridBoard::create(markersX, markersY, markerLength, markerSeparation, dictionary);
Ptr<aruco::Board> board = gridboard.staticCast<aruco::Board>();
double totalTime = 0;
int totalIterations = 0;

@ -79,30 +79,30 @@ static bool readCameraParameters(string filename, Mat &camMatrix, Mat &distCoeff
/**
*/
static bool readDetectorParameters(string filename, aruco::DetectorParameters &params) {
static bool readDetectorParameters(string filename, Ptr<aruco::DetectorParameters> &params) {
FileStorage fs(filename, FileStorage::READ);
if(!fs.isOpened())
return false;
fs["adaptiveThreshWinSizeMin"] >> params.adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params.adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params.adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params.adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params.minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params.maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params.polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params.minCornerDistanceRate;
fs["minDistanceToBorder"] >> params.minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params.minMarkerDistanceRate;
fs["doCornerRefinement"] >> params.doCornerRefinement;
fs["cornerRefinementWinSize"] >> params.cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params.cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params.cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params.markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params.perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params.perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params.maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params.minOtsuStdDev;
fs["errorCorrectionRate"] >> params.errorCorrectionRate;
fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;
fs["minDistanceToBorder"] >> params->minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;
fs["doCornerRefinement"] >> params->doCornerRefinement;
fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params->markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params->minOtsuStdDev;
fs["errorCorrectionRate"] >> params->errorCorrectionRate;
return true;
}
@ -141,7 +141,7 @@ int main(int argc, char *argv[]) {
}
}
aruco::DetectorParameters detectorParams;
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
if(parser.has("dp")) {
bool readOk = readDetectorParameters(parser.get<string>("dp"), detectorParams);
if(!readOk) {
@ -155,7 +155,7 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
VideoCapture inputVideo;
@ -171,8 +171,9 @@ int main(int argc, char *argv[]) {
float axisLength = 0.5f * ((float)min(squaresX, squaresY) * (squareLength));
// create charuco board object
aruco::CharucoBoard board =
Ptr<aruco::CharucoBoard> charucoboard =
aruco::CharucoBoard::create(squaresX, squaresY, squareLength, markerLength, dictionary);
Ptr<aruco::Board> board = charucoboard.staticCast<aruco::Board>();
double totalTime = 0;
int totalIterations = 0;
@ -201,13 +202,13 @@ int main(int argc, char *argv[]) {
int interpolatedCorners = 0;
if(markerIds.size() > 0)
interpolatedCorners =
aruco::interpolateCornersCharuco(markerCorners, markerIds, image, board,
aruco::interpolateCornersCharuco(markerCorners, markerIds, image, charucoboard,
charucoCorners, charucoIds, camMatrix, distCoeffs);
// estimate charuco board pose
bool validPose = false;
if(camMatrix.total() != 0)
validPose = aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, board,
validPose = aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, charucoboard,
camMatrix, distCoeffs, rvec, tvec);

@ -80,30 +80,30 @@ static bool readCameraParameters(string filename, Mat &camMatrix, Mat &distCoeff
/**
*/
static bool readDetectorParameters(string filename, aruco::DetectorParameters &params) {
static bool readDetectorParameters(string filename, Ptr<aruco::DetectorParameters> &params) {
FileStorage fs(filename, FileStorage::READ);
if(!fs.isOpened())
return false;
fs["adaptiveThreshWinSizeMin"] >> params.adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params.adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params.adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params.adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params.minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params.maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params.polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params.minCornerDistanceRate;
fs["minDistanceToBorder"] >> params.minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params.minMarkerDistanceRate;
fs["doCornerRefinement"] >> params.doCornerRefinement;
fs["cornerRefinementWinSize"] >> params.cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params.cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params.cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params.markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params.perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params.perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params.maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params.minOtsuStdDev;
fs["errorCorrectionRate"] >> params.errorCorrectionRate;
fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;
fs["minDistanceToBorder"] >> params->minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;
fs["doCornerRefinement"] >> params->doCornerRefinement;
fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params->markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params->minOtsuStdDev;
fs["errorCorrectionRate"] >> params->errorCorrectionRate;
return true;
}
@ -127,7 +127,7 @@ int main(int argc, char *argv[]) {
bool autoScale = parser.has("as");
float autoScaleFactor = autoScale ? parser.get<float>("as") : 1.f;
aruco::DetectorParameters detectorParams;
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
if(parser.has("dp")) {
bool readOk = readDetectorParameters(parser.get<string>("dp"), detectorParams);
if(!readOk) {
@ -148,7 +148,7 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
Mat camMatrix, distCoeffs;

@ -74,30 +74,30 @@ static bool readCameraParameters(string filename, Mat &camMatrix, Mat &distCoeff
/**
*/
static bool readDetectorParameters(string filename, aruco::DetectorParameters &params) {
static bool readDetectorParameters(string filename, Ptr<aruco::DetectorParameters> &params) {
FileStorage fs(filename, FileStorage::READ);
if(!fs.isOpened())
return false;
fs["adaptiveThreshWinSizeMin"] >> params.adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params.adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params.adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params.adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params.minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params.maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params.polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params.minCornerDistanceRate;
fs["minDistanceToBorder"] >> params.minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params.minMarkerDistanceRate;
fs["doCornerRefinement"] >> params.doCornerRefinement;
fs["cornerRefinementWinSize"] >> params.cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params.cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params.cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params.markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params.perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params.perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params.maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params.minOtsuStdDev;
fs["errorCorrectionRate"] >> params.errorCorrectionRate;
fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;
fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;
fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;
fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;
fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;
fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;
fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;
fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;
fs["minDistanceToBorder"] >> params->minDistanceToBorder;
fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;
fs["doCornerRefinement"] >> params->doCornerRefinement;
fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;
fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;
fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;
fs["markerBorderBits"] >> params->markerBorderBits;
fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;
fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;
fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;
fs["minOtsuStdDev"] >> params->minOtsuStdDev;
fs["errorCorrectionRate"] >> params->errorCorrectionRate;
return true;
}
@ -119,7 +119,7 @@ int main(int argc, char *argv[]) {
bool estimatePose = parser.has("c");
float markerLength = parser.get<float>("l");
aruco::DetectorParameters detectorParams;
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
if(parser.has("dp")) {
bool readOk = readDetectorParameters(parser.get<string>("dp"), detectorParams);
if(!readOk) {
@ -127,7 +127,7 @@ int main(int argc, char *argv[]) {
return 0;
}
}
detectorParams.doCornerRefinement = true; // do corner refinement in markers
detectorParams->doCornerRefinement = true; // do corner refinement in markers
int camId = parser.get<int>("ci");
@ -141,7 +141,7 @@ int main(int argc, char *argv[]) {
return 0;
}
aruco::Dictionary dictionary =
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
Mat camMatrix, distCoeffs;

@ -76,6 +76,15 @@ DetectorParameters::DetectorParameters()
errorCorrectionRate(0.6) {}
/**
* @brief Create a new set of DetectorParameters with default values.
*/
Ptr<DetectorParameters> DetectorParameters::create() {
Ptr<DetectorParameters> params = makePtr<DetectorParameters>();
return params;
}
/**
* @brief Convert input image to gray if it is a 3-channels image
*/
@ -267,7 +276,7 @@ class DetectInitialCandidatesParallel : public ParallelLoopBody {
DetectInitialCandidatesParallel(const Mat *_grey,
vector< vector< vector< Point2f > > > *_candidatesArrays,
vector< vector< vector< Point > > > *_contoursArrays,
DetectorParameters *_params)
const Ptr<DetectorParameters> &_params)
: grey(_grey), candidatesArrays(_candidatesArrays), contoursArrays(_contoursArrays),
params(_params) {}
@ -296,7 +305,7 @@ class DetectInitialCandidatesParallel : public ParallelLoopBody {
const Mat *grey;
vector< vector< vector< Point2f > > > *candidatesArrays;
vector< vector< vector< Point > > > *contoursArrays;
DetectorParameters *params;
const Ptr<DetectorParameters> &params;
};
@ -305,15 +314,15 @@ class DetectInitialCandidatesParallel : public ParallelLoopBody {
*/
static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f > > &candidates,
vector< vector< Point > > &contours,
DetectorParameters params) {
const Ptr<DetectorParameters> &params) {
CV_Assert(params.adaptiveThreshWinSizeMin >= 3 && params.adaptiveThreshWinSizeMax >= 3);
CV_Assert(params.adaptiveThreshWinSizeMax >= params.adaptiveThreshWinSizeMin);
CV_Assert(params.adaptiveThreshWinSizeStep > 0);
CV_Assert(params->adaptiveThreshWinSizeMin >= 3 && params->adaptiveThreshWinSizeMax >= 3);
CV_Assert(params->adaptiveThreshWinSizeMax >= params->adaptiveThreshWinSizeMin);
CV_Assert(params->adaptiveThreshWinSizeStep > 0);
// number of window sizes (scales) to apply adaptive thresholding
int nScales = (params.adaptiveThreshWinSizeMax - params.adaptiveThreshWinSizeMin) /
params.adaptiveThreshWinSizeStep + 1;
int nScales = (params->adaptiveThreshWinSizeMax - params->adaptiveThreshWinSizeMin) /
params->adaptiveThreshWinSizeStep + 1;
vector< vector< vector< Point2f > > > candidatesArrays((size_t) nScales);
vector< vector< vector< Point > > > contoursArrays((size_t) nScales);
@ -333,7 +342,7 @@ static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f >
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, nScales), DetectInitialCandidatesParallel(&grey, &candidatesArrays,
&contoursArrays, &params));
&contoursArrays, params));
// join candidates
for(int i = 0; i < nScales; i++) {
@ -349,7 +358,7 @@ static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f >
* @brief Detect square candidates in the input image
*/
static void _detectCandidates(InputArray _image, OutputArrayOfArrays _candidates,
OutputArrayOfArrays _contours, DetectorParameters params) {
OutputArrayOfArrays _contours, const Ptr<DetectorParameters> &_params) {
Mat image = _image.getMat();
CV_Assert(image.total() != 0);
@ -361,7 +370,7 @@ static void _detectCandidates(InputArray _image, OutputArrayOfArrays _candidates
vector< vector< Point2f > > candidates;
vector< vector< Point > > contours;
/// 2. DETECT FIRST SET OF CANDIDATES
_detectInitialCandidates(grey, candidates, contours, params);
_detectInitialCandidates(grey, candidates, contours, _params);
/// 3. SORT CORNERS
_reorderCandidatesCorners(candidates);
@ -370,7 +379,7 @@ static void _detectCandidates(InputArray _image, OutputArrayOfArrays _candidates
vector< vector< Point2f > > candidatesOut;
vector< vector< Point > > contoursOut;
_filterTooCloseCandidates(candidates, candidatesOut, contours, contoursOut,
params.minMarkerDistanceRate);
_params->minMarkerDistanceRate);
// parse output
_candidates.create((int)candidatesOut.size(), 1, CV_32FC2);
@ -489,35 +498,35 @@ static int _getBorderErrors(const Mat &bits, int markerSize, int borderSize) {
/**
* @brief Tries to identify one candidate given the dictionary
*/
static bool _identifyOneCandidate(const Dictionary &dictionary, InputArray _image,
InputOutputArray _corners, int &idx, DetectorParameters params) {
static bool _identifyOneCandidate(Ptr<Dictionary> &dictionary, InputArray _image,
InputOutputArray _corners, int &idx, const Ptr<DetectorParameters> &params) {
CV_Assert(_corners.total() == 4);
CV_Assert(_image.getMat().total() != 0);
CV_Assert(params.markerBorderBits > 0);
CV_Assert(params->markerBorderBits > 0);
// get bits
Mat candidateBits =
_extractBits(_image, _corners, dictionary.markerSize, params.markerBorderBits,
params.perspectiveRemovePixelPerCell,
params.perspectiveRemoveIgnoredMarginPerCell, params.minOtsuStdDev);
_extractBits(_image, _corners, dictionary->markerSize, params->markerBorderBits,
params->perspectiveRemovePixelPerCell,
params->perspectiveRemoveIgnoredMarginPerCell, params->minOtsuStdDev);
// analyze border bits
int maximumErrorsInBorder =
int(dictionary.markerSize * dictionary.markerSize * params.maxErroneousBitsInBorderRate);
int(dictionary->markerSize * dictionary->markerSize * params->maxErroneousBitsInBorderRate);
int borderErrors =
_getBorderErrors(candidateBits, dictionary.markerSize, params.markerBorderBits);
_getBorderErrors(candidateBits, dictionary->markerSize, params->markerBorderBits);
if(borderErrors > maximumErrorsInBorder) return false; // border is wrong
// take only inner bits
Mat onlyBits =
candidateBits.rowRange(params.markerBorderBits,
candidateBits.rows - params.markerBorderBits)
.colRange(params.markerBorderBits, candidateBits.rows - params.markerBorderBits);
candidateBits.rowRange(params->markerBorderBits,
candidateBits.rows - params->markerBorderBits)
.colRange(params->markerBorderBits, candidateBits.rows - params->markerBorderBits);
// try to indentify the marker
int rotation;
if(!dictionary.identify(onlyBits, idx, rotation, params.errorCorrectionRate))
if(!dictionary->identify(onlyBits, idx, rotation, params->errorCorrectionRate))
return false;
else {
// shift corner positions to the correct rotation
@ -539,9 +548,9 @@ static bool _identifyOneCandidate(const Dictionary &dictionary, InputArray _imag
class IdentifyCandidatesParallel : public ParallelLoopBody {
public:
IdentifyCandidatesParallel(const Mat *_grey, InputArrayOfArrays _candidates,
InputArrayOfArrays _contours, const Dictionary *_dictionary,
InputArrayOfArrays _contours, Ptr<Dictionary> &_dictionary,
vector< int > *_idsTmp, vector< char > *_validCandidates,
DetectorParameters *_params)
const Ptr<DetectorParameters> &_params)
: grey(_grey), candidates(_candidates), contours(_contours), dictionary(_dictionary),
idsTmp(_idsTmp), validCandidates(_validCandidates), params(_params) {}
@ -552,7 +561,7 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
for(int i = begin; i < end; i++) {
int currId;
Mat currentCandidate = candidates.getMat(i);
if(_identifyOneCandidate(*dictionary, *grey, currentCandidate, currId, *params)) {
if(_identifyOneCandidate(dictionary, *grey, currentCandidate, currId, params)) {
(*validCandidates)[i] = 1;
(*idsTmp)[i] = currId;
}
@ -564,21 +573,65 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
const Mat *grey;
InputArrayOfArrays candidates, contours;
const Dictionary *dictionary;
Ptr<Dictionary> &dictionary;
vector< int > *idsTmp;
vector< char > *validCandidates;
DetectorParameters *params;
const Ptr<DetectorParameters> &params;
};
/**
* @brief Copy the contents of a Mat vector to an OutputArray, settings its size.
*/
void _copyVector2Output(vector< Mat > &vec, OutputArrayOfArrays out);
/**
*
*/
void _copyVector2Output(vector< Mat > &vec, OutputArrayOfArrays out) {
out.release();
out.create((int)vec.size(), 1, CV_32FC2);
if(out.isMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(4, 1, CV_32FC2, i, true);
Mat &m = out.getMatRef(i);
vec[i].copyTo(m);
}
}
else if(out.isUMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(4, 1, CV_32FC2, i, true);
UMat &m = out.getUMatRef(i);
vec[i].copyTo(m);
}
}
else if(out.kind() == _OutputArray::STD_VECTOR_VECTOR){
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(4, 1, CV_32FC2, i, true);
Mat m = out.getMat(i);
vec[i].copyTo(m);
}
}
else {
CV_Error(cv::Error::StsNotImplemented,
"Only Mat vector, UMat vector, and vector<vector> OutputArrays are currently supported.");
}
}
/**
* @brief Identify square candidates according to a marker dictionary
*/
static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidates,
InputArrayOfArrays _contours, const Dictionary &dictionary,
InputArrayOfArrays _contours, Ptr<Dictionary> &_dictionary,
OutputArrayOfArrays _accepted, OutputArray _ids,
DetectorParameters params,
const Ptr<DetectorParameters> &params,
OutputArrayOfArrays _rejected = noArray()) {
int ncandidates = (int)_candidates.total();
@ -607,8 +660,8 @@ static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidate
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, ncandidates),
IdentifyCandidatesParallel(&grey, _candidates, _contours, &dictionary, &idsTmp,
&validCandidates, &params));
IdentifyCandidatesParallel(&grey, _candidates, _contours, _dictionary, &idsTmp,
&validCandidates, params));
for(int i = 0; i < ncandidates; i++) {
if(validCandidates[i] == 1) {
@ -620,24 +673,14 @@ static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidate
}
// parse output
_accepted.create((int)accepted.size(), 1, CV_32FC2);
for(unsigned int i = 0; i < accepted.size(); i++) {
_accepted.create(4, 1, CV_32FC2, i, true);
Mat m = _accepted.getMat(i);
accepted[i].copyTo(m);
}
_copyVector2Output(accepted, _accepted);
_ids.create((int)ids.size(), 1, CV_32SC1);
for(unsigned int i = 0; i < ids.size(); i++)
_ids.getMat().ptr< int >(0)[i] = ids[i];
if(_rejected.needed()) {
_rejected.create((int)rejected.size(), 1, CV_32FC2);
for(unsigned int i = 0; i < rejected.size(); i++) {
_rejected.create(4, 1, CV_32FC2, i, true);
Mat m = _rejected.getMat(i);
rejected[i].copyTo(m);
}
_copyVector2Output(rejected, _rejected);
}
}
@ -744,7 +787,7 @@ static void _getSingleMarkerObjectPoints(float markerLength, OutputArray _objPoi
class MarkerSubpixelParallel : public ParallelLoopBody {
public:
MarkerSubpixelParallel(const Mat *_grey, OutputArrayOfArrays _corners,
DetectorParameters *_params)
const Ptr<DetectorParameters> &_params)
: grey(_grey), corners(_corners), params(_params) {}
void operator()(const Range &range) const {
@ -765,15 +808,15 @@ class MarkerSubpixelParallel : public ParallelLoopBody {
const Mat *grey;
OutputArrayOfArrays corners;
DetectorParameters *params;
const Ptr<DetectorParameters> &params;
};
/**
*/
void detectMarkers(InputArray _image, Dictionary dictionary, OutputArrayOfArrays _corners,
OutputArray _ids, DetectorParameters params,
void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayOfArrays _corners,
OutputArray _ids, const Ptr<DetectorParameters> &_params,
OutputArrayOfArrays _rejectedImgPoints) {
CV_Assert(_image.getMat().total() != 0);
@ -784,19 +827,19 @@ void detectMarkers(InputArray _image, Dictionary dictionary, OutputArrayOfArrays
/// STEP 1: Detect marker candidates
vector< vector< Point2f > > candidates;
vector< vector< Point > > contours;
_detectCandidates(grey, candidates, contours, params);
_detectCandidates(grey, candidates, contours, _params);
/// STEP 2: Check candidate codification (identify markers)
_identifyCandidates(grey, candidates, contours, dictionary, _corners, _ids, params,
_identifyCandidates(grey, candidates, contours, _dictionary, _corners, _ids, _params,
_rejectedImgPoints);
/// STEP 3: Filter detected markers;
_filterDetectedMarkers(_corners, _ids, _corners, _ids);
/// STEP 4: Corner refinement
if(params.doCornerRefinement) {
CV_Assert(params.cornerRefinementWinSize > 0 && params.cornerRefinementMaxIterations > 0 &&
params.cornerRefinementMinAccuracy > 0);
if(_params->doCornerRefinement) {
CV_Assert(_params->cornerRefinementWinSize > 0 && _params->cornerRefinementMaxIterations > 0 &&
_params->cornerRefinementMinAccuracy > 0);
//// do corner refinement for each of the detected markers
// for (unsigned int i = 0; i < _corners.total(); i++) {
@ -809,7 +852,7 @@ void detectMarkers(InputArray _image, Dictionary dictionary, OutputArrayOfArrays
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, (int)_corners.total()),
MarkerSubpixelParallel(&grey, _corners, &params));
MarkerSubpixelParallel(&grey, _corners, _params));
}
}
@ -883,11 +926,11 @@ void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength,
* @brief Given a board configuration and a set of detected markers, returns the corresponding
* image points and object points to call solvePnP
*/
static void _getBoardObjectAndImagePoints(const Board &board, InputArray _detectedIds,
static void _getBoardObjectAndImagePoints(Ptr<Board> &_board, InputArray _detectedIds,
InputArrayOfArrays _detectedCorners,
OutputArray _imgPoints, OutputArray _objPoints) {
CV_Assert(board.ids.size() == board.objPoints.size());
CV_Assert(_board->ids.size() == _board->objPoints.size());
CV_Assert(_detectedIds.total() == _detectedCorners.total());
size_t nDetectedMarkers = _detectedIds.total();
@ -901,10 +944,10 @@ static void _getBoardObjectAndImagePoints(const Board &board, InputArray _detect
// look for detected markers that belong to the board and get their information
for(unsigned int i = 0; i < nDetectedMarkers; i++) {
int currentId = _detectedIds.getMat().ptr< int >(0)[i];
for(unsigned int j = 0; j < board.ids.size(); j++) {
if(currentId == board.ids[j]) {
for(unsigned int j = 0; j < _board->ids.size(); j++) {
if(currentId == _board->ids[j]) {
for(int p = 0; p < 4; p++) {
objPnts.push_back(board.objPoints[j][p]);
objPnts.push_back(_board->objPoints[j][p]);
imgPnts.push_back(_detectedCorners.getMat(i).ptr< Point2f >(0)[p]);
}
}
@ -926,7 +969,7 @@ static void _getBoardObjectAndImagePoints(const Board &board, InputArray _detect
/**
* Project board markers that are not included in the list of detected markers
*/
static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArrays _detectedCorners,
static void _projectUndetectedMarkers(Ptr<Board> &_board, InputOutputArrayOfArrays _detectedCorners,
InputOutputArray _detectedIds, InputArray _cameraMatrix,
InputArray _distCoeffs,
OutputArrayOfArrays _undetectedMarkersProjectedCorners,
@ -935,7 +978,7 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
// first estimate board pose with the current avaible markers
Mat rvec, tvec;
int boardDetectedMarkers;
boardDetectedMarkers = aruco::estimatePoseBoard(_detectedCorners, _detectedIds, board,
boardDetectedMarkers = aruco::estimatePoseBoard(_detectedCorners, _detectedIds, _board,
_cameraMatrix, _distCoeffs, rvec, tvec);
// at least one marker from board so rvec and tvec are valid
@ -944,10 +987,10 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
// search undetected markers and project them using the previous pose
vector< vector< Point2f > > undetectedCorners;
vector< int > undetectedIds;
for(unsigned int i = 0; i < board.ids.size(); i++) {
for(unsigned int i = 0; i < _board->ids.size(); i++) {
int foundIdx = -1;
for(unsigned int j = 0; j < _detectedIds.total(); j++) {
if(board.ids[i] == _detectedIds.getMat().ptr< int >()[j]) {
if(_board->ids[i] == _detectedIds.getMat().ptr< int >()[j]) {
foundIdx = j;
break;
}
@ -956,8 +999,8 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
// not detected
if(foundIdx == -1) {
undetectedCorners.push_back(vector< Point2f >());
undetectedIds.push_back(board.ids[i]);
projectPoints(board.objPoints[i], rvec, tvec, _cameraMatrix, _distCoeffs,
undetectedIds.push_back(_board->ids[i]);
projectPoints(_board->objPoints[i], rvec, tvec, _cameraMatrix, _distCoeffs,
undetectedCorners.back());
}
}
@ -984,19 +1027,19 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
* Interpolate board markers that are not included in the list of detected markers using
* global homography
*/
static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArrays _detectedCorners,
static void _projectUndetectedMarkers(Ptr<Board> &_board, InputOutputArrayOfArrays _detectedCorners,
InputOutputArray _detectedIds,
OutputArrayOfArrays _undetectedMarkersProjectedCorners,
OutputArray _undetectedMarkersIds) {
// check board points are in the same plane, if not, global homography cannot be applied
CV_Assert(board.objPoints.size() > 0);
CV_Assert(board.objPoints[0].size() > 0);
float boardZ = board.objPoints[0][0].z;
for(unsigned int i = 0; i < board.objPoints.size(); i++) {
for(unsigned int j = 0; j < board.objPoints[i].size(); j++) {
CV_Assert(boardZ == board.objPoints[i][j].z);
CV_Assert(_board->objPoints.size() > 0);
CV_Assert(_board->objPoints[0].size() > 0);
float boardZ = _board->objPoints[0][0].z;
for(unsigned int i = 0; i < _board->objPoints.size(); i++) {
for(unsigned int j = 0; j < _board->objPoints[i].size(); j++) {
CV_Assert(boardZ == _board->objPoints[i][j].z);
}
}
@ -1007,14 +1050,14 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
// missing markers in different vectors
vector< int > undetectedMarkersIds; // ids of missing markers
// find markers included in board, and missing markers from board. Fill the previous vectors
for(unsigned int j = 0; j < board.ids.size(); j++) {
for(unsigned int j = 0; j < _board->ids.size(); j++) {
bool found = false;
for(unsigned int i = 0; i < _detectedIds.total(); i++) {
if(_detectedIds.getMat().ptr< int >()[i] == board.ids[j]) {
if(_detectedIds.getMat().ptr< int >()[i] == _board->ids[j]) {
for(int c = 0; c < 4; c++) {
imageCornersAll.push_back(_detectedCorners.getMat(i).ptr< Point2f >()[c]);
detectedMarkersObj2DAll.push_back(
Point2f(board.objPoints[j][c].x, board.objPoints[j][c].y));
Point2f(_board->objPoints[j][c].x, _board->objPoints[j][c].y));
}
found = true;
break;
@ -1024,9 +1067,9 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
undetectedMarkersObj2D.push_back(vector< Point2f >());
for(int c = 0; c < 4; c++) {
undetectedMarkersObj2D.back().push_back(
Point2f(board.objPoints[j][c].x, board.objPoints[j][c].y));
Point2f(_board->objPoints[j][c].x, _board->objPoints[j][c].y));
}
undetectedMarkersIds.push_back(board.ids[j]);
undetectedMarkersIds.push_back(_board->ids[j]);
}
}
if(imageCornersAll.size() == 0) return;
@ -1054,28 +1097,30 @@ static void _projectUndetectedMarkers(const Board &board, InputOutputArrayOfArra
/**
*/
void refineDetectedMarkers(InputArray _image, const Board &board,
void refineDetectedMarkers(InputArray _image, Ptr<Board> &_board,
InputOutputArrayOfArrays _detectedCorners, InputOutputArray _detectedIds,
InputOutputArray _rejectedCorners, InputArray _cameraMatrix,
InputArray _distCoeffs, float minRepDistance, float errorCorrectionRate,
bool checkAllOrders, OutputArray _recoveredIdxs,
DetectorParameters params) {
const Ptr<DetectorParameters> &_params) {
CV_Assert(minRepDistance > 0);
if(_detectedIds.total() == 0 || _rejectedCorners.total() == 0) return;
DetectorParameters &params = *_params;
// get projections of missing markers in the board
vector< vector< Point2f > > undetectedMarkersCorners;
vector< int > undetectedMarkersIds;
if(_cameraMatrix.total() != 0) {
// reproject based on camera projection model
_projectUndetectedMarkers(board, _detectedCorners, _detectedIds, _cameraMatrix, _distCoeffs,
_projectUndetectedMarkers(_board, _detectedCorners, _detectedIds, _cameraMatrix, _distCoeffs,
undetectedMarkersCorners, undetectedMarkersIds);
} else {
// reproject based on global homography
_projectUndetectedMarkers(board, _detectedCorners, _detectedIds, undetectedMarkersCorners,
_projectUndetectedMarkers(_board, _detectedCorners, _detectedIds, undetectedMarkersCorners,
undetectedMarkersIds);
}
@ -1083,8 +1128,9 @@ void refineDetectedMarkers(InputArray _image, const Board &board,
vector< bool > alreadyIdentified(_rejectedCorners.total(), false);
// maximum bits that can be corrected
Dictionary &dictionary = *(_board->dictionary);
int maxCorrectionRecalculated =
int(double(board.dictionary.maxCorrectionBits) * errorCorrectionRate);
int(double(dictionary.maxCorrectionBits) * errorCorrectionRate);
Mat grey;
_convertToGrey(_image, grey);
@ -1152,7 +1198,7 @@ void refineDetectedMarkers(InputArray _image, const Board &board,
// extract bits
Mat bits = _extractBits(
grey, rotatedMarker, board.dictionary.markerSize, params.markerBorderBits,
grey, rotatedMarker, dictionary.markerSize, params.markerBorderBits,
params.perspectiveRemovePixelPerCell,
params.perspectiveRemoveIgnoredMarginPerCell, params.minOtsuStdDev);
@ -1161,7 +1207,7 @@ void refineDetectedMarkers(InputArray _image, const Board &board,
.colRange(params.markerBorderBits, bits.rows - params.markerBorderBits);
codeDistance =
board.dictionary.getDistanceToId(onlyBits, undetectedMarkersIds[i], false);
dictionary.getDistanceToId(onlyBits, undetectedMarkersIds[i], false);
}
// if everythin is ok, assign values to current best match
@ -1250,7 +1296,7 @@ void refineDetectedMarkers(InputArray _image, const Board &board,
/**
*/
int estimatePoseBoard(InputArrayOfArrays _corners, InputArray _ids, const Board &board,
int estimatePoseBoard(InputArrayOfArrays _corners, InputArray _ids, Ptr<Board> &board,
InputArray _cameraMatrix, InputArray _distCoeffs, OutputArray _rvec,
OutputArray _tvec) {
@ -1279,33 +1325,33 @@ int estimatePoseBoard(InputArrayOfArrays _corners, InputArray _ids, const Board
/**
*/
void GridBoard::draw(Size outSize, OutputArray _img, int marginSize, int borderBits) {
aruco::drawPlanarBoard((*this), outSize, _img, marginSize, borderBits);
_drawPlanarBoardImpl(this, outSize, _img, marginSize, borderBits);
}
/**
*/
GridBoard GridBoard::create(int markersX, int markersY, float markerLength, float markerSeparation,
Dictionary _dictionary) {
GridBoard res;
Ptr<GridBoard> GridBoard::create(int markersX, int markersY, float markerLength, float markerSeparation,
Ptr<Dictionary> &dictionary) {
CV_Assert(markersX > 0 && markersY > 0 && markerLength > 0 && markerSeparation > 0);
res._markersX = markersX;
res._markersY = markersY;
res._markerLength = markerLength;
res._markerSeparation = markerSeparation;
res.dictionary = _dictionary;
Ptr<GridBoard> res = makePtr<GridBoard>();
res->_markersX = markersX;
res->_markersY = markersY;
res->_markerLength = markerLength;
res->_markerSeparation = markerSeparation;
res->dictionary = dictionary;
size_t totalMarkers = (size_t) markersX * markersY;
res.ids.resize(totalMarkers);
res.objPoints.reserve(totalMarkers);
res->ids.resize(totalMarkers);
res->objPoints.reserve(totalMarkers);
// fill ids with first identifiers
for(unsigned int i = 0; i < totalMarkers; i++) {
res.ids[i] = i;
res->ids[i] = i;
}
// calculate Board objPoints
@ -1319,7 +1365,7 @@ GridBoard GridBoard::create(int markersX, int markersY, float markerLength, floa
corners[1] = corners[0] + Point3f(markerLength, 0, 0);
corners[2] = corners[0] + Point3f(markerLength, -markerLength, 0);
corners[3] = corners[0] + Point3f(0, -markerLength, 0);
res.objPoints.push_back(corners);
res->objPoints.push_back(corners);
}
}
@ -1403,15 +1449,13 @@ void drawAxis(InputOutputArray _image, InputArray _cameraMatrix, InputArray _dis
/**
*/
void drawMarker(Dictionary dictionary, int id, int sidePixels, OutputArray _img, int borderBits) {
dictionary.drawMarker(id, sidePixels, _img, borderBits);
void drawMarker(Ptr<Dictionary> &dictionary, int id, int sidePixels, OutputArray _img, int borderBits) {
dictionary->drawMarker(id, sidePixels, _img, borderBits);
}
/**
*/
void drawPlanarBoard(const Board &board, Size outSize, OutputArray _img, int marginSize,
void _drawPlanarBoardImpl(Board *_board, Size outSize, OutputArray _img, int marginSize,
int borderBits) {
CV_Assert(outSize.area() > 0);
@ -1424,17 +1468,17 @@ void drawPlanarBoard(const Board &board, Size outSize, OutputArray _img, int mar
out.colRange(marginSize, out.cols - marginSize).rowRange(marginSize, out.rows - marginSize);
// calculate max and min values in XY plane
CV_Assert(board.objPoints.size() > 0);
CV_Assert(_board->objPoints.size() > 0);
float minX, maxX, minY, maxY;
minX = maxX = board.objPoints[0][0].x;
minY = maxY = board.objPoints[0][0].y;
minX = maxX = _board->objPoints[0][0].x;
minY = maxY = _board->objPoints[0][0].y;
for(unsigned int i = 0; i < board.objPoints.size(); i++) {
for(unsigned int i = 0; i < _board->objPoints.size(); i++) {
for(int j = 0; j < 4; j++) {
minX = min(minX, board.objPoints[i][j].x);
maxX = max(maxX, board.objPoints[i][j].x);
minY = min(minY, board.objPoints[i][j].y);
maxY = max(maxY, board.objPoints[i][j].y);
minX = min(minX, _board->objPoints[i][j].x);
maxX = max(maxX, _board->objPoints[i][j].x);
minY = min(minY, _board->objPoints[i][j].y);
maxY = max(maxY, _board->objPoints[i][j].y);
}
}
@ -1459,14 +1503,15 @@ void drawPlanarBoard(const Board &board, Size outSize, OutputArray _img, int mar
}
// now paint each marker
for(unsigned int m = 0; m < board.objPoints.size(); m++) {
Dictionary &dictionary = *(_board->dictionary);
for(unsigned int m = 0; m < _board->objPoints.size(); m++) {
// transform corners to markerZone coordinates
vector< Point2f > outCorners;
outCorners.resize(4);
for(int j = 0; j < 4; j++) {
Point2f p0, p1, pf;
p0 = Point2f(board.objPoints[m][j].x, board.objPoints[m][j].y);
p0 = Point2f(_board->objPoints[m][j].x, _board->objPoints[m][j].y);
// remove negativity
p1.x = p0.x - minX;
p1.y = p0.y - minY;
@ -1476,9 +1521,9 @@ void drawPlanarBoard(const Board &board, Size outSize, OutputArray _img, int mar
}
// get tiny marker
int tinyMarkerSize = 10 * board.dictionary.markerSize + 2;
int tinyMarkerSize = 10 * dictionary.markerSize + 2;
Mat tinyMarker;
board.dictionary.drawMarker(board.ids[m], tinyMarkerSize, tinyMarker, borderBits);
dictionary.drawMarker(_board->ids[m], tinyMarkerSize, tinyMarker, borderBits);
// interpolate tiny marker to marker position in markerZone
Mat inCorners(4, 1, CV_32FC2);
@ -1506,10 +1551,19 @@ void drawPlanarBoard(const Board &board, Size outSize, OutputArray _img, int mar
/**
*/
void drawPlanarBoard(Ptr<Board> &_board, Size outSize, OutputArray _img, int marginSize,
int borderBits) {
_drawPlanarBoardImpl(_board, outSize, _img, marginSize, borderBits);
}
/**
*/
double calibrateCameraAruco(InputArrayOfArrays _corners, InputArray _ids, InputArray _counter,
const Board &board, Size imageSize, InputOutputArray _cameraMatrix,
Ptr<Board> &board, Size imageSize, InputOutputArray _cameraMatrix,
InputOutputArray _distCoeffs, OutputArrayOfArrays _rvecs,
OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria) {
@ -1544,5 +1598,8 @@ double calibrateCameraAruco(InputArrayOfArrays _corners, InputArray _ids, InputA
return calibrateCamera(processedObjectPoints, processedImagePoints, imageSize, _cameraMatrix,
_distCoeffs, _rvecs, _tvecs, flags, criteria);
}
}
}

@ -93,8 +93,8 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
// draw markers
Mat markersImg;
aruco::drawPlanarBoard((*this), chessboardZoneImg.size(), markersImg,
diffSquareMarkerLengthPixels, borderBits);
aruco::_drawPlanarBoardImpl(this, chessboardZoneImg.size(), markersImg,
diffSquareMarkerLengthPixels, borderBits);
markersImg.copyTo(chessboardZoneImg);
@ -120,17 +120,17 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
/**
*/
CharucoBoard CharucoBoard::create(int squaresX, int squaresY, float squareLength,
float markerLength, Dictionary dictionary) {
Ptr<CharucoBoard> CharucoBoard::create(int squaresX, int squaresY, float squareLength,
float markerLength, Ptr<Dictionary> &dictionary) {
CV_Assert(squaresX > 1 && squaresY > 1 && markerLength > 0 && squareLength > markerLength);
CharucoBoard res;
Ptr<CharucoBoard> res = makePtr<CharucoBoard>();
res._squaresX = squaresX;
res._squaresY = squaresY;
res._squareLength = squareLength;
res._markerLength = markerLength;
res.dictionary = dictionary;
res->_squaresX = squaresX;
res->_squaresY = squaresY;
res->_squareLength = squareLength;
res->_markerLength = markerLength;
res->dictionary = dictionary;
float diffSquareMarkerLength = (squareLength - markerLength) / 2;
@ -147,10 +147,10 @@ CharucoBoard CharucoBoard::create(int squaresX, int squaresY, float squareLength
corners[1] = corners[0] + Point3f(markerLength, 0, 0);
corners[2] = corners[0] + Point3f(markerLength, -markerLength, 0);
corners[3] = corners[0] + Point3f(0, -markerLength, 0);
res.objPoints.push_back(corners);
res->objPoints.push_back(corners);
// first ids in dictionary
int nextId = (int)res.ids.size();
res.ids.push_back(nextId);
int nextId = (int)res->ids.size();
res->ids.push_back(nextId);
}
}
@ -161,11 +161,11 @@ CharucoBoard CharucoBoard::create(int squaresX, int squaresY, float squareLength
corner.x = (x + 1) * squareLength;
corner.y = (y + 1) * squareLength;
corner.z = 0;
res.chessboardCorners.push_back(corner);
res->chessboardCorners.push_back(corner);
}
}
res._getNearestMarkerCorners();
res->_getNearestMarkerCorners();
return res;
}
@ -230,7 +230,7 @@ void CharucoBoard::_getNearestMarkerCorners() {
/**
* Remove charuco corners if any of their minMarkers closest markers has not been detected
*/
static unsigned int _filterCornersWithoutMinMarkers(const CharucoBoard &board,
static unsigned int _filterCornersWithoutMinMarkers(Ptr<CharucoBoard> &_board,
InputArray _allCharucoCorners,
InputArray _allCharucoIds,
InputArray _allArucoIds, int minMarkers,
@ -246,8 +246,8 @@ static unsigned int _filterCornersWithoutMinMarkers(const CharucoBoard &board,
int currentCharucoId = _allCharucoIds.getMat().ptr< int >(0)[i];
int totalMarkers = 0; // nomber of closest marker detected
// look for closest markers
for(unsigned int m = 0; m < board.nearestMarkerIdx[currentCharucoId].size(); m++) {
int markerId = board.ids[board.nearestMarkerIdx[currentCharucoId][m]];
for(unsigned int m = 0; m < _board->nearestMarkerIdx[currentCharucoId].size(); m++) {
int markerId = _board->ids[_board->nearestMarkerIdx[currentCharucoId][m]];
bool found = false;
for(unsigned int k = 0; k < _allArucoIds.getMat().total(); k++) {
if(_allArucoIds.getMat().ptr< int >(0)[k] == markerId) {
@ -286,7 +286,7 @@ static unsigned int _filterCornersWithoutMinMarkers(const CharucoBoard &board,
class CharucoSubpixelParallel : public ParallelLoopBody {
public:
CharucoSubpixelParallel(const Mat *_grey, vector< Point2f > *_filteredChessboardImgPoints,
vector< Size > *_filteredWinSizes, DetectorParameters *_params)
vector< Size > *_filteredWinSizes, const Ptr<DetectorParameters> &_params)
: grey(_grey), filteredChessboardImgPoints(_filteredChessboardImgPoints),
filteredWinSizes(_filteredWinSizes), params(_params) {}
@ -316,7 +316,7 @@ class CharucoSubpixelParallel : public ParallelLoopBody {
const Mat *grey;
vector< Point2f > *filteredChessboardImgPoints;
vector< Size > *filteredWinSizes;
DetectorParameters *params;
const Ptr<DetectorParameters> &params;
};
@ -358,7 +358,7 @@ static unsigned int _selectAndRefineChessboardCorners(InputArray _allCorners, In
else
_image.getMat().copyTo(grey);
DetectorParameters params; // use default params for corner refinement
const Ptr<DetectorParameters> params = DetectorParameters::create(); // use default params for corner refinement
//// For each of the charuco corners, apply subpixel refinement using its correspondind winSize
// for(unsigned int i=0; i<filteredChessboardImgPoints.size(); i++) {
@ -377,7 +377,7 @@ static unsigned int _selectAndRefineChessboardCorners(InputArray _allCorners, In
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(
Range(0, (int)filteredChessboardImgPoints.size()),
CharucoSubpixelParallel(&grey, &filteredChessboardImgPoints, &filteredWinSizes, &params));
CharucoSubpixelParallel(&grey, &filteredChessboardImgPoints, &filteredWinSizes, params));
// parse output
_selectedCorners.create((int)filteredChessboardImgPoints.size(), 1, CV_32FC2);
@ -399,7 +399,7 @@ static unsigned int _selectAndRefineChessboardCorners(InputArray _allCorners, In
* distance to their closest markers
*/
static void _getMaximumSubPixWindowSizes(InputArrayOfArrays markerCorners, InputArray markerIds,
InputArray charucoCorners, const CharucoBoard &board,
InputArray charucoCorners, Ptr<CharucoBoard> &board,
vector< Size > &sizes) {
unsigned int nCharucoCorners = (unsigned int)charucoCorners.getMat().total();
@ -407,15 +407,15 @@ static void _getMaximumSubPixWindowSizes(InputArrayOfArrays markerCorners, Input
for(unsigned int i = 0; i < nCharucoCorners; i++) {
if(charucoCorners.getMat().ptr< Point2f >(0)[i] == Point2f(-1, -1)) continue;
if(board.nearestMarkerIdx[i].size() == 0) continue;
if(board->nearestMarkerIdx[i].size() == 0) continue;
double minDist = -1;
int counter = 0;
// calculate the distance to each of the closest corner of each closest marker
for(unsigned int j = 0; j < board.nearestMarkerIdx[i].size(); j++) {
for(unsigned int j = 0; j < board->nearestMarkerIdx[i].size(); j++) {
// find marker
int markerId = board.ids[board.nearestMarkerIdx[i][j]];
int markerId = board->ids[board->nearestMarkerIdx[i][j]];
int markerIdx = -1;
for(unsigned int k = 0; k < markerIds.getMat().total(); k++) {
if(markerIds.getMat().ptr< int >(0)[k] == markerId) {
@ -425,7 +425,7 @@ static void _getMaximumSubPixWindowSizes(InputArrayOfArrays markerCorners, Input
}
if(markerIdx == -1) continue;
Point2f markerCorner =
markerCorners.getMat(markerIdx).ptr< Point2f >(0)[board.nearestMarkerCorners[i][j]];
markerCorners.getMat(markerIdx).ptr< Point2f >(0)[board->nearestMarkerCorners[i][j]];
Point2f charucoCorner = charucoCorners.getMat().ptr< Point2f >(0)[i];
double dist = norm(markerCorner - charucoCorner);
if(minDist == -1) minDist = dist; // if first distance, just assign it
@ -453,7 +453,7 @@ static void _getMaximumSubPixWindowSizes(InputArrayOfArrays markerCorners, Input
*/
static int _interpolateCornersCharucoApproxCalib(InputArrayOfArrays _markerCorners,
InputArray _markerIds, InputArray _image,
const CharucoBoard &board,
Ptr<CharucoBoard> &_board,
InputArray _cameraMatrix, InputArray _distCoeffs,
OutputArray _charucoCorners,
OutputArray _charucoIds) {
@ -465,22 +465,24 @@ static int _interpolateCornersCharucoApproxCalib(InputArrayOfArrays _markerCorne
// approximated pose estimation using marker corners
Mat approximatedRvec, approximatedTvec;
int detectedBoardMarkers;
Ptr<Board> _b = _board.staticCast<Board>();
detectedBoardMarkers =
aruco::estimatePoseBoard(_markerCorners, _markerIds, board, _cameraMatrix, _distCoeffs,
approximatedRvec, approximatedTvec);
aruco::estimatePoseBoard(_markerCorners, _markerIds, _b,
_cameraMatrix, _distCoeffs, approximatedRvec, approximatedTvec);
if(detectedBoardMarkers == 0) return 0;
// project chessboard corners
vector< Point2f > allChessboardImgPoints;
projectPoints(board.chessboardCorners, approximatedRvec, approximatedTvec, _cameraMatrix,
projectPoints(_board->chessboardCorners, approximatedRvec, approximatedTvec, _cameraMatrix,
_distCoeffs, allChessboardImgPoints);
// calculate maximum window sizes for subpixel refinement. The size is limited by the distance
// to the closes marker corner to avoid erroneous displacements to marker corners
vector< Size > subPixWinSizes;
_getMaximumSubPixWindowSizes(_markerCorners, _markerIds, allChessboardImgPoints, board,
_getMaximumSubPixWindowSizes(_markerCorners, _markerIds, allChessboardImgPoints, _board,
subPixWinSizes);
// filter corners outside the image and subpixel-refine charuco corners
@ -489,7 +491,7 @@ static int _interpolateCornersCharucoApproxCalib(InputArrayOfArrays _markerCorne
allChessboardImgPoints, _image, _charucoCorners, _charucoIds, subPixWinSizes);
// to return a charuco corner, its two closes aruco markers should have been detected
nRefinedCorners = _filterCornersWithoutMinMarkers(board, _charucoCorners, _charucoIds,
nRefinedCorners = _filterCornersWithoutMinMarkers(_board, _charucoCorners, _charucoIds,
_markerIds, 2, _charucoCorners, _charucoIds);
return nRefinedCorners;
@ -502,7 +504,7 @@ static int _interpolateCornersCharucoApproxCalib(InputArrayOfArrays _markerCorne
*/
static int _interpolateCornersCharucoLocalHom(InputArrayOfArrays _markerCorners,
InputArray _markerIds, InputArray _image,
const CharucoBoard &board,
Ptr<CharucoBoard> &_board,
OutputArray _charucoCorners,
OutputArray _charucoIds) {
@ -518,28 +520,28 @@ static int _interpolateCornersCharucoLocalHom(InputArrayOfArrays _markerCorners,
for(unsigned int i = 0; i < nMarkers; i++) {
vector< Point2f > markerObjPoints2D;
int markerId = _markerIds.getMat().ptr< int >(0)[i];
vector< int >::const_iterator it = find(board.ids.begin(), board.ids.end(), markerId);
if(it == board.ids.end()) continue;
int boardIdx = (int)std::distance(board.ids.begin(), it);
vector< int >::const_iterator it = find(_board->ids.begin(), _board->ids.end(), markerId);
if(it == _board->ids.end()) continue;
int boardIdx = (int)std::distance<std::vector<int>::const_iterator>(_board->ids.begin(), it);
markerObjPoints2D.resize(4);
for(unsigned int j = 0; j < 4; j++)
markerObjPoints2D[j] =
Point2f(board.objPoints[boardIdx][j].x, board.objPoints[boardIdx][j].y);
Point2f(_board->objPoints[boardIdx][j].x, _board->objPoints[boardIdx][j].y);
transformations[i] = getPerspectiveTransform(markerObjPoints2D, _markerCorners.getMat(i));
}
unsigned int nCharucoCorners = (unsigned int)board.chessboardCorners.size();
unsigned int nCharucoCorners = (unsigned int)_board->chessboardCorners.size();
vector< Point2f > allChessboardImgPoints(nCharucoCorners, Point2f(-1, -1));
// for each charuco corner, calculate its interpolation position based on the closest markers
// homographies
for(unsigned int i = 0; i < nCharucoCorners; i++) {
Point2f objPoint2D = Point2f(board.chessboardCorners[i].x, board.chessboardCorners[i].y);
Point2f objPoint2D = Point2f(_board->chessboardCorners[i].x, _board->chessboardCorners[i].y);
vector< Point2f > interpolatedPositions;
for(unsigned int j = 0; j < board.nearestMarkerIdx[i].size(); j++) {
int markerId = board.ids[board.nearestMarkerIdx[i][j]];
for(unsigned int j = 0; j < _board->nearestMarkerIdx[i].size(); j++) {
int markerId = _board->ids[_board->nearestMarkerIdx[i][j]];
int markerIdx = -1;
for(unsigned int k = 0; k < _markerIds.getMat().total(); k++) {
if(_markerIds.getMat().ptr< int >(0)[k] == markerId) {
@ -569,7 +571,7 @@ static int _interpolateCornersCharucoLocalHom(InputArrayOfArrays _markerCorners,
// calculate maximum window sizes for subpixel refinement. The size is limited by the distance
// to the closes marker corner to avoid erroneous displacements to marker corners
vector< Size > subPixWinSizes;
_getMaximumSubPixWindowSizes(_markerCorners, _markerIds, allChessboardImgPoints, board,
_getMaximumSubPixWindowSizes(_markerCorners, _markerIds, allChessboardImgPoints, _board,
subPixWinSizes);
@ -579,7 +581,7 @@ static int _interpolateCornersCharucoLocalHom(InputArrayOfArrays _markerCorners,
allChessboardImgPoints, _image, _charucoCorners, _charucoIds, subPixWinSizes);
// to return a charuco corner, its two closes aruco markers should have been detected
nRefinedCorners = _filterCornersWithoutMinMarkers(board, _charucoCorners, _charucoIds,
nRefinedCorners = _filterCornersWithoutMinMarkers(_board, _charucoCorners, _charucoIds,
_markerIds, 2, _charucoCorners, _charucoIds);
return nRefinedCorners;
@ -590,19 +592,19 @@ static int _interpolateCornersCharucoLocalHom(InputArrayOfArrays _markerCorners,
/**
*/
int interpolateCornersCharuco(InputArrayOfArrays _markerCorners, InputArray _markerIds,
InputArray _image, const CharucoBoard &board,
InputArray _image, Ptr<CharucoBoard> &_board,
OutputArray _charucoCorners, OutputArray _charucoIds,
InputArray _cameraMatrix, InputArray _distCoeffs) {
// if camera parameters are avaible, use approximated calibration
if(_cameraMatrix.total() != 0) {
return _interpolateCornersCharucoApproxCalib(_markerCorners, _markerIds, _image, board,
return _interpolateCornersCharucoApproxCalib(_markerCorners, _markerIds, _image, _board,
_cameraMatrix, _distCoeffs, _charucoCorners,
_charucoIds);
}
// else use local homography
else {
return _interpolateCornersCharucoLocalHom(_markerCorners, _markerIds, _image, board,
return _interpolateCornersCharucoLocalHom(_markerCorners, _markerIds, _image, _board,
_charucoCorners, _charucoIds);
}
}
@ -679,7 +681,7 @@ static bool _arePointsEnoughForPoseEstimation(const vector< Point3f > &points) {
/**
*/
bool estimatePoseCharucoBoard(InputArray _charucoCorners, InputArray _charucoIds,
CharucoBoard &board, InputArray _cameraMatrix, InputArray _distCoeffs,
Ptr<CharucoBoard> &_board, InputArray _cameraMatrix, InputArray _distCoeffs,
OutputArray _rvec, OutputArray _tvec) {
CV_Assert((_charucoCorners.getMat().total() == _charucoIds.getMat().total()));
@ -691,8 +693,8 @@ bool estimatePoseCharucoBoard(InputArray _charucoCorners, InputArray _charucoIds
objPoints.reserve(_charucoIds.getMat().total());
for(unsigned int i = 0; i < _charucoIds.getMat().total(); i++) {
int currId = _charucoIds.getMat().ptr< int >(0)[i];
CV_Assert(currId >= 0 && currId < (int)board.chessboardCorners.size());
objPoints.push_back(board.chessboardCorners[currId]);
CV_Assert(currId >= 0 && currId < (int)_board->chessboardCorners.size());
objPoints.push_back(_board->chessboardCorners[currId]);
}
// points need to be in different lines, check if detected points are enough
@ -709,12 +711,11 @@ bool estimatePoseCharucoBoard(InputArray _charucoCorners, InputArray _charucoIds
/**
*/
double calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfArrays _charucoIds,
const CharucoBoard &board, Size imageSize,
Ptr<CharucoBoard> &_board, Size imageSize,
InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs,
OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags,
TermCriteria criteria) {
CV_Assert(_charucoIds.total() > 0 && (_charucoIds.total() == _charucoCorners.total()));
// Join object points of charuco corners in a single vector for calibrateCamera() function
@ -727,8 +728,8 @@ double calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfAr
for(unsigned int j = 0; j < nCorners; j++) {
int pointId = _charucoIds.getMat(i).ptr< int >(0)[j];
CV_Assert(pointId >= 0 && pointId < (int)board.chessboardCorners.size());
allObjPoints[i].push_back(board.chessboardCorners[pointId]);
CV_Assert(pointId >= 0 && pointId < (int)_board->chessboardCorners.size());
allObjPoints[i].push_back(_board->chessboardCorners[pointId]);
}
}
@ -750,9 +751,9 @@ void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners,
const float minRepDistanceRate = 0.12f;
// create Charuco board layout for diamond (3x3 layout)
CharucoBoard charucoDiamondLayout;
Dictionary dict = getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME(0));
charucoDiamondLayout = CharucoBoard::create(3, 3, squareMarkerLengthRate, 1., dict);
Ptr<Dictionary> dict = getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME(0));
Ptr<CharucoBoard> _charucoDiamondLayout = CharucoBoard::create(3, 3, squareMarkerLengthRate, 1., dict);
vector< vector< Point2f > > diamondCorners;
vector< Vec4i > diamondIds;
@ -808,13 +809,15 @@ void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners,
// modify charuco layout id to make sure all the ids are different than current id
for(int k = 1; k < 4; k++)
charucoDiamondLayout.ids[k] = currentId + 1 + k;
_charucoDiamondLayout->ids[k] = currentId + 1 + k;
// current id is assigned to [0], so it is the marker on the top
charucoDiamondLayout.ids[0] = currentId;
_charucoDiamondLayout->ids[0] = currentId;
// try to find the rest of markers in the diamond
vector< int > acceptedIdxs;
aruco::refineDetectedMarkers(grey, charucoDiamondLayout, currentMarker, currentMarkerId,
Ptr<Board> _b = _charucoDiamondLayout.staticCast<Board>();
aruco::refineDetectedMarkers(grey, _b,
currentMarker, currentMarkerId,
candidates, noArray(), noArray(), minRepDistance, -1, false,
acceptedIdxs);
@ -836,7 +839,7 @@ void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners,
// interpolate the charuco corners of the diamond
vector< Point2f > currentMarkerCorners;
Mat aux;
interpolateCornersCharuco(currentMarker, currentMarkerId, grey, charucoDiamondLayout,
interpolateCornersCharuco(currentMarker, currentMarkerId, grey, _charucoDiamondLayout,
currentMarkerCorners, aux, _cameraMatrix, _distCoeffs);
// if everything is ok, save the diamond
@ -878,22 +881,22 @@ void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners,
/**
*/
void drawCharucoDiamond(Dictionary dictionary, Vec4i ids, int squareLength, int markerLength,
void drawCharucoDiamond(Ptr<Dictionary> &dictionary, Vec4i ids, int squareLength, int markerLength,
OutputArray _img, int marginSize, int borderBits) {
CV_Assert(squareLength > 0 && markerLength > 0 && squareLength > markerLength);
CV_Assert(marginSize >= 0 && borderBits > 0);
// create a charuco board similar to a charuco marker and print it
CharucoBoard board =
Ptr<CharucoBoard> board =
CharucoBoard::create(3, 3, (float)squareLength, (float)markerLength, dictionary);
// assign the charuco marker ids
for(int i = 0; i < 4; i++)
board.ids[i] = ids[i];
board->ids[i] = ids[i];
Size outSize(3 * squareLength + 2 * marginSize, 3 * squareLength + 2 * marginSize);
board.draw(outSize, _img, marginSize, borderBits);
board->draw(outSize, _img, marginSize, borderBits);
}

@ -48,6 +48,16 @@ namespace aruco {
using namespace std;
/**
*/
Dictionary::Dictionary(const Ptr<Dictionary> &_dictionary) {
markerSize = _dictionary->markerSize;
maxCorrectionBits = _dictionary->maxCorrectionBits;
bytesList = _dictionary->bytesList.clone();
}
/**
*/
Dictionary::Dictionary(const Mat &_bytesList, int _markerSize, int _maxcorr) {
@ -57,6 +67,28 @@ Dictionary::Dictionary(const Mat &_bytesList, int _markerSize, int _maxcorr) {
}
/**
*/
Ptr<Dictionary> Dictionary::create(int nMarkers, int markerSize) {
Ptr<Dictionary> baseDictionary = makePtr<Dictionary>();
return create(nMarkers, markerSize, baseDictionary);
}
/**
*/
Ptr<Dictionary> Dictionary::create(int nMarkers, int markerSize,
Ptr<Dictionary> &baseDictionary) {
return generateCustomDictionary(nMarkers, markerSize, baseDictionary);
}
/**
*/
Ptr<Dictionary> Dictionary::get(int dict) {
return getPredefinedDictionary(dict);
}
/**
*/
@ -259,50 +291,55 @@ const Dictionary DICT_7X7_250_DATA = Dictionary(Mat(250, (7*7 + 7)/8 ,CV_8UC4, (
const Dictionary DICT_7X7_1000_DATA = Dictionary(Mat(1000, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 6);
const Dictionary &getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) {
Ptr<Dictionary> getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) {
switch(name) {
case DICT_ARUCO_ORIGINAL:
return DICT_ARUCO_DATA;
return makePtr<Dictionary>(DICT_ARUCO_DATA);
case DICT_4X4_50:
return DICT_4X4_50_DATA;
return makePtr<Dictionary>(DICT_4X4_50_DATA);
case DICT_4X4_100:
return DICT_4X4_100_DATA;
return makePtr<Dictionary>(DICT_4X4_100_DATA);
case DICT_4X4_250:
return DICT_4X4_250_DATA;
return makePtr<Dictionary>(DICT_4X4_250_DATA);
case DICT_4X4_1000:
return DICT_4X4_1000_DATA;
return makePtr<Dictionary>(DICT_4X4_1000_DATA);
case DICT_5X5_50:
return DICT_5X5_50_DATA;
return makePtr<Dictionary>(DICT_5X5_50_DATA);
case DICT_5X5_100:
return DICT_5X5_100_DATA;
return makePtr<Dictionary>(DICT_5X5_100_DATA);
case DICT_5X5_250:
return DICT_5X5_250_DATA;
return makePtr<Dictionary>(DICT_5X5_250_DATA);
case DICT_5X5_1000:
return DICT_5X5_1000_DATA;
return makePtr<Dictionary>(DICT_5X5_1000_DATA);
case DICT_6X6_50:
return DICT_6X6_50_DATA;
return makePtr<Dictionary>(DICT_6X6_50_DATA);
case DICT_6X6_100:
return DICT_6X6_100_DATA;
return makePtr<Dictionary>(DICT_6X6_100_DATA);
case DICT_6X6_250:
return DICT_6X6_250_DATA;
return makePtr<Dictionary>(DICT_6X6_250_DATA);
case DICT_6X6_1000:
return DICT_6X6_1000_DATA;
return makePtr<Dictionary>(DICT_6X6_1000_DATA);
case DICT_7X7_50:
return DICT_7X7_50_DATA;
return makePtr<Dictionary>(DICT_7X7_50_DATA);
case DICT_7X7_100:
return DICT_7X7_100_DATA;
return makePtr<Dictionary>(DICT_7X7_100_DATA);
case DICT_7X7_250:
return DICT_7X7_250_DATA;
return makePtr<Dictionary>(DICT_7X7_250_DATA);
case DICT_7X7_1000:
return DICT_7X7_1000_DATA;
return makePtr<Dictionary>(DICT_7X7_1000_DATA);
}
return DICT_4X4_50_DATA;
return makePtr<Dictionary>(DICT_4X4_50_DATA);
}
Ptr<Dictionary> getPredefinedDictionary(int dict) {
return getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME(dict));
}
@ -339,11 +376,11 @@ static int _getSelfDistance(const Mat &marker) {
/**
*/
Dictionary generateCustomDictionary(int nMarkers, int markerSize,
const Dictionary &baseDictionary) {
Ptr<Dictionary> generateCustomDictionary(int nMarkers, int markerSize,
Ptr<Dictionary> &baseDictionary) {
Dictionary out;
out.markerSize = markerSize;
Ptr<Dictionary> out = makePtr<Dictionary>();
out->markerSize = markerSize;
// theoretical maximum intermarker distance
// See S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, and M. J. Marín-Jiménez. 2014.
@ -353,17 +390,17 @@ Dictionary generateCustomDictionary(int nMarkers, int markerSize,
int tau = 2 * (int)std::floor(float(C) * 4.f / 3.f);
// if baseDictionary is provided, calculate its intermarker distance
if(baseDictionary.bytesList.rows > 0) {
CV_Assert(baseDictionary.markerSize == markerSize);
out.bytesList = baseDictionary.bytesList.clone();
if(baseDictionary->bytesList.rows > 0) {
CV_Assert(baseDictionary->markerSize == markerSize);
out->bytesList = baseDictionary->bytesList.clone();
int minDistance = markerSize * markerSize + 1;
for(int i = 0; i < out.bytesList.rows; i++) {
Mat markerBytes = out.bytesList.rowRange(i, i + 1);
for(int i = 0; i < out->bytesList.rows; i++) {
Mat markerBytes = out->bytesList.rowRange(i, i + 1);
Mat markerBits = Dictionary::getBitsFromByteList(markerBytes, markerSize);
minDistance = min(minDistance, _getSelfDistance(markerBits));
for(int j = i + 1; j < out.bytesList.rows; j++) {
minDistance = min(minDistance, out.getDistanceToId(markerBits, j));
for(int j = i + 1; j < out->bytesList.rows; j++) {
minDistance = min(minDistance, out->getDistanceToId(markerBits, j));
}
}
tau = minDistance;
@ -377,7 +414,7 @@ Dictionary generateCustomDictionary(int nMarkers, int markerSize,
const int maxUnproductiveIterations = 5000;
int unproductiveIterations = 0;
while(out.bytesList.rows < nMarkers) {
while(out->bytesList.rows < nMarkers) {
Mat currentMarker = _generateRandomMarker(markerSize);
int selfDistance = _getSelfDistance(currentMarker);
@ -386,8 +423,8 @@ Dictionary generateCustomDictionary(int nMarkers, int markerSize,
// if self distance is better or equal than current best option, calculate distance
// to previous accepted markers
if(selfDistance >= bestTau) {
for(int i = 0; i < out.bytesList.rows; i++) {
int currentDistance = out.getDistanceToId(currentMarker, i);
for(int i = 0; i < out->bytesList.rows; i++) {
int currentDistance = out->getDistanceToId(currentMarker, i);
minDistance = min(currentDistance, minDistance);
if(minDistance <= bestTau) {
break;
@ -400,7 +437,7 @@ Dictionary generateCustomDictionary(int nMarkers, int markerSize,
unproductiveIterations = 0;
bestTau = 0;
Mat bytes = Dictionary::getByteListFromBits(currentMarker);
out.bytesList.push_back(bytes);
out->bytesList.push_back(bytes);
} else {
unproductiveIterations++;
@ -416,15 +453,25 @@ Dictionary generateCustomDictionary(int nMarkers, int markerSize,
tau = bestTau;
bestTau = 0;
Mat bytes = Dictionary::getByteListFromBits(bestMarker);
out.bytesList.push_back(bytes);
out->bytesList.push_back(bytes);
}
}
}
// update the maximum number of correction bits for the generated dictionary
out.maxCorrectionBits = (tau - 1) / 2;
out->maxCorrectionBits = (tau - 1) / 2;
return out;
}
/**
*/
Ptr<Dictionary> generateCustomDictionary(int nMarkers, int markerSize) {
Ptr<Dictionary> baseDictionary = makePtr<Dictionary>();
return generateCustomDictionary(nMarkers, markerSize, baseDictionary);
}
}
}

@ -62,7 +62,7 @@ CV_ArucoDetectionSimple::CV_ArucoDetectionSimple() {}
void CV_ArucoDetectionSimple::run(int) {
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
// 20 images
for(int i = 0; i < 20; i++) {
@ -99,7 +99,7 @@ void CV_ArucoDetectionSimple::run(int) {
// detect markers
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
aruco::detectMarkers(img, dictionary, corners, ids, params);
// check detection results
@ -183,7 +183,7 @@ static void getSyntheticRT(double yaw, double pitch, double distance, Mat &rvec,
/**
* @brief Create a synthetic image of a marker with perspective
*/
static Mat projectMarker(aruco::Dictionary dictionary, int id, Mat cameraMatrix, double yaw,
static Mat projectMarker(Ptr<aruco::Dictionary> &dictionary, int id, Mat cameraMatrix, double yaw,
double pitch, double distance, Size imageSize, int markerBorder,
vector< Point2f > &corners) {
@ -257,7 +257,7 @@ void CV_ArucoDetectionPerspective::run(int) {
cameraMatrix.at< double >(0, 0) = cameraMatrix.at< double >(1, 1) = 650;
cameraMatrix.at< double >(0, 2) = imgSize.width / 2;
cameraMatrix.at< double >(1, 2) = imgSize.height / 2;
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
// detect from different positions
for(double distance = 0.1; distance <= 0.5; distance += 0.2) {
@ -275,9 +275,9 @@ void CV_ArucoDetectionPerspective::run(int) {
// detect markers
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
params.minDistanceToBorder = 1;
params.markerBorderBits = markerBorder;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
params->minDistanceToBorder = 1;
params->markerBorderBits = markerBorder;
aruco::detectMarkers(img, dictionary, corners, ids, params);
// check results
@ -320,7 +320,7 @@ CV_ArucoDetectionMarkerSize::CV_ArucoDetectionMarkerSize() {}
void CV_ArucoDetectionMarkerSize::run(int) {
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
int markerSide = 20;
int imageSize = 200;
@ -337,10 +337,10 @@ void CV_ArucoDetectionMarkerSize::run(int) {
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
// set a invalid minMarkerPerimeterRate
params.minMarkerPerimeterRate = min(4., (4. * markerSide) / float(imageSize) + 0.1);
params->minMarkerPerimeterRate = min(4., (4. * markerSide) / float(imageSize) + 0.1);
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(corners.size() != 0) {
ts->printf(cvtest::TS::LOG, "Error in DetectorParameters::minMarkerPerimeterRate");
@ -349,7 +349,7 @@ void CV_ArucoDetectionMarkerSize::run(int) {
}
// set an valid minMarkerPerimeterRate
params.minMarkerPerimeterRate = max(0., (4. * markerSide) / float(imageSize) - 0.1);
params->minMarkerPerimeterRate = max(0., (4. * markerSide) / float(imageSize) - 0.1);
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(corners.size() != 1 || (corners.size() == 1 && ids[0] != id)) {
ts->printf(cvtest::TS::LOG, "Error in DetectorParameters::minMarkerPerimeterRate");
@ -358,7 +358,7 @@ void CV_ArucoDetectionMarkerSize::run(int) {
}
// set a invalid maxMarkerPerimeterRate
params.maxMarkerPerimeterRate = min(4., (4. * markerSide) / float(imageSize) - 0.1);
params->maxMarkerPerimeterRate = min(4., (4. * markerSide) / float(imageSize) - 0.1);
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(corners.size() != 0) {
ts->printf(cvtest::TS::LOG, "Error in DetectorParameters::maxMarkerPerimeterRate");
@ -367,7 +367,7 @@ void CV_ArucoDetectionMarkerSize::run(int) {
}
// set an valid maxMarkerPerimeterRate
params.maxMarkerPerimeterRate = max(0., (4. * markerSide) / float(imageSize) + 0.1);
params->maxMarkerPerimeterRate = max(0., (4. * markerSide) / float(imageSize) + 0.1);
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(corners.size() != 1 || (corners.size() == 1 && ids[0] != id)) {
ts->printf(cvtest::TS::LOG, "Error in DetectorParameters::maxMarkerPerimeterRate");
@ -395,11 +395,12 @@ CV_ArucoBitCorrection::CV_ArucoBitCorrection() {}
void CV_ArucoBitCorrection::run(int) {
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
aruco::Dictionary dictionary2 = dictionary;
Ptr<aruco::Dictionary> _dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
aruco::Dictionary &dictionary = *_dictionary;
aruco::Dictionary dictionary2 = *_dictionary;
int markerSide = 50;
int imageSize = 150;
aruco::DetectorParameters params;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
// 10 markers
for(int l = 0; l < 10; l++) {
@ -411,9 +412,9 @@ void CV_ArucoBitCorrection::run(int) {
// 5 valid cases
for(int i = 0; i < 5; i++) {
// how many bit errors (the error is low enough so it can be corrected)
params.errorCorrectionRate = 0.2 + i * 0.1;
params->errorCorrectionRate = 0.2 + i * 0.1;
int errors =
(int)std::floor(dictionary.maxCorrectionBits * params.errorCorrectionRate - 1.);
(int)std::floor(dictionary.maxCorrectionBits * params->errorCorrectionRate - 1.);
// create erroneous marker in currentCodeBits
Mat currentCodeBits =
@ -427,14 +428,14 @@ void CV_ArucoBitCorrection::run(int) {
Mat currentCodeBytesError = aruco::Dictionary::getByteListFromBits(currentCodeBits);
currentCodeBytesError.copyTo(dictionary2.bytesList.rowRange(id, id + 1));
Mat img = Mat(imageSize, imageSize, CV_8UC1, Scalar::all(255));
aruco::drawMarker(dictionary2, id, markerSide, marker);
dictionary2.drawMarker(id, markerSide, marker);
Mat aux = img.colRange(30, 30 + markerSide).rowRange(50, 50 + markerSide);
marker.copyTo(aux);
// try to detect using original dictionary
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::detectMarkers(img, dictionary, corners, ids, params);
aruco::detectMarkers(img, _dictionary, corners, ids, params);
if(corners.size() != 1 || (corners.size() == 1 && ids[0] != id)) {
ts->printf(cvtest::TS::LOG, "Error in bit correction");
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
@ -445,9 +446,9 @@ void CV_ArucoBitCorrection::run(int) {
// 5 invalid cases
for(int i = 0; i < 5; i++) {
// how many bit errors (the error is too high to be corrected)
params.errorCorrectionRate = 0.2 + i * 0.1;
params->errorCorrectionRate = 0.2 + i * 0.1;
int errors =
(int)std::floor(dictionary.maxCorrectionBits * params.errorCorrectionRate + 1.);
(int)std::floor(dictionary.maxCorrectionBits * params->errorCorrectionRate + 1.);
// create erroneous marker in currentCodeBits
Mat currentCodeBits =
@ -458,21 +459,23 @@ void CV_ArucoBitCorrection::run(int) {
}
// dictionary3 is only composed by the modified marker (in its original form)
aruco::Dictionary dictionary3 = dictionary;
dictionary3.bytesList = dictionary2.bytesList.rowRange(id, id + 1).clone();
Ptr<aruco::Dictionary> _dictionary3 = makePtr<aruco::Dictionary>(
dictionary2.bytesList.rowRange(id, id + 1).clone(),
dictionary.markerSize,
dictionary.maxCorrectionBits);
// add erroneous marker to dictionary2 in order to create the erroneous marker image
Mat currentCodeBytesError = aruco::Dictionary::getByteListFromBits(currentCodeBits);
currentCodeBytesError.copyTo(dictionary2.bytesList.rowRange(id, id + 1));
Mat img = Mat(imageSize, imageSize, CV_8UC1, Scalar::all(255));
aruco::drawMarker(dictionary2, id, markerSide, marker);
dictionary2.drawMarker(id, markerSide, marker);
Mat aux = img.colRange(30, 30 + markerSide).rowRange(50, 50 + markerSide);
marker.copyTo(aux);
// try to detect using dictionary3, it should fail
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::detectMarkers(img, dictionary3, corners, ids, params);
aruco::detectMarkers(img, _dictionary3, corners, ids, params);
if(corners.size() != 0) {
ts->printf(cvtest::TS::LOG, "Error in DetectorParameters::errorCorrectionRate");
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);

@ -98,7 +98,7 @@ static void getSyntheticRT(double yaw, double pitch, double distance, Mat &rvec,
/**
* @brief Project a synthetic marker
*/
static void projectMarker(Mat &img, aruco::Dictionary dictionary, int id,
static void projectMarker(Mat &img, Ptr<aruco::Dictionary> &dictionary, int id,
vector< Point3f > markerObjPoints, Mat cameraMatrix, Mat rvec, Mat tvec,
int markerBorder) {
@ -140,15 +140,15 @@ static void projectMarker(Mat &img, aruco::Dictionary dictionary, int id,
/**
* @brief Get a synthetic image of GridBoard in perspective
*/
static Mat projectBoard(aruco::GridBoard board, Mat cameraMatrix, double yaw, double pitch,
static Mat projectBoard(Ptr<aruco::GridBoard> &board, Mat cameraMatrix, double yaw, double pitch,
double distance, Size imageSize, int markerBorder) {
Mat rvec, tvec;
getSyntheticRT(yaw, pitch, distance, rvec, tvec);
Mat img = Mat(imageSize, CV_8UC1, Scalar::all(255));
for(unsigned int m = 0; m < board.ids.size(); m++) {
projectMarker(img, board.dictionary, board.ids[m], board.objPoints[m], cameraMatrix, rvec,
for(unsigned int m = 0; m < board->ids.size(); m++) {
projectMarker(img, board->dictionary, board->ids[m], board->objPoints[m], cameraMatrix, rvec,
tvec, markerBorder);
}
@ -177,8 +177,9 @@ void CV_ArucoBoardPose::run(int) {
int iter = 0;
Mat cameraMatrix = Mat::eye(3, 3, CV_64FC1);
Size imgSize(500, 500);
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
aruco::GridBoard board = aruco::GridBoard::create(3, 3, 0.02f, 0.005f, dictionary);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::GridBoard> gridboard = aruco::GridBoard::create(3, 3, 0.02f, 0.005f, dictionary);
Ptr<aruco::Board> board = gridboard.staticCast<aruco::Board>();
cameraMatrix.at< double >(0, 0) = cameraMatrix.at< double >(1, 1) = 650;
cameraMatrix.at< double >(0, 2) = imgSize.width / 2;
cameraMatrix.at< double >(1, 2) = imgSize.height / 2;
@ -188,21 +189,21 @@ void CV_ArucoBoardPose::run(int) {
for(double distance = 0.2; distance <= 0.4; distance += 0.2) {
for(int yaw = 0; yaw < 360; yaw += 100) {
for(int pitch = 30; pitch <= 90; pitch += 50) {
for(unsigned int i = 0; i < board.ids.size(); i++)
board.ids[i] = (iter + int(i)) % 250;
for(unsigned int i = 0; i < gridboard->ids.size(); i++)
gridboard->ids[i] = (iter + int(i)) % 250;
int markerBorder = iter % 2 + 1;
iter++;
// create synthetic image
Mat img = projectBoard(board, cameraMatrix, deg2rad(pitch), deg2rad(yaw), distance,
Mat img = projectBoard(gridboard, cameraMatrix, deg2rad(pitch), deg2rad(yaw), distance,
imgSize, markerBorder);
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
params.minDistanceToBorder = 3;
params.markerBorderBits = markerBorder;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
params->minDistanceToBorder = 3;
params->markerBorderBits = markerBorder;
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(ids.size() == 0) {
@ -218,8 +219,8 @@ void CV_ArucoBoardPose::run(int) {
// check result
for(unsigned int i = 0; i < ids.size(); i++) {
int foundIdx = -1;
for(unsigned int j = 0; j < board.ids.size(); j++) {
if(board.ids[j] == ids[i]) {
for(unsigned int j = 0; j < gridboard->ids.size(); j++) {
if(gridboard->ids[j] == ids[i]) {
foundIdx = int(j);
break;
}
@ -232,7 +233,7 @@ void CV_ArucoBoardPose::run(int) {
}
vector< Point2f > projectedCorners;
projectPoints(board.objPoints[foundIdx], rvec, tvec, cameraMatrix, distCoeffs,
projectPoints(gridboard->objPoints[foundIdx], rvec, tvec, cameraMatrix, distCoeffs,
projectedCorners);
for(int c = 0; c < 4; c++) {
@ -271,8 +272,9 @@ void CV_ArucoRefine::run(int) {
int iter = 0;
Mat cameraMatrix = Mat::eye(3, 3, CV_64FC1);
Size imgSize(500, 500);
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
aruco::GridBoard board = aruco::GridBoard::create(3, 3, 0.02f, 0.005f, dictionary);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::GridBoard> gridboard = aruco::GridBoard::create(3, 3, 0.02f, 0.005f, dictionary);
Ptr<aruco::Board> board = gridboard.staticCast<aruco::Board>();
cameraMatrix.at< double >(0, 0) = cameraMatrix.at< double >(1, 1) = 650;
cameraMatrix.at< double >(0, 2) = imgSize.width / 2;
cameraMatrix.at< double >(1, 2) = imgSize.height / 2;
@ -282,23 +284,23 @@ void CV_ArucoRefine::run(int) {
for(double distance = 0.2; distance <= 0.4; distance += 0.2) {
for(int yaw = 0; yaw < 360; yaw += 100) {
for(int pitch = 30; pitch <= 90; pitch += 50) {
for(unsigned int i = 0; i < board.ids.size(); i++)
board.ids[i] = (iter + int(i)) % 250;
for(unsigned int i = 0; i < gridboard->ids.size(); i++)
gridboard->ids[i] = (iter + int(i)) % 250;
int markerBorder = iter % 2 + 1;
iter++;
// create synthetic image
Mat img = projectBoard(board, cameraMatrix, deg2rad(pitch), deg2rad(yaw), distance,
Mat img = projectBoard(gridboard, cameraMatrix, deg2rad(pitch), deg2rad(yaw), distance,
imgSize, markerBorder);
// detect markers
vector< vector< Point2f > > corners, rejected;
vector< int > ids;
aruco::DetectorParameters params;
params.minDistanceToBorder = 3;
params.doCornerRefinement = true;
params.markerBorderBits = markerBorder;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
params->minDistanceToBorder = 3;
params->doCornerRefinement = true;
params->markerBorderBits = markerBorder;
aruco::detectMarkers(img, dictionary, corners, ids, params, rejected);
// remove a marker from detection

@ -98,7 +98,7 @@ static void getSyntheticRT(double yaw, double pitch, double distance, Mat &rvec,
/**
* @brief Project a synthetic marker
*/
static void projectMarker(Mat &img, aruco::Dictionary dictionary, int id,
static void projectMarker(Mat &img, Ptr<aruco::Dictionary> dictionary, int id,
vector< Point3f > markerObjPoints, Mat cameraMatrix, Mat rvec, Mat tvec,
int markerBorder) {
@ -176,7 +176,7 @@ static Mat projectChessboard(int squaresX, int squaresY, float squareSize, Size
/**
* @brief Check pose estimation of charuco board
*/
static Mat projectCharucoBoard(aruco::CharucoBoard board, Mat cameraMatrix, double yaw,
static Mat projectCharucoBoard(Ptr<aruco::CharucoBoard> &board, Mat cameraMatrix, double yaw,
double pitch, double distance, Size imageSize, int markerBorder,
Mat &rvec, Mat &tvec) {
@ -184,15 +184,15 @@ static Mat projectCharucoBoard(aruco::CharucoBoard board, Mat cameraMatrix, doub
// project markers
Mat img = Mat(imageSize, CV_8UC1, Scalar::all(255));
for(unsigned int m = 0; m < board.ids.size(); m++) {
projectMarker(img, board.dictionary, board.ids[m], board.objPoints[m], cameraMatrix, rvec,
for(unsigned int m = 0; m < board->ids.size(); m++) {
projectMarker(img, board->dictionary, board->ids[m], board->objPoints[m], cameraMatrix, rvec,
tvec, markerBorder);
}
// project chessboard
Mat chessboard =
projectChessboard(board.getChessboardSize().width, board.getChessboardSize().height,
board.getSquareLength(), imageSize, cameraMatrix, rvec, tvec);
projectChessboard(board->getChessboardSize().width, board->getChessboardSize().height,
board->getSquareLength(), imageSize, cameraMatrix, rvec, tvec);
for(unsigned int i = 0; i < chessboard.total(); i++) {
if(chessboard.ptr< unsigned char >()[i] == 0) {
@ -226,8 +226,8 @@ void CV_CharucoDetection::run(int) {
int iter = 0;
Mat cameraMatrix = Mat::eye(3, 3, CV_64FC1);
Size imgSize(500, 500);
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
aruco::CharucoBoard board = aruco::CharucoBoard::create(4, 4, 0.03f, 0.015f, dictionary);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create(4, 4, 0.03f, 0.015f, dictionary);
cameraMatrix.at< double >(0, 0) = cameraMatrix.at< double >(1, 1) = 650;
cameraMatrix.at< double >(0, 2) = imgSize.width / 2;
@ -251,9 +251,9 @@ void CV_CharucoDetection::run(int) {
// detect markers
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
params.minDistanceToBorder = 3;
params.markerBorderBits = markerBorder;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
params->minDistanceToBorder = 3;
params->markerBorderBits = markerBorder;
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(ids.size() == 0) {
@ -276,14 +276,14 @@ void CV_CharucoDetection::run(int) {
// check results
vector< Point2f > projectedCharucoCorners;
projectPoints(board.chessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
projectPoints(board->chessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
projectedCharucoCorners);
for(unsigned int i = 0; i < charucoIds.size(); i++) {
int currentId = charucoIds[i];
if(currentId >= (int)board.chessboardCorners.size()) {
if(currentId >= (int)board->chessboardCorners.size()) {
ts->printf(cvtest::TS::LOG, "Invalid Charuco corner id");
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return;
@ -325,8 +325,8 @@ void CV_CharucoPoseEstimation::run(int) {
int iter = 0;
Mat cameraMatrix = Mat::eye(3, 3, CV_64FC1);
Size imgSize(500, 500);
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
aruco::CharucoBoard board = aruco::CharucoBoard::create(4, 4, 0.03f, 0.015f, dictionary);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create(4, 4, 0.03f, 0.015f, dictionary);
cameraMatrix.at< double >(0, 0) = cameraMatrix.at< double >(1, 1) = 650;
cameraMatrix.at< double >(0, 2) = imgSize.width / 2;
@ -349,9 +349,9 @@ void CV_CharucoPoseEstimation::run(int) {
// detect markers
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
params.minDistanceToBorder = 3;
params.markerBorderBits = markerBorder;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
params->minDistanceToBorder = 3;
params->markerBorderBits = markerBorder;
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(ids.size() == 0) {
@ -381,14 +381,14 @@ void CV_CharucoPoseEstimation::run(int) {
// check result
vector< Point2f > projectedCharucoCorners;
projectPoints(board.chessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
projectPoints(board->chessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
projectedCharucoCorners);
for(unsigned int i = 0; i < charucoIds.size(); i++) {
int currentId = charucoIds[i];
if(currentId >= (int)board.chessboardCorners.size()) {
if(currentId >= (int)board->chessboardCorners.size()) {
ts->printf(cvtest::TS::LOG, "Invalid Charuco corner id");
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return;
@ -429,10 +429,10 @@ void CV_CharucoDiamondDetection::run(int) {
int iter = 0;
Mat cameraMatrix = Mat::eye(3, 3, CV_64FC1);
Size imgSize(500, 500);
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
float squareLength = 0.03f;
float markerLength = 0.015f;
aruco::CharucoBoard board =
Ptr<aruco::CharucoBoard> board =
aruco::CharucoBoard::create(3, 3, squareLength, markerLength, dictionary);
cameraMatrix.at< double >(0, 0) = cameraMatrix.at< double >(1, 1) = 650;
@ -447,7 +447,7 @@ void CV_CharucoDiamondDetection::run(int) {
int markerBorder = iter % 2 + 1;
for(int i = 0; i < 4; i++)
board.ids[i] = 4 * iter + i;
board->ids[i] = 4 * iter + i;
iter++;
// get synthetic image
@ -458,9 +458,9 @@ void CV_CharucoDiamondDetection::run(int) {
// detect markers
vector< vector< Point2f > > corners;
vector< int > ids;
aruco::DetectorParameters params;
params.minDistanceToBorder = 0;
params.markerBorderBits = markerBorder;
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
params->minDistanceToBorder = 0;
params->markerBorderBits = markerBorder;
aruco::detectMarkers(img, dictionary, corners, ids, params);
if(ids.size() != 4) {
@ -483,7 +483,7 @@ void CV_CharucoDiamondDetection::run(int) {
}
for(int i = 0; i < 4; i++) {
if(diamondIds[0][i] != board.ids[i]) {
if(diamondIds[0][i] != board->ids[i]) {
ts->printf(cvtest::TS::LOG, "Incorrect diamond ids");
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return;
@ -492,7 +492,7 @@ void CV_CharucoDiamondDetection::run(int) {
vector< Point2f > projectedDiamondCorners;
projectPoints(board.chessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
projectPoints(board->chessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
projectedDiamondCorners);
vector< Point2f > projectedDiamondCornersReorder(4);

Loading…
Cancel
Save