Merge pull request #23515 from vovka643:4.x_aruco_stereo_calibration

added aruco pattern support into stereo_calibration.cpp
pull/23637/head
Alexander Smorkalov 2 years ago committed by GitHub
commit bcb49d71b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 121
      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 <vector>
#include <string>
@ -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=<board_width default=9> -h=<board_height default=6> -s=<square_size default=1.0> <image list XML/YML file default=stereo_calib.xml>\n" << endl;
cout << "Usage:\n " << argv[0] << " -w=<board_width default=9> -h=<board_height default=6>"
<<" -t=<pattern type: chessboard or charucoboard default=chessboard> -s=<square_size default=1.0> -ms=<marker size default=0.5>"
<<" -ad=<predefined aruco dictionary name default=DICT_4X4_50> -adf=<aruco dictionary file default=None>"
<<" <image list XML/YML file default=stereo_calib.xml>\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<string>& imagelist, Size boardSize, float squareSize, bool displayCorners = false, bool useCalibrated=true, bool showRectified=true)
StereoCalib(const vector<string>& 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<string>& imagelist, Size boardSize, float squareSize, b
imagePoints[1].resize(nimages);
vector<string> 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<int> markerIds;
for( i = j = 0; i < nimages; i++ )
{
for( k = 0; k < 2; k++ )
@ -99,8 +141,19 @@ StereoCalib(const vector<string>& 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<string>& 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<string>& 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<string>& 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<string>& 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<string>("@input"));
boardSize.width = parser.get<int>("w");
boardSize.height = parser.get<int>("h");
inputBoardSize.width = parser.get<int>("w");
inputBoardSize.height = parser.get<int>("h");
string type = parser.get<string>("t");
float squareSize = parser.get<float>("s");
float markerSize = parser.get<float>("ms");
string arucoDictName = parser.get<string>("ad");
string arucoDictFile = parser.get<string>("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;
}

Loading…
Cancel
Save