From fa5c5f4105b0866dbb96701d569a7b595d838e6c Mon Sep 17 00:00:00 2001 From: vovka643 Date: Sun, 16 Apr 2023 13:43:38 +0300 Subject: [PATCH] added aruco pattern into stereo_calibration.cpp --- samples/cpp/stereo_calib.cpp | 121 ++++++++++++++++++++++++++++++----- 1 file changed, 104 insertions(+), 17 deletions(-) diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index bfc3b22d71..c583c8fa09 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -24,6 +24,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/objdetect/charuco_detector.hpp" #include #include @@ -40,21 +41,31 @@ using namespace std; static int print_help(char** argv) { cout << - " Given a list of chessboard images, the number of corners (nx, ny)\n" - " on the chessboards, and a flag: useCalibrated for \n" + " Given a list of chessboard or ChArUco images, the number of corners (nx, ny)\n" + " on the chessboards and the number of squares (nx, ny) on ChArUco,\n" + " and a flag: useCalibrated for \n" " calibrated (0) or\n" " uncalibrated \n" " (1: use stereoCalibrate(), 2: compute fundamental\n" " matrix separately) stereo. \n" " Calibrate the cameras and display the\n" " rectified results along with the computed disparity images. \n" << endl; - cout << "Usage:\n " << argv[0] << " -w= -h= -s= \n" << endl; + cout << "Usage:\n " << argv[0] << " -w= -h=" + <<" -t= -s= -ms=" + <<" -ad= -adf=" + <<" \n" << endl; + cout << "Available Aruco dictionaries: DICT_4X4_50, DICT_4X4_100, DICT_4X4_250, " + << "DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, DICT_5X5_1000, " + << "DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, " + << "DICT_7X7_100, DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, " + << "DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11\n"; + return 0; } static void -StereoCalib(const vector& imagelist, Size boardSize, float squareSize, bool displayCorners = false, bool useCalibrated=true, bool showRectified=true) +StereoCalib(const vector& imagelist, Size inputBoardSize, string type, float squareSize, float markerSize, cv::aruco::PredefinedDictionaryType arucoDict, string arucoDictFile, bool displayCorners = false, bool useCalibrated=true, bool showRectified=true) { if( imagelist.size() % 2 != 0 ) { @@ -75,6 +86,37 @@ StereoCalib(const vector& imagelist, Size boardSize, float squareSize, b imagePoints[1].resize(nimages); vector goodImageList; + Size boardSizeInnerCorners, boardSizeUnits; + if (type == "chessboard") { + //chess board pattern boardSize is given in inner corners + boardSizeInnerCorners = inputBoardSize; + boardSizeUnits.height = inputBoardSize.height+1; + boardSizeUnits.width = inputBoardSize.width+1; + } + else if (type == "charucoboard") { + //ChArUco board pattern boardSize is given in squares units + boardSizeUnits = inputBoardSize; + boardSizeInnerCorners.width = inputBoardSize.width - 1; + boardSizeInnerCorners.height = inputBoardSize.height - 1; + } + else { + std::cout << "unknown pattern type " << type << "\n"; + return; + } + + cv::aruco::Dictionary dictionary; + if (arucoDictFile == "None") { + dictionary = cv::aruco::getPredefinedDictionary(arucoDict); + } + else { + cv::FileStorage dict_file(arucoDictFile, cv::FileStorage::Mode::READ); + cv::FileNode fn(dict_file.root()); + dictionary.readDictionary(fn); + } + cv::aruco::CharucoBoard ch_board(boardSizeUnits, squareSize, markerSize, dictionary); + cv::aruco::CharucoDetector ch_detector(ch_board); + std::vector markerIds; + for( i = j = 0; i < nimages; i++ ) { for( k = 0; k < 2; k++ ) @@ -99,8 +141,19 @@ StereoCalib(const vector& imagelist, Size boardSize, float squareSize, b timg = img; else resize(img, timg, Size(), scale, scale, INTER_LINEAR_EXACT); - found = findChessboardCorners(timg, boardSize, corners, - CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE); + + if (type == "chessboard") { + found = findChessboardCorners(timg, boardSizeInnerCorners, corners, + CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE); + } + else if (type == "charucoboard") { + ch_detector.detectBoard(timg, corners, markerIds); + found = corners.size() == (size_t) (boardSizeInnerCorners.height*boardSizeInnerCorners.width); + } + else { + cout << "Error: unknown pattern " << type << "\n"; + return; + } if( found ) { if( scale > 1 ) @@ -116,7 +169,7 @@ StereoCalib(const vector& imagelist, Size boardSize, float squareSize, b cout << filename << endl; Mat cimg, cimg1; cvtColor(img, cimg, COLOR_GRAY2BGR); - drawChessboardCorners(cimg, boardSize, corners, found); + drawChessboardCorners(cimg, boardSizeInnerCorners, corners, found); double sf = 640./MAX(img.rows, img.cols); resize(cimg, cimg1, Size(), sf, sf, INTER_LINEAR_EXACT); imshow("corners", cimg1); @@ -128,9 +181,11 @@ StereoCalib(const vector& imagelist, Size boardSize, float squareSize, b putchar('.'); if( !found ) break; - cornerSubPix(img, corners, Size(11,11), Size(-1,-1), - TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, - 30, 0.01)); + if (type == "chessboard") { + cornerSubPix(img, corners, Size(11, 11), Size(-1, -1), + TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, + 30, 0.01)); + } } if( k == 2 ) { @@ -153,8 +208,8 @@ StereoCalib(const vector& imagelist, Size boardSize, float squareSize, b for( i = 0; i < nimages; i++ ) { - for( j = 0; j < boardSize.height; j++ ) - for( k = 0; k < boardSize.width; k++ ) + for( j = 0; j < boardSizeInnerCorners.height; j++ ) + for( k = 0; k < boardSizeInnerCorners.width; k++ ) objectPoints[i].push_back(Point3f(k*squareSize, j*squareSize, 0)); } @@ -342,17 +397,49 @@ static bool readStringList( const string& filename, vector& l ) int main(int argc, char** argv) { - Size boardSize; + Size inputBoardSize; string imagelistfn; bool showRectified; - cv::CommandLineParser parser(argc, argv, "{w|9|}{h|6|}{s|1.0|}{nr||}{help||}{@input|stereo_calib.xml|}"); + cv::CommandLineParser parser(argc, argv, "{w|9|}{h|6|}{t|chessboard|}{s|1.0|}{ms|0.5|}{ad|DICT_4X4_50|}{adf|None|}{nr||}{help||}{@input|stereo_calib.xml|}"); if (parser.has("help")) return print_help(argv); showRectified = !parser.has("nr"); imagelistfn = samples::findFile(parser.get("@input")); - boardSize.width = parser.get("w"); - boardSize.height = parser.get("h"); + inputBoardSize.width = parser.get("w"); + inputBoardSize.height = parser.get("h"); + string type = parser.get("t"); float squareSize = parser.get("s"); + float markerSize = parser.get("ms"); + string arucoDictName = parser.get("ad"); + string arucoDictFile = parser.get("adf"); + + cv::aruco::PredefinedDictionaryType arucoDict; + if (arucoDictName == "DICT_4X4_50") { arucoDict = cv::aruco::DICT_4X4_50; } + else if (arucoDictName == "DICT_4X4_100") { arucoDict = cv::aruco::DICT_4X4_100; } + else if (arucoDictName == "DICT_4X4_250") { arucoDict = cv::aruco::DICT_4X4_250; } + else if (arucoDictName == "DICT_4X4_1000") { arucoDict = cv::aruco::DICT_4X4_1000; } + else if (arucoDictName == "DICT_5X5_50") { arucoDict = cv::aruco::DICT_5X5_50; } + else if (arucoDictName == "DICT_5X5_100") { arucoDict = cv::aruco::DICT_5X5_100; } + else if (arucoDictName == "DICT_5X5_250") { arucoDict = cv::aruco::DICT_5X5_250; } + else if (arucoDictName == "DICT_5X5_1000") { arucoDict = cv::aruco::DICT_5X5_1000; } + else if (arucoDictName == "DICT_6X6_50") { arucoDict = cv::aruco::DICT_6X6_50; } + else if (arucoDictName == "DICT_6X6_100") { arucoDict = cv::aruco::DICT_6X6_100; } + else if (arucoDictName == "DICT_6X6_250") { arucoDict = cv::aruco::DICT_6X6_250; } + else if (arucoDictName == "DICT_6X6_1000") { arucoDict = cv::aruco::DICT_6X6_1000; } + else if (arucoDictName == "DICT_7X7_50") { arucoDict = cv::aruco::DICT_7X7_50; } + else if (arucoDictName == "DICT_7X7_100") { arucoDict = cv::aruco::DICT_7X7_100; } + else if (arucoDictName == "DICT_7X7_250") { arucoDict = cv::aruco::DICT_7X7_250; } + else if (arucoDictName == "DICT_7X7_1000") { arucoDict = cv::aruco::DICT_7X7_1000; } + else if (arucoDictName == "DICT_ARUCO_ORIGINAL") { arucoDict = cv::aruco::DICT_ARUCO_ORIGINAL; } + else if (arucoDictName == "DICT_APRILTAG_16h5") { arucoDict = cv::aruco::DICT_APRILTAG_16h5; } + else if (arucoDictName == "DICT_APRILTAG_25h9") { arucoDict = cv::aruco::DICT_APRILTAG_25h9; } + else if (arucoDictName == "DICT_APRILTAG_36h10") { arucoDict = cv::aruco::DICT_APRILTAG_36h10; } + else if (arucoDictName == "DICT_APRILTAG_36h11") { arucoDict = cv::aruco::DICT_APRILTAG_36h11; } + else { + cout << "incorrect name of aruco dictionary \n"; + return 1; + } + if (!parser.check()) { parser.printErrors(); @@ -366,6 +453,6 @@ int main(int argc, char** argv) return print_help(argv); } - StereoCalib(imagelist, boardSize, squareSize, false, true, showRectified); + StereoCalib(imagelist, inputBoardSize, type, squareSize, markerSize, arucoDict, arucoDictFile, false, true, showRectified); return 0; }