|
|
@ -11,31 +11,7 @@ |
|
|
|
using namespace cv; |
|
|
|
using namespace cv; |
|
|
|
using namespace std; |
|
|
|
using namespace std; |
|
|
|
|
|
|
|
|
|
|
|
const char * usage = |
|
|
|
static void calcChessboardCorners(const Size &boardSize, const Size2d &squareSize, Mat& corners) |
|
|
|
"\n example command line for omnidirectional camera calibration.\n" |
|
|
|
|
|
|
|
" omni_calibration -w 6 -h 9 -sw 80 -sh 80 imagelist.xml \n" |
|
|
|
|
|
|
|
" \n" |
|
|
|
|
|
|
|
" the file imagelist.xml is generated by imagelist_creator as\n" |
|
|
|
|
|
|
|
"imagelist_creator imagelist.xml *.*"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void help() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("\n This is a sample for omnidirectional camera calibration.\n" |
|
|
|
|
|
|
|
"Usage: omni_calibration\n" |
|
|
|
|
|
|
|
" -w <board_width> # the number of inner corners per one of board dimension\n" |
|
|
|
|
|
|
|
" -h <board_height> # the number of inner corners per another board dimension\n" |
|
|
|
|
|
|
|
" [-sw <square_width>] # the width of square in some user-defined units (1 by default)\n" |
|
|
|
|
|
|
|
" [-sh <square_height>] # the height of square in some user-defined units (1 by default)\n" |
|
|
|
|
|
|
|
" [-o <out_camera_params>] # the output filename for intrinsic [and extrinsic] parameters\n" |
|
|
|
|
|
|
|
" [-fs <fix_skew>] # fix skew\n" |
|
|
|
|
|
|
|
" [-fp ] # fix the principal point at the center\n" |
|
|
|
|
|
|
|
" input_data # input data - text file with a list of the images of the board, which is generated by imagelist_creator" |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
printf("\n %s", usage); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void calcChessboardCorners(Size boardSize, double square_width, double square_height, |
|
|
|
|
|
|
|
Mat& corners) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// corners has type of CV_64FC3
|
|
|
|
// corners has type of CV_64FC3
|
|
|
|
corners.release(); |
|
|
|
corners.release(); |
|
|
@ -46,7 +22,7 @@ static void calcChessboardCorners(Size boardSize, double square_width, double sq |
|
|
|
{ |
|
|
|
{ |
|
|
|
for (int j = 0; j < boardSize.width; ++j) |
|
|
|
for (int j = 0; j < boardSize.width; ++j) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ptr[i*boardSize.width + j] = Vec3d(double(j * square_width), double(i * square_height), 0.0); |
|
|
|
ptr[i*boardSize.width + j] = Vec3d(double(j * squareSize.width), double(i * squareSize.height), 0.0); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -60,6 +36,7 @@ static bool detecChessboardCorners(const vector<string>& list, vector<string>& l |
|
|
|
Mat img; |
|
|
|
Mat img; |
|
|
|
for(int i = 0; i < n_img; ++i) |
|
|
|
for(int i = 0; i < n_img; ++i) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
cout << list[i] << "... "; |
|
|
|
Mat points; |
|
|
|
Mat points; |
|
|
|
img = imread(list[i], IMREAD_GRAYSCALE); |
|
|
|
img = imread(list[i], IMREAD_GRAYSCALE); |
|
|
|
bool found = findChessboardCorners( img, boardSize, points); |
|
|
|
bool found = findChessboardCorners( img, boardSize, points); |
|
|
@ -70,6 +47,7 @@ static bool detecChessboardCorners(const vector<string>& list, vector<string>& l |
|
|
|
imagePoints.push_back(points); |
|
|
|
imagePoints.push_back(points); |
|
|
|
list_detected.push_back(list[i]); |
|
|
|
list_detected.push_back(list[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
cout << (found ? "FOUND" : "NO") << endl; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!img.empty()) |
|
|
|
if (!img.empty()) |
|
|
|
imageSize = img.size(); |
|
|
|
imageSize = img.size(); |
|
|
@ -169,78 +147,64 @@ static void saveCameraParams( const string & filename, int flags, const Mat& cam |
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv) |
|
|
|
int main(int argc, char** argv) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Size boardSize, imageSize; |
|
|
|
cv::CommandLineParser parser(argc, argv, |
|
|
|
int flags = 0; |
|
|
|
"{w||board width}" |
|
|
|
double square_width = 0.0, square_height = 0.0; |
|
|
|
"{h||board height}" |
|
|
|
const char* outputFilename = "out_camera_params.xml"; |
|
|
|
"{sw|1.0|square width}" |
|
|
|
const char* inputFilename = 0; |
|
|
|
"{sh|1.0|square height}" |
|
|
|
vector<Mat> objectPoints; |
|
|
|
"{o|out_camera_params.xml|output file}" |
|
|
|
vector<Mat> imagePoints; |
|
|
|
"{fs|false|fix skew}" |
|
|
|
|
|
|
|
"{fp|false|fix principal point at the center}" |
|
|
|
if(argc < 2) |
|
|
|
"{@input||input file - xml file with a list of the images, created with cpp-example-imagelist_creator tool}" |
|
|
|
|
|
|
|
"{help||show help}" |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
parser.about("This is a sample for omnidirectional camera calibration. Example command line:\n" |
|
|
|
|
|
|
|
" omni_calibration -w=6 -h=9 -sw=80 -sh=80 imagelist.xml \n"); |
|
|
|
|
|
|
|
if (parser.has("help") || !parser.has("w") || !parser.has("h")) |
|
|
|
{ |
|
|
|
{ |
|
|
|
help(); |
|
|
|
parser.printMessage(); |
|
|
|
return 1; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(int i = 1; i < argc; i++) |
|
|
|
Size boardSize(parser.get<int>("w"), parser.get<int>("h")); |
|
|
|
{ |
|
|
|
Size2d squareSize(parser.get<double>("sw"), parser.get<double>("sh")); |
|
|
|
const char* s = argv[i]; |
|
|
|
int flags = 0; |
|
|
|
if( strcmp( s, "-w") == 0) |
|
|
|
if (parser.get<bool>("fs")) |
|
|
|
{ |
|
|
|
|
|
|
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 ) |
|
|
|
|
|
|
|
return fprintf( stderr, "Invalid board width\n" ), -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( strcmp( s, "-h" ) == 0 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 ) |
|
|
|
|
|
|
|
return fprintf( stderr, "Invalid board height\n" ), -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( strcmp( s, "-sw" ) == 0 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( sscanf( argv[++i], "%lf", &square_width ) != 1 || square_width <= 0 ) |
|
|
|
|
|
|
|
return fprintf(stderr, "Invalid square width\n"), -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( strcmp( s, "-sh" ) == 0 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( sscanf( argv[++i], "%lf", &square_height) != 1 || square_height <= 0 ) |
|
|
|
|
|
|
|
return fprintf(stderr, "Invalid square height\n"), -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( strcmp( s, "-o" ) == 0 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
outputFilename = argv[++i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( strcmp( s, "-fs" ) == 0 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
flags |= omnidir::CALIB_FIX_SKEW; |
|
|
|
flags |= omnidir::CALIB_FIX_SKEW; |
|
|
|
} |
|
|
|
if (parser.get<bool>("fp")) |
|
|
|
else if( strcmp( s, "-fp" ) == 0 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
flags |= omnidir::CALIB_FIX_CENTER; |
|
|
|
flags |= omnidir::CALIB_FIX_CENTER; |
|
|
|
} |
|
|
|
const string outputFilename = parser.get<string>("o"); |
|
|
|
else if( s[0] != '-') |
|
|
|
const string inputFilename = parser.get<string>(0); |
|
|
|
{ |
|
|
|
|
|
|
|
inputFilename = s; |
|
|
|
if (!parser.check()) |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
return fprintf( stderr, "Unknown option %s\n", s ), -1; |
|
|
|
parser.printErrors(); |
|
|
|
} |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// get image name list
|
|
|
|
// get image name list
|
|
|
|
vector<string> image_list, detec_list; |
|
|
|
vector<string> image_list, detec_list; |
|
|
|
if(!readStringList(inputFilename, image_list)) |
|
|
|
if(!readStringList(inputFilename, image_list)) |
|
|
|
return fprintf( stderr, "Failed to read image list\n"), -1; |
|
|
|
{ |
|
|
|
|
|
|
|
cout << "Can not read imagelist" << endl; |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// find corners in images
|
|
|
|
// find corners in images
|
|
|
|
// some images may be failed in automatic corner detection, passed cases are in detec_list
|
|
|
|
// some images may be failed in automatic corner detection, passed cases are in detec_list
|
|
|
|
|
|
|
|
cout << "Detecting chessboards (" << image_list.size() << ")" << endl; |
|
|
|
|
|
|
|
vector<Mat> imagePoints; |
|
|
|
|
|
|
|
Size imageSize; |
|
|
|
if(!detecChessboardCorners(image_list, detec_list, imagePoints, boardSize, imageSize)) |
|
|
|
if(!detecChessboardCorners(image_list, detec_list, imagePoints, boardSize, imageSize)) |
|
|
|
return fprintf(stderr, "Not enough corner detected images\n"), -1; |
|
|
|
{ |
|
|
|
|
|
|
|
cout << "Not enough corner detected images" << endl; |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// calculate object coordinates
|
|
|
|
// calculate object coordinates
|
|
|
|
|
|
|
|
vector<Mat> objectPoints; |
|
|
|
Mat object; |
|
|
|
Mat object; |
|
|
|
calcChessboardCorners(boardSize, square_width, square_height, object); |
|
|
|
calcChessboardCorners(boardSize, squareSize, object); |
|
|
|
for(int i = 0; i < (int)detec_list.size(); ++i) |
|
|
|
for(int i = 0; i < (int)detec_list.size(); ++i) |
|
|
|
objectPoints.push_back(object); |
|
|
|
objectPoints.push_back(object); |
|
|
|
|
|
|
|
|
|
|
@ -252,6 +216,7 @@ int main(int argc, char** argv) |
|
|
|
TermCriteria criteria(3, 200, 1e-8); |
|
|
|
TermCriteria criteria(3, 200, 1e-8); |
|
|
|
rms = omnidir::calibrate(objectPoints, imagePoints, imageSize, K, xi, D, rvecs, tvecs, flags, criteria, idx); |
|
|
|
rms = omnidir::calibrate(objectPoints, imagePoints, imageSize, K, xi, D, rvecs, tvecs, flags, criteria, idx); |
|
|
|
_xi = xi.at<double>(0); |
|
|
|
_xi = xi.at<double>(0); |
|
|
|
|
|
|
|
cout << "Saving camera params to " << outputFilename << endl; |
|
|
|
saveCameraParams(outputFilename, flags, K, D, _xi, |
|
|
|
saveCameraParams(outputFilename, flags, K, D, _xi, |
|
|
|
rvecs, tvecs, detec_list, idx, rms, imagePoints); |
|
|
|
rvecs, tvecs, detec_list, idx, rms, imagePoints); |
|
|
|
} |
|
|
|
} |
|
|
|