diff --git a/modules/aruco/samples/create_board_charuco.cpp b/modules/aruco/samples/create_board_charuco.cpp index 2a32500f700..4b714d793a8 100644 --- a/modules/aruco/samples/create_board_charuco.cpp +++ b/modules/aruco/samples/create_board_charuco.cpp @@ -1,45 +1,6 @@ -/* -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the names of the copyright holders nor the names of the contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as is" and -any express or implied warranties, including, but not limited to, the implied -warranties of merchantability and fitness for a particular purpose are -disclaimed. In no event shall copyright holders or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages -(including, but not limited to, procurement of substitute goods or services; -loss of use, data, or profits; or business interruption) however caused -and on any theory of liability, whether in contract, strict liability, -or tort (including negligence or otherwise) arising in any way out of -the use of this software, even if advised of the possibility of such damage. -*/ - - -#include -#include #include +#include +#include #include "aruco_samples_utility.hpp" using namespace cv; @@ -96,7 +57,9 @@ int main(int argc, char *argv[]) { aruco::Dictionary dictionary = aruco::getPredefinedDictionary(0); if (parser.has("d")) { int dictionaryId = parser.get("d"); - dictionary = aruco::getPredefinedDictionary(aruco::PredefinedDictionaryType(dictionaryId)); + dictionary = aruco::getPredefinedDictionary( + aruco::PredefinedDictionaryType(dictionaryId) + ); } else if (parser.has("cd")) { FileStorage fs(parser.get("cd"), FileStorage::READ); @@ -115,7 +78,9 @@ int main(int argc, char *argv[]) { imageSize.width = squaresX * squareLength + 2 * margins; imageSize.height = squaresY * squareLength + 2 * margins; - aruco::CharucoBoard board(Size(squaresX, squaresY), (float)squareLength, (float)markerLength, dictionary); + aruco::CharucoBoard board( + cv::Size(squaresX, squaresY), (float)squareLength, (float)markerLength, dictionary + ); // show created board Mat boardImage; diff --git a/modules/aruco/samples/create_diamond.cpp b/modules/aruco/samples/create_diamond.cpp index 1ccc0cd351a..c38a47c58c7 100644 --- a/modules/aruco/samples/create_diamond.cpp +++ b/modules/aruco/samples/create_diamond.cpp @@ -1,46 +1,7 @@ -/* -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the names of the copyright holders nor the names of the contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as is" and -any express or implied warranties, including, but not limited to, the implied -warranties of merchantability and fitness for a particular purpose are -disclaimed. In no event shall copyright holders or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages -(including, but not limited to, procurement of substitute goods or services; -loss of use, data, or profits; or business interruption) however caused -and on any theory of liability, whether in contract, strict liability, -or tort (including negligence or otherwise) arising in any way out of -the use of this software, even if advised of the possibility of such damage. -*/ - - -#include -#include -#include #include +#include +#include +#include using namespace std; using namespace cv; @@ -86,32 +47,36 @@ int main(int argc, char *argv[]) { return 0; } - aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::PredefinedDictionaryType(dictionaryId)); - istringstream ss(idsString); vector< string > splittedIds; string token; while(getline(ss, token, ',')) splittedIds.push_back(token); + if(splittedIds.size() < 4) { cerr << "Incorrect ids format" << endl; parser.printMessage(); return 0; } + Vec4i ids; for(int i = 0; i < 4; i++) ids[i] = atoi(splittedIds[i].c_str()); - Mat markerImg; - aruco::drawCharucoDiamond(makePtr(dictionary), ids, squareLength, markerLength, markerImg, margins, - borderBits); + cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(dictionaryId); + cv::aruco::CharucoBoard board(cv::Size(3, 3), (float)squareLength, (float)markerLength, dictionary, ids); + + cv::Mat diamondImage; + cv::Size imageSize(3 * squareLength, 3 * squareLength); + board.generateImage(imageSize, diamondImage, margins, borderBits); + if(showImage) { - imshow("board", markerImg); + imshow("board", diamondImage); waitKey(0); } - imwrite(out, markerImg); + imwrite(out, diamondImage); return 0; } diff --git a/modules/aruco/samples/detect_board_charuco.cpp b/modules/aruco/samples/detect_board_charuco.cpp index 68290e58d30..3fd8152c063 100644 --- a/modules/aruco/samples/detect_board_charuco.cpp +++ b/modules/aruco/samples/detect_board_charuco.cpp @@ -1,46 +1,7 @@ -/* -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the names of the copyright holders nor the names of the contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as is" and -any express or implied warranties, including, but not limited to, the implied -warranties of merchantability and fitness for a particular purpose are -disclaimed. In no event shall copyright holders or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages -(including, but not limited to, procurement of substitute goods or services; -loss of use, data, or profits; or business interruption) however caused -and on any theory of liability, whether in contract, strict liability, -or tort (including negligence or otherwise) arising in any way out of -the use of this software, even if advised of the possibility of such damage. -*/ - - -#include -#include -#include #include +#include +#include +#include #include "aruco_samples_utility.hpp" using namespace std; @@ -90,19 +51,19 @@ int main(int argc, char *argv[]) { video = parser.get("v"); } - Mat camMatrix, distCoeffs; + Mat cameraMatrix, distCoeffs; if(parser.has("c")) { - bool readOk = readCameraParameters(parser.get("c"), camMatrix, distCoeffs); + bool readOk = readCameraParameters(parser.get("c"), cameraMatrix, distCoeffs); if(!readOk) { cerr << "Invalid camera file" << endl; return 0; } } - Ptr detectorParams = makePtr(); + aruco::DetectorParameters detectorParams = aruco::DetectorParameters(); if(parser.has("dp")) { FileStorage fs(parser.get("dp"), FileStorage::READ); - bool readOk = detectorParams->readDetectorParameters(fs.root()); + bool readOk = detectorParams.readDetectorParameters(fs.root()); if(!readOk) { cerr << "Invalid detector parameters file" << endl; return 0; @@ -144,9 +105,18 @@ int main(int argc, char *argv[]) { float axisLength = 0.5f * ((float)min(squaresX, squaresY) * (squareLength)); - // create charuco board object - Ptr charucoboard = new aruco::CharucoBoard(Size(squaresX, squaresY), squareLength, markerLength, dictionary); - Ptr board = charucoboard.staticCast(); + // Create charuco board object + aruco::CharucoBoard board(Size(squaresX, squaresY), squareLength, markerLength, dictionary); + + aruco::CharucoParameters charucoParams; + charucoParams.cameraMatrix = cameraMatrix; + charucoParams.distCoeffs = distCoeffs; + + if(refindStrategy) { + charucoParams.tryRefineMarkers = true; + } + + aruco::CharucoDetector detector(board, charucoParams, detectorParams); // , refineParams); double totalTime = 0; int totalIterations = 0; @@ -157,34 +127,23 @@ int main(int argc, char *argv[]) { double tick = (double)getTickCount(); - vector< int > markerIds, charucoIds; - vector< vector< Point2f > > markerCorners, rejectedMarkers; - vector< Point2f > charucoCorners; + vector markerIds, charucoIds; + vector> markerCorners, rejectedMarkers; + vector charucoCorners; Vec3d rvec, tvec; - // detect markers - aruco::detectMarkers(image, makePtr(dictionary), markerCorners, markerIds, detectorParams, - rejectedMarkers); - - // refind strategy to detect more markers - if(refindStrategy) - aruco::refineDetectedMarkers(image, board, markerCorners, markerIds, rejectedMarkers, - camMatrix, distCoeffs); + detector.detectBoard(image, charucoCorners, charucoIds, markerCorners, markerIds); - // interpolate charuco corners - int interpolatedCorners = 0; - if(markerIds.size() > 0) - interpolatedCorners = - aruco::interpolateCornersCharuco(markerCorners, markerIds, image, charucoboard, - charucoCorners, charucoIds, camMatrix, distCoeffs); - - // estimate charuco board pose - bool validPose = false; - if(camMatrix.total() != 0) - validPose = estimatePoseCharucoBoard(charucoCorners, charucoIds, charucoboard, - camMatrix, distCoeffs, rvec, tvec); + // Estimate charuco board pose + Mat objPoints, imgPoints; + int markersOfBoardDetected = 0; + // Get object and image points for the solvePnP function + board.matchImagePoints(charucoCorners, charucoIds, objPoints, imgPoints); + // Find pose + solvePnP(objPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec); + markersOfBoardDetected = (int)objPoints.total() / 4; double currentTime = ((double)getTickCount() - tick) / getTickFrequency(); totalTime += currentTime; @@ -194,25 +153,25 @@ int main(int argc, char *argv[]) { << "(Mean = " << 1000 * totalTime / double(totalIterations) << " ms)" << endl; } - - - // draw results + // Draw results image.copyTo(imageCopy); - if(markerIds.size() > 0) { - aruco::drawDetectedMarkers(imageCopy, markerCorners); + if(!markerIds.empty()) { + aruco::drawDetectedMarkers(imageCopy, markerCorners); // , markerIds); } - if(showRejected && rejectedMarkers.size() > 0) + if(showRejected && !rejectedMarkers.empty()) { aruco::drawDetectedMarkers(imageCopy, rejectedMarkers, noArray(), Scalar(100, 0, 255)); + } - if(interpolatedCorners > 0) { + if(!charucoIds.empty()) { Scalar color; color = Scalar(255, 0, 0); aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, color); } - if(validPose) - cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvec, tvec, axisLength); + if(markersOfBoardDetected > 0) { + drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, axisLength); + } imshow("out", imageCopy); char key = (char)waitKey(waitTime); diff --git a/modules/aruco/samples/detect_diamonds.cpp b/modules/aruco/samples/detect_diamonds.cpp index 8baa267858a..f9ac9958d10 100644 --- a/modules/aruco/samples/detect_diamonds.cpp +++ b/modules/aruco/samples/detect_diamonds.cpp @@ -1,46 +1,7 @@ -/* -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the names of the copyright holders nor the names of the contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as is" and -any express or implied warranties, including, but not limited to, the implied -warranties of merchantability and fitness for a particular purpose are -disclaimed. In no event shall copyright holders or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages -(including, but not limited to, procurement of substitute goods or services; -loss of use, data, or profits; or business interruption) however caused -and on any theory of liability, whether in contract, strict liability, -or tort (including negligence or otherwise) arising in any way out of -the use of this software, even if advised of the possibility of such damage. -*/ - - -#include -#include -#include #include +#include +#include +#include #include "aruco_samples_utility.hpp" using namespace std; @@ -58,13 +19,9 @@ const char* keys = "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" "{cd | | Input file with custom dictionary }" "{c | | Output file with calibrated camera parameters }" - "{as | | Automatic scale. The provided number is multiplied by the last" - "diamond id becoming an indicator of the square length. In this case, the -sl and " - "-ml are only used to know the relative length relation between squares and markers }" "{v | | Input from video file, if ommited, input comes from camera }" "{ci | 0 | Camera id if input doesnt come from video (-v) }" "{dp | | File of marker detector parameters }" - "{rs | | Apply refind strategy }" "{refine | | Corner refinement: CORNER_REFINE_NONE=0, CORNER_REFINE_SUBPIX=1," "CORNER_REFINE_CONTOUR=2, CORNER_REFINE_APRILTAG=3}" "{r | | show rejected candidates too }"; @@ -84,23 +41,23 @@ int main(int argc, char *argv[]) { float markerLength = parser.get("ml"); bool showRejected = parser.has("r"); bool estimatePose = parser.has("c"); - bool autoScale = parser.has("as"); - float autoScaleFactor = autoScale ? parser.get("as") : 1.f; - Ptr detectorParams = makePtr(); + aruco::DetectorParameters detectorParams = aruco::DetectorParameters(); if(parser.has("dp")) { FileStorage fs(parser.get("dp"), FileStorage::READ); - bool readOk = detectorParams->readDetectorParameters(fs.root()); + bool readOk = detectorParams.readDetectorParameters(fs.root()); if(!readOk) { cerr << "Invalid detector parameters file" << endl; return 0; } } + if (parser.has("refine")) { //override cornerRefinementMethod read from config file - detectorParams->cornerRefinementMethod = parser.get("refine"); + detectorParams.cornerRefinementMethod = parser.get("refine"); } - std::cout << "Corner refinement method (0: None, 1: Subpixel, 2:contour, 3: AprilTag 2): " << (int)detectorParams->cornerRefinementMethod << std::endl; + std::cout << "Corner refinement method (0: None, 1: Subpixel, 2:contour, 3: AprilTag 2): " + << (int)detectorParams.cornerRefinementMethod << std::endl; int camId = parser.get("ci"); String video; @@ -132,9 +89,9 @@ int main(int argc, char *argv[]) { return 0; } - Mat camMatrix, distCoeffs; + Mat cameraMatrix, distCoeffs; if(estimatePose) { - bool readOk = readCameraParameters(parser.get("c"), camMatrix, distCoeffs); + bool readOk = readCameraParameters(parser.get("c"), cameraMatrix, distCoeffs); if(!readOk) { cerr << "Invalid camera file" << endl; return 0; @@ -151,6 +108,20 @@ int main(int argc, char *argv[]) { waitTime = 10; } + aruco::CharucoParameters charucoParams; + charucoParams.cameraMatrix = cameraMatrix; + charucoParams.distCoeffs = distCoeffs; + + aruco::CharucoBoard board(Size(3, 3), squareLength, markerLength, dictionary); + aruco::CharucoDetector detector(board, charucoParams, detectorParams); + + // Set coordinate system + cv::Mat objPoints(4, 1, CV_32FC3); + objPoints.ptr(0)[0] = Vec3f(-markerLength/2.f, markerLength/2.f, 0); + objPoints.ptr(0)[1] = Vec3f(markerLength/2.f, markerLength/2.f, 0); + objPoints.ptr(0)[2] = Vec3f(markerLength/2.f, -markerLength/2.f, 0); + objPoints.ptr(0)[3] = Vec3f(-markerLength/2.f, -markerLength/2.f, 0); + double totalTime = 0; int totalIterations = 0; @@ -160,67 +131,54 @@ int main(int argc, char *argv[]) { double tick = (double)getTickCount(); - vector< int > markerIds; - vector< Vec4i > diamondIds; - vector< vector< Point2f > > markerCorners, rejectedMarkers, diamondCorners; - vector< Vec3d > rvecs, tvecs; - - // detect markers - aruco::detectMarkers(image, makePtr(dictionary), markerCorners, markerIds, detectorParams, - rejectedMarkers); - - // detect diamonds - if(markerIds.size() > 0) - aruco::detectCharucoDiamond(image, markerCorners, markerIds, - squareLength / markerLength, diamondCorners, diamondIds, - camMatrix, distCoeffs); - - // estimate diamond pose - if(estimatePose && diamondIds.size() > 0) { - if(!autoScale) { - aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, camMatrix, - distCoeffs, rvecs, tvecs); - } else { - // if autoscale, extract square size from last diamond id - for(unsigned int i = 0; i < diamondCorners.size(); i++) { - float autoSquareLength = autoScaleFactor * float(diamondIds[i].val[3]); - vector< vector< Point2f > > currentCorners; - vector< Vec3d > currentRvec, currentTvec; - currentCorners.push_back(diamondCorners[i]); - aruco::estimatePoseSingleMarkers(currentCorners, autoSquareLength, camMatrix, - distCoeffs, currentRvec, currentTvec); - rvecs.push_back(currentRvec[0]); - tvecs.push_back(currentTvec[0]); - } + vector> markerCorners, rejectedMarkers; + vector markerIds; + vector> diamondCorners; + vector diamondIds; + + // Detect diamonds and markers + detector.detectDiamonds(image, diamondCorners, diamondIds, + markerCorners, markerIds); + + size_t nDiamonds = diamondCorners.size(); + vector rvecs(nDiamonds), tvecs(nDiamonds); + + // Estimate diamond poses + if(estimatePose && !markerCorners.empty()) { + for(size_t i = 0; i < nDiamonds; i++) { + solvePnP(objPoints, diamondCorners[i], cameraMatrix, + distCoeffs, rvecs[i], tvecs[i]); } } - double currentTime = ((double)getTickCount() - tick) / getTickFrequency(); totalTime += currentTime; totalIterations++; if(totalIterations % 30 == 0) { cout << "Detection Time = " << currentTime * 1000 << " ms " - << "(Mean = " << 1000 * totalTime / double(totalIterations) << " ms)" << endl; + << "(Mean = " << 1000 * totalTime / double(totalIterations) + << " ms)" << endl; } - - // draw results + // Draw results image.copyTo(imageCopy); - if(markerIds.size() > 0) - aruco::drawDetectedMarkers(imageCopy, markerCorners); + if(!markerIds.empty()) { + aruco::drawDetectedMarkers(imageCopy, markerCorners); + } - if(showRejected && rejectedMarkers.size() > 0) + if(showRejected && !rejectedMarkers.empty()) { aruco::drawDetectedMarkers(imageCopy, rejectedMarkers, noArray(), Scalar(100, 0, 255)); + } - if(diamondIds.size() > 0) { + if(!diamondIds.empty()) { aruco::drawDetectedDiamonds(imageCopy, diamondCorners, diamondIds); + } - if(estimatePose) { - for(unsigned int i = 0; i < diamondIds.size(); i++) - cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i], - squareLength * 1.1f); + if(estimatePose) { + for(unsigned int i = 0; i < diamondIds.size(); i++) { + drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, + rvecs[i], tvecs[i], squareLength * 1.1f); } } diff --git a/modules/aruco/samples/tutorial_charuco_create_detect.cpp b/modules/aruco/samples/tutorial_charuco_create_detect.cpp index 0e0d027a3ca..af4b0135ffc 100644 --- a/modules/aruco/samples/tutorial_charuco_create_detect.cpp +++ b/modules/aruco/samples/tutorial_charuco_create_detect.cpp @@ -1,127 +1,152 @@ -//! [charucohdr] -#include -//! [charucohdr] -#include #include #include +//! [charuco_header] +#include +//! [charuco_header] +#include #include "aruco_samples_utility.hpp" namespace { const char* about = "A tutorial code on charuco board creation and detection of charuco board with and without camera caliberation"; -const char* keys = "{c | | Put value of c=1 to create charuco board;\nc=2 to detect charuco board without camera calibration;\nc=3 to detect charuco board with camera calibration and Pose Estimation}"; +const char* keys = + "{c | | Put value of c=1 to create charuco board; c=2 to detect charuco board without camera calibration; c=3 to detect charuco board with camera calibration and Pose Estimation}"; } static inline void createBoard() { cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); - //! [createBoard] + + //! [charuco_create_board] cv::aruco::CharucoBoard board(cv::Size(5, 7), 0.04f, 0.02f, dictionary); cv::Mat boardImage; board.generateImage(cv::Size(600, 500), boardImage, 10, 1); - //! [createBoard] + //! [charuco_create_board] + cv::imwrite("BoardImage.jpg", boardImage); } -//! [detwcp] +//! [charuco_with_calib] static inline void detectCharucoBoardWithCalibrationPose() { cv::VideoCapture inputVideo; inputVideo.open(0); - //! [matdiscoff] + + //! [charuco_read_cam_params] cv::Mat cameraMatrix, distCoeffs; - std::string filename = "calib.txt"; + std::string filename = "../samples/tutorial_camera_params.yml"; bool readOk = readCameraParameters(filename, cameraMatrix, distCoeffs); - //! [matdiscoff] + //! [charuco_read_cam_params] + if (!readOk) { std::cerr << "Invalid camera file" << std::endl; - } else { - //! [dictboard] - cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); - cv::Ptr board = new cv::aruco::CharucoBoard(cv::Size(5, 7), 0.04f, 0.02f, dictionary); - cv::Ptr params = cv::makePtr(); - //! [dictboard] - while (inputVideo.grab()) { - //! [inputImg] - cv::Mat image; - //! [inputImg] - cv::Mat imageCopy; - inputVideo.retrieve(image); - image.copyTo(imageCopy); - //! [midcornerdet] - std::vector markerIds; - std::vector > markerCorners; - cv::aruco::detectMarkers(image, cv::makePtr(board->getDictionary()), markerCorners, markerIds, params); - //! [midcornerdet] - // if at least one marker detected - if (markerIds.size() > 0) { - cv::aruco::drawDetectedMarkers(imageCopy, markerCorners, markerIds); - //! [charidcor] - std::vector charucoCorners; - std::vector charucoIds; - cv::aruco::interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds, cameraMatrix, distCoeffs); - //! [charidcor] - // if at least one charuco corner detected - if (charucoIds.size() > 0) { - cv::Scalar color = cv::Scalar(255, 0, 0); - //! [detcor] - cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, color); - //! [detcor] - cv::Vec3d rvec, tvec; - //! [pose] - bool valid = cv::aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, board, cameraMatrix, distCoeffs, rvec, tvec); - //! [pose] - // if charuco pose is valid - if (valid) - cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1f); - } - } - cv::imshow("out", imageCopy); - char key = (char)cv::waitKey(30); - if (key == 27) - break; + return; + } + + //! [charuco_board_params] + cv::aruco::CharucoParameters charucoParams; + charucoParams.cameraMatrix = cameraMatrix; + charucoParams.distCoeffs = distCoeffs; + + cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters(); + cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); + + cv::aruco::CharucoBoard board(cv::Size(5, 7), 0.04f, 0.02f, dictionary); + cv::aruco::CharucoDetector detector(board, charucoParams, detectorParams); + //! [charuco_board_params] + + while (inputVideo.grab()) { + cv::Mat image; + + cv::Mat imageCopy; + inputVideo.retrieve(image); + image.copyTo(imageCopy); + + //! [charuco_detect_board] + std::vector markerIds; + std::vector charucoIds; + std::vector> markerCorners; + std::vector charucoCorners; + + detector.detectBoard(image, charucoCorners, charucoIds, markerCorners, markerIds); + //! [charuco_detect_board] + + // If at least one marker detected + if (!charucoIds.empty()) { + cv::aruco::drawDetectedMarkers(imageCopy, markerCorners, markerIds); } + + // If at least one charuco corner detected + if (!charucoIds.empty()) { + //! [charuco_draw_corners] + cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds); + //! [charuco_draw_corners] + + //! [charuco_pose_estimation] + cv::Vec3d rvec, tvec; + cv::Mat objPoints, imgPoints; + int markersOfBoardDetected = 0; + + // Get object and image points for the solvePnP function + board.matchImagePoints(charucoCorners, charucoIds, objPoints, imgPoints); + // Find pose + cv::solvePnP(objPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec); + //! [charuco_pose_estimation] + + // If charuco pose is valid + markersOfBoardDetected = (int)objPoints.total() / 4; + if (markersOfBoardDetected != 0) + cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1f); + } + + cv::imshow("out", imageCopy); + char key = (char)cv::waitKey(30); + if (key == 27) + break; } } -//! [detwcp] +//! [charuco_with_calib] -//! [detwc] +//! [charuco_wo_calib] static inline void detectCharucoBoardWithoutCalibration() { cv::VideoCapture inputVideo; + inputVideo.open(0); + + std::vector markerIds; + std::vector charucoIds; + std::vector> markerCorners; + std::vector charucoCorners; + cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); - cv::Ptr board = new cv::aruco::CharucoBoard(cv::Size(5, 7), 0.04f, 0.02f, dictionary); + cv::aruco::CharucoBoard board(cv::Size(5, 7), 0.04f, 0.02f, dictionary); + cv::aruco::CharucoDetector detector(board); - cv::Ptr params = cv::makePtr(); - params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_NONE; while (inputVideo.grab()) { cv::Mat image, imageCopy; inputVideo.retrieve(image); image.copyTo(imageCopy); - std::vector markerIds; - std::vector > markerCorners; - cv::aruco::detectMarkers(image, cv::makePtr(board->getDictionary()), markerCorners, markerIds, params); - //or - //cv::aruco::detectMarkers(image, dictionary, markerCorners, markerIds, params); - // if at least one marker detected - if (markerIds.size() > 0) { - cv::aruco::drawDetectedMarkers(imageCopy, markerCorners, markerIds); - //! [charidcorwc] - std::vector charucoCorners; - std::vector charucoIds; - cv::aruco::interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds); - //! [charidcorwc] - // if at least one charuco corner detected - if (charucoIds.size() > 0) - cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, cv::Scalar(255, 0, 0)); + + // Detect markers and interpolate corners + detector.detectBoard(image, charucoCorners, charucoIds, markerCorners, markerIds); + + // If at least one marker detected + if (!charucoIds.empty()) { + cv::aruco::drawDetectedMarkers(imageCopy, markerCorners); //, markerIds); } + + // If at least one charuco corner detected + if (!charucoCorners.empty()) { + cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds); + } + cv::imshow("out", imageCopy); char key = (char)cv::waitKey(30); if (key == 27) break; } } -//! [detwc] +//! [charuco_wo_calib] int main(int argc, char* argv[]) { diff --git a/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown b/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown index 5d47ce59269..060fb4fe5ff 100644 --- a/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown +++ b/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown @@ -28,14 +28,14 @@ Goal In this tutorial you will learn: -- How to create a charuco board ? -- How to detect the charuco corners without performing camera calibration ? -- How to detect the charuco corners with camera calibration and pose estimation ? +- How to create a charuco board? +- How to detect the charuco corners without performing camera calibration? +- How to detect the charuco corners with camera calibration and pose estimation? Source code ----------- -You can find this code in `opencv_contrib/modules/aruco/samples/tutorial_charuco_create_detect.cpp` +You can find this code in `tutorial_charuco_create_detect.cpp` in `samples` folder. Here's a sample code of how to achieve all the stuff enumerated at the goal list. @@ -44,13 +44,13 @@ Here's a sample code of how to achieve all the stuff enumerated at the goal list ChArUco Board Creation ------ -The aruco module provides the ```cv::aruco::CharucoBoard``` class that represents a Charuco Board and which inherits from the ```Board``` class. +The aruco module provides the `cv::aruco::CharucoBoard` class that represents a Charuco Board and which inherits from the `cv::aruco::Board` class. This class, as the rest of ChArUco functionalities, are defined in: -@snippet samples/tutorial_charuco_create_detect.cpp charucohdr +@snippet samples/tutorial_charuco_create_detect.cpp charuco_header -To define a ```CharucoBoard```, it is necessary: +To define a `CharucoBoard`, it is necessary: - Number of chessboard squares in X direction. - Number of chessboard squares in Y direction. @@ -59,42 +59,38 @@ To define a ```CharucoBoard```, it is necessary: - The dictionary of the markers. - Ids of all the markers. -As for the ```GridBoard``` objects, the aruco module provides a function to create ```CharucoBoard```s easily. This function -is the static function ```cv::aruco::CharucoBoard::create()``` : +You can easily create `CharucoBoard` by passing parameters to its constructor: @code{.cpp} - cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary); + aruco::CharucoBoard board(Size(squaresX, squaresY), squareLength, markerLength, dictionary, markerIds); @endcode - The first and second parameters are the number of squares in X and Y direction respectively. - The third and fourth parameters are the length of the squares and the markers respectively. They can be provided in any unit, having in mind that the estimated pose for this board would be measured in the same units (usually meters are used). - Finally, the dictionary of the markers is provided. +- If you don't provide ids of the markerr, they are assigned by default in ascending order and starting on 0. -The ids of each of the markers are assigned by default in ascending order and starting on 0, like in ```GridBoard::create()```. -This can be easily customized by accessing to the ids vector through ```board.ids```, like in the ```Board``` parent class. +Once we have our `CharucoBoard` object, we can create an image to print it. This can be done with the `aruco::CharucoBoard::generateImage` method: -Once we have our ```CharucoBoard``` object, we can create an image to print it. This can be done with the -CharucoBoard::generateImage() method: - -@snippet samples/tutorial_charuco_create_detect.cpp createBoard +@snippet samples/tutorial_charuco_create_detect.cpp charuco_create_board - The first parameter is the size of the output image in pixels. In this case 600x500 pixels. If this is not proportional to the board dimensions, it will be centered on the image. -- ```boardImage```: the output image with the board. +- `boardImage`: the output image with the board. - The third parameter is the (optional) margin in pixels, so none of the markers are touching the image border. In this case the margin is 10. -- Finally, the size of the marker border, similarly to ```generateImageMarker()``` function. The default value is 1. +- Finally, the size of the marker border, similarly to `generateImageMarker` function. The default value is 1. The output image will be something like this: ![](images/charucoboard.png) -A full working example is included in the `create_board_charuco.cpp` inside the `modules/aruco/samples/`. +A full working example is included in the `create_board_charuco.cpp` inside the `samples` directory. Note: The create_board_charuco.cpp now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like @code{.cpp} - "_output_path_/chboard.png" -w=5 -h=7 -sl=200 -ml=120 -d=10 + -w=5 -h=7 -sl=200 -ml=120 -d=10 charuco_board.png @endcode @@ -106,64 +102,45 @@ When you detect a ChArUco board, what you are actually detecting is each of the Each corner on a ChArUco board has a unique identifier (id) assigned. These ids go from 0 to the total number of corners in the board. The steps of charuco board detection can be broken down to the following steps: -- **Taking input Image** - -@snippet samples/tutorial_charuco_create_detect.cpp inputImg - -The original image where the markers are to be detected. The image is necessary to perform subpixel refinement in the ChArUco corners. - -- **Reading the camera calibration Parameters(only for detection with camera calibration)** +- **Reading the camera calibration Parameters (only for detection with camera calibration)** -@snippet samples/tutorial_charuco_create_detect.cpp matdiscoff +@snippet samples/tutorial_charuco_create_detect.cpp charuco_read_cam_params -The parameters of readCameraParameters are: -- filename- This is the path to caliberation.txt file which is the output file generated by calibrate_camera_charuco.cpp -- cameraMatrix and distCoeffs- the optional camera calibration parameters +The parameters of `readCameraParameters` are: +- filename - The path to `yaml` file which is the output file generated by calibrate_camera_charuco.cpp +- cameraMatrix and distCoeffs - `readCameraParameters` fills these variables with camera calibration parameters This function takes these parameters as input and returns a boolean value of whether the camera calibration parameters are valid or not. For detection of corners without calibration, this step is not required. -- **Detecting the markers** - -@snippet samples/tutorial_charuco_create_detect.cpp dictboard -@snippet samples/tutorial_charuco_create_detect.cpp midcornerdet - -The parameters of detectMarkers are: -- image - Input image. -- dictionary - Pointer to the Dictionary/Set of Markers that will be searched. -- markerCorners - vector of detected marker corners. -- markerIds - vector of identifiers of the detected markers -- params - marker detection parameters -The detection of the ChArUco corners is based on the previous detected markers. So that, first markers are detected, and then ChArUco corners are interpolated from markers. +- **Detecting the markers and interpolate charuco corners** -- **Interpolation of charuco corners from markers** +The detection of the ChArUco corners is based on the detected markers. First, markers are detected, and then ChArUco corners are interpolated from the markers. -For detection with calibration +@snippet samples/tutorial_charuco_create_detect.cpp charuco_board_params +@snippet samples/tutorial_charuco_create_detect.cpp charuco_detect_board -@snippet samples/tutorial_charuco_create_detect.cpp charidcor - -For detection without calibration - -@snippet samples/tutorial_charuco_create_detect.cpp charidcorwc - -The function that detect the ChArUco corners is cv::aruco::interpolateCornersCharuco(). This function returns the number of Charuco corners interpolated. - -- ```std::vector charucoCorners``` : list of image positions of the detected corners. -- ```std::vector charucoIds``` : ids for each of the detected corners in ```charucoCorners```. - -If calibration parameters are provided, the ChArUco corners are interpolated by, first, estimating a rough pose from the ArUco markers -and, then, reprojecting the ChArUco corners back to the image. +The parameters of detectBoard are: +- image - Input image +- charucoCorners - list of image positions of the detected corners +- charucoIds - ids for each of the detected corners in `charucoCorners` +- markerCorners - vector of detected marker corners +- markerIds - vector of identifiers of the detected markers -On the other hand, if calibration parameters are not provided, the ChArUco corners are interpolated by calculating the -corresponding homography between the ChArUco plane and the ChArUco image projection. +If calibration parameters are provided, the ChArUco corners are interpolated by, first, +estimating a rough pose from the ArUco markers and, then, reprojecting the ChArUco corners +back to the image. If calibration parameters are not provided, the ChArUco corners are +interpolated by calculating the corresponding homography between the ChArUco plane +and the ChArUco image projection. -The main problem of using homography is that the interpolation is more sensible to image distortion. Actually, the homography is only performed -using the closest markers of each ChArUco corner to reduce the effect of distortion. +The main problem of using homography is that the interpolation is more sensible to image distortion. +Actually, the homography is only performed using the closest markers of each ChArUco corner to reduce +the effect of distortion. -When detecting markers for ChArUco boards, and specially when using homography, it is recommended to disable the corner refinement of markers. The reason of this -is that, due to the proximity of the chessboard squares, the subpixel process can produce important -deviations in the corner positions and these deviations are propagated to the ChArUco corner interpolation, -producing poor results. +When detecting markers for ChArUco boards, and specially when using homography, it is recommended +to disable the corner refinement of markers. The reason of this is that, due to the proximity +of the chessboard squares, the subpixel process can produce important deviations in the corner positions +and these deviations are propagated to the ChArUco corner interpolation, producing poor results. Furthermore, only those corners whose two surrounding markers have be found are returned. If any of the two surrounding markers has not been detected, this usually means that there is some occlusion or the image quality is not good in that zone. In any case, it is @@ -172,16 +149,15 @@ preferable not to consider that corner, since what we want is to be sure that th After the ChArUco corners have been interpolated, a subpixel refinement is performed. Once we have interpolated the ChArUco corners, we would probably want to draw them to see if their detections are correct. -This can be easily done using the ```drawDetectedCornersCharuco()``` function: +This can be easily done using the `drawDetectedCornersCharuco()` function: -@snippet samples/tutorial_charuco_create_detect.cpp detcor +@snippet samples/tutorial_charuco_create_detect.cpp charuco_draw_corners -- ```imageCopy``` is the image where the corners will be drawn (it will normally be the same image where the corners were detected). -- The ```outputImage``` will be a clone of ```inputImage``` with the corners drawn. -- ```charucoCorners``` and ```charucoIds``` are the detected Charuco corners from the ```interpolateCornersCharuco()``` function. -- Finally, the last parameter is the (optional) color we want to draw the corners with, of type ```cv::Scalar```. +- `imageCopy` is the image where the corners will be drawn (it will normally be the same image where the corners were detected). +- `charucoCorners` and `charucoIds` are the detected Charuco corners from the `detectBoard()` method. +- The last optional parameter is the `cv::Scalar` type - color we want to draw the corners with. -For this image: +For the image: ![Image with Charuco board](images/choriginal.jpg) @@ -195,7 +171,7 @@ In the presence of occlusion. like in the following image, although some corners Finally, this is a full example of ChArUco detection (without using calibration parameters): -@snippet samples/tutorial_charuco_create_detect.cpp detwc +@snippet samples/tutorial_charuco_create_detect.cpp charuco_wo_calib Sample video: @@ -203,7 +179,7 @@ Sample video: @endhtmlonly -A full working example is included in the `detect_board_charuco.cpp` inside the `modules/aruco/samples/`. +A full working example is included in the `detect_board_charuco.cpp` inside the `samples` folder. Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like @code{.cpp} @@ -216,30 +192,24 @@ ChArUco Pose Estimation The final goal of the ChArUco boards is finding corners very accurately for a high precision calibration or pose estimation. -The aruco module provides a function to perform ChArUco pose estimation easily. As in the ```GridBoard```, the coordinate system -of the ```CharucoBoard``` is placed in the board plane with the Z axis pointing out, and centered in the bottom left corner of the board. +The aruco module provides a function to perform ChArUco pose estimation easily. As in the `GridBoard`, the coordinate system +of the `CharucoBoard` is placed in the board plane with the Z axis pointing out, and centered in the bottom left corner of the board. -The function for pose estimation is ```estimatePoseCharucoBoard()```: +The function for pose estimation is `solvePnP()`: -@snippet samples/tutorial_charuco_create_detect.cpp pose +@snippet samples/tutorial_charuco_create_detect.cpp charuco_pose_estimation -- The ```charucoCorners``` and ```charucoIds``` parameters are the detected charuco corners from the ```interpolateCornersCharuco()``` -function. -- The third parameter is the ```CharucoBoard``` object. -- The ```cameraMatrix``` and ```distCoeffs``` are the camera calibration parameters which are necessary for pose estimation. -- Finally, the ```rvec``` and ```tvec``` parameters are the output pose of the Charuco Board. -- The function returns true if the pose was correctly estimated and false otherwise. The main reason of failing is that there are -not enough corners for pose estimation or they are in the same line. +The `rvec` and `tvec` parameters are the output pose of the Charuco Board. `solvePnP` returns true if the pose was correctly estimated and false otherwise. The main reason of failing is that there are not enough corners for pose estimation or they are in the same line. -The axis can be drawn using ```drawFrameAxes()``` to check the pose is correctly estimated. The result would be: (X:red, Y:green, Z:blue) +The axis can be drawn using `drawFrameAxes()` to check the pose is correctly estimated. The result would be: (X:red, Y:green, Z:blue) ![Charuco Board Axis](images/chaxis.jpg) A full example of ChArUco detection with pose estimation: -@snippet samples/tutorial_charuco_create_detect.cpp detwcp +@snippet samples/tutorial_charuco_create_detect.cpp charuco_with_calib -A full working example is included in the `detect_board_charuco.cpp` inside the `modules/aruco/samples/detect_board_charuco.cpp`. +A full working example is included in the `detect_board_charuco.cpp` in `samples` folder. Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like @code{.cpp} diff --git a/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown b/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown index 946f878c617..70cd84fb3ed 100644 --- a/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown +++ b/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown @@ -33,95 +33,90 @@ up to N^4 different ids, being N the number of markers in the used dictionary. - Give to each of the four markers a conceptual meaning. For instance, one of the four marker ids could be used to indicate the scale of the marker (i.e. the size of the square), so that the same diamond can be found in the environment with different sizes just by changing one of the four markers and the user does not need -to manually indicate the scale of each of them. This case is included in the ```diamond_detector.cpp``` file inside +to manually indicate the scale of each of them. This case is included in the `detect_diamonds.cpp` file inside the samples folder of the module. Furthermore, as its corners are chessboard corners, they can be used for accurate pose estimation. -The diamond functionalities are included in `````` +The diamond functionalities are included in `` ChArUco Diamond Creation ------ -The image of a diamond marker can be easily created using the ```drawCharucoDiamond()``` function. +The image of a diamond marker can be easily created using the CharucoBoard `generateImage` method. For instance: @code{.cpp} + int squareLength = 200; + int markerLength = 120; + + cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); + cv::aruco::CharucoBoard board(cv::Size(3, 3), squareLength, markerLength, dictionary); + cv::Mat diamondImage; - cv::Ptr dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); - cv::aruco::drawCharucoDiamond(dictionary, cv::Vec4i(45,68,28,74), 200, 120, markerImage); + board.generateImage(cv::Size(600, 600), diamondImage); @endcode This will create a diamond marker image with a square size of 200 pixels and a marker size of 120 pixels. -The marker ids are given in the second parameter as a ```Vec4i``` object. The order of the marker ids -in the diamond layout are the same as in a standard ChArUco board, i.e. top, left, right and bottom. - The image produced will be: ![Diamond marker](images/diamondmarker.png) -A full working example is included in the `create_diamond.cpp` inside the `modules/aruco/samples/`. +A full working example is included in the `create_diamond.cpp` inside the `samples` folder. Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like @code{.cpp} - "_path_/mydiamond.png" -sl=200 -ml=120 -d=10 -ids=45,68,28,74 + -sl=200 -ml=120 -d=10 -ids=0,1,2,3 charuco_diamond.png @endcode -ChArUco Diamond Detection +ChArUco Diamonds Detection ------ -As in most cases, the detection of diamond markers requires a previous detection of ArUco markers. -After detecting markers, diamond are detected using the ```detectCharucoDiamond()``` function: +Diamonds detection consists of two steps: detection of the ArUco markers and then detection of the ChArUco boards, and this can be easily done with a single call of the detector's `detectDiamonds()` method: @code{.cpp} - cv::Mat inputImage; + Mat inputImage; float squareLength = 0.40; float markerLength = 0.25; ... + // Initialize 3x3 board and detector + aruco::CharucoBoard board(Size(3, 3), squareLength, markerLength); + aruco::CharucoDetector detector(board); - std::vector markerIds; - std::vector> markerCorners; - - // detect ArUco markers - cv::aruco::detectMarkers(inputImage, dictionary, markerCorners, markerIds); - - std::vector diamondIds; - std::vector> diamondCorners; - - // detect diamon diamonds - cv::aruco::detectCharucoDiamond(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds); + // Detect diamonds + vector markerIds; + vector> markerCorners; + vector diamondIds; + vector> diamondCorners; + detector.detectDiamonds(inputImage, diamondCorners, diamondIds, markerCorners, markerIds); @endcode -The ```detectCharucoDiamond()``` function receives the original image and the previous detected marker corners and ids. -The input image is necessary to perform subpixel refinement in the ChArUco corners. -It also receives the rate between the square size and the marker sizes which is required for both, detecting the diamond -from the relative positions of the markers and interpolating the ChArUco corners. - -The function returns the detected diamonds in two parameters. The first parameter, ```diamondCorners```, is an array containing -all the four corners of each detected diamond. Its format is similar to the detected corners by the ```detectMarkers()``` +The `detectDiamonds()` function returns the detected diamonds in two parameters. The first parameter, `diamondCorners`, is an array containing +all the four corners of each detected diamond. Its format is similar to the detected corners by the `detectMarkers()` function and, for each diamond, the corners are represented in the same order than in the ArUco markers, i.e. clockwise order -starting with the top-left corner. The second returned parameter, ```diamondIds```, contains all the ids of the returned -diamond corners in ```diamondCorners```. Each id is actually an array of 4 integers that can be represented with ```Vec4i```. +starting with the top-left corner. The second returned parameter, `diamondIds`, contains all the ids of the returned +diamond corners in `diamondCorners`. Each id is actually an array of 4 integers that can be represented with `Vec4i`. The `markerCorners` and the `markerIds` are return in the same way. -The detected diamond can be visualized using the function ```drawDetectedDiamonds()``` which simply receives the image and the diamond +The detected diamond can be visualized using the function `drawDetectedDiamonds()` which simply receives the image and the diamond corners and ids: @code{.cpp} ... - std::vector diamondIds; - std::vector> diamondCorners; - cv::aruco::detectCharucoDiamond(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds); - cv::aruco::drawDetectedDiamonds(inputImage, diamondCorners, diamondIds); + vector diamondIds; + vector> diamondCorners; + detector.detectDiamonds(inputImage, diamondCorners, diamondIds); + + aruco::drawDetectedDiamonds(inputImage, diamondCorners, diamondIds); @endcode -The result is the same that the one produced by ```drawDetectedMarkers()```, but printing the four ids of the diamond: +The result is the same that the one produced by `drawDetectedMarkers()`, but printing the four ids of the diamond: ![Detected diamond markers](images/detecteddiamonds.png) -A full working example is included in the `detect_diamonds.cpp` inside the `modules/aruco/samples/`. +A full working example is included in the `detect_diamonds.cpp` inside the `samples` folder. Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like @code{.cpp} @@ -134,31 +129,30 @@ ChArUco Diamond Pose Estimation ------ Since a ChArUco diamond is represented by its four corners, its pose can be estimated in the same way than in a single ArUco marker, -i.e. using the ```estimatePoseSingleMarkers()``` function. For instance: +i.e. using the `solvePnP()` function. For instance: @code{.cpp} ... - std::vector diamondIds; - std::vector> diamondCorners; - - // detect diamon diamonds - cv::aruco::detectCharucoDiamond(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds); + // Detect diamonds + detector.detectDiamonds(inputImage, diamondCorners, diamondIds); - // estimate poses - std::vector rvecs, tvecs; - cv::aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, camMatrix, distCoeffs, rvecs, tvecs); + // Estimate diamond poses + int nDiamonds = diamondCorners.size(); + vector rvecs(nDiamonds), tvecs(nDiamonds); + for(size_t i = 0; i < nDiamonds; i++) + solvePnP(objPoints, diamondCorners.at(i), cameraMatrix, distCoeffs, rvecs.at(i), tvecs.at(i)); - // draw axis - for(unsigned int i=0; i @endhtmlonly -A full working example is included in the `detect_diamonds.cpp` inside the `modules/aruco/samples/`. +A full working example is included in the `detect_diamonds.cpp` inside the `samples` folder. Note: The samples now take input via commandline via the [OpenCV Commandline Parser](http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0). For this file the example parameters will look like @code{.cpp}