#include "opencv2/ccalib/randpattern.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/calib3d.hpp" #include #include #include using namespace std; using namespace cv; const char * usage = "\n example command line for calibrate a camera by random pattern. \n" " random_pattern_calibration -pw 600 -ph 850 -mm 20 image_list.xml \n" "\n" " the file image_list.xml is generated by imagelist_creator as\n" "imagelist_creator image_list.xml *.*"; static void help() { printf("\n This is a sample for camera calibration by a random pattern.\n" "Usage: random_pattern_calibration\n" " -pw # the physical width of random pattern\n" " -ph # the physical height of random pattern\n" " -mm # minimal number of matches\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 bool readStringList( const string& filename, vector& l ) { l.resize(0); FileStorage fs(filename, FileStorage::READ); if( !fs.isOpened() ) return false; FileNode n = fs.getFirstTopLevelNode(); if( n.type() != FileNode::SEQ ) return false; FileNodeIterator it = n.begin(), it_end = n.end(); for( ; it != it_end; ++it ) l.push_back((string)*it); return true; } static void saveCameraParams(const string& filename, Size imageSize, float patternWidth, float patternHeight, int flags, const Mat& cameraMatrix, const Mat& distCoeffs, const vector& rvecs, const vector& tvecs, double rms) { FileStorage fs (filename, FileStorage::WRITE ); time_t tt; time( &tt ); struct tm *t2 = localtime( &tt ); char buf[1024]; strftime( buf, sizeof(buf)-1, "%c", t2 ); fs << "calibration_time" << buf; if( !rvecs.empty()) fs << "nframes" << (int)rvecs.size(); fs << "image_width" << imageSize.width; fs << "image_height" << imageSize.height; fs << "pattern_width" << patternWidth; fs << "pattern_height" << patternHeight; fs << "flags" < imglist; vector vecImg; int flags = 0; float patternWidth = 0.0f, patternHeight = 0.0f; int nMiniMatches = 0; if(argc < 2) { help(); return 1; } for (int i = 1; i < argc; ++i) { const char* s = argv[i]; if(strcmp(s, "-pw") == 0) { if(sscanf(argv[++i], "%f", &patternWidth) != 1 || patternWidth <= 0) return fprintf( stderr, "Invalid pattern width\n"), -1; } else if(strcmp(s, "-ph") == 0) { if(sscanf(argv[++i], "%f", &patternHeight) != 1 || patternHeight <= 0) return fprintf( stderr, "Invalid pattern height\n"), -1; } else if (strcmp(s, "-mm") == 0) { if (sscanf(argv[++i], "%d", &nMiniMatches) != 1 || nMiniMatches < 15) return fprintf( stderr, "Invalid number of minimal matches or number is too small"), -1; } else if( strcmp( s, "-fp" ) == 0 ) { flags |= CALIB_FIX_PRINCIPAL_POINT; } else if( s[0] != '-') { inputFilename = s; } else { return fprintf( stderr, "Unknown option %s\n", s ), -1; } } readStringList(inputFilename, imglist); // the first image is the pattern Mat pattern = cv::imread(imglist[0], cv::IMREAD_GRAYSCALE); for (int i = 1; i < (int)imglist.size(); ++i) { Mat img; img = cv::imread(imglist[i], cv::IMREAD_GRAYSCALE); vecImg.push_back(img); } randpattern::RandomPatternCornerFinder finder(patternWidth, patternHeight, nMiniMatches); finder.loadPattern(pattern); finder.computeObjectImagePoints(vecImg); vector objectPoints = finder.getObjectPoints(); vector imagePoints = finder.getImagePoints(); Mat K; Mat D; vector rvec, tvec; double rms = calibrateCamera(objectPoints, imagePoints, vecImg[0].size(), K, D, rvec, tvec); saveCameraParams(outputFilename, vecImg[0].size(), patternWidth, patternHeight, flags, K, D, rvec, tvec, rms); }