You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
5.3 KiB
161 lines
5.3 KiB
#include "opencv2/ccalib/randpattern.hpp" |
|
#include "opencv2/highgui.hpp" |
|
#include "opencv2/imgproc.hpp" |
|
#include "opencv2/calib3d.hpp" |
|
#include <vector> |
|
#include <iostream> |
|
#include <time.h> |
|
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 <pattern_width> # the physical width of random pattern\n" |
|
" -ph <pattern_height> # the physical height of random pattern\n" |
|
" -mm <minimal_match> # 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<string>& 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<Mat>& rvecs, const vector<Mat>& 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" <<flags; |
|
|
|
fs << "camera_matrix" << cameraMatrix; |
|
fs << "distortion_coefficients" << distCoeffs; |
|
|
|
fs << "rms" << rms; |
|
|
|
if( !rvecs.empty() && !tvecs.empty() ) |
|
{ |
|
CV_Assert(rvecs[0].type() == tvecs[0].type()); |
|
Mat bigmat((int)rvecs.size(), 6, rvecs[0].type()); |
|
for( int i = 0; i < (int)rvecs.size(); i++ ) |
|
{ |
|
Mat r = bigmat(Range(i, i+1), Range(0,3)); |
|
Mat t = bigmat(Range(i, i+1), Range(3,6)); |
|
|
|
CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1); |
|
CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1); |
|
//*.t() is MatExpr (not Mat) so we can use assignment operator |
|
r = rvecs[i].t(); |
|
t = tvecs[i].t(); |
|
} |
|
//cvWriteComment( *fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0 ); |
|
fs << "extrinsic_parameters" << bigmat; |
|
} |
|
} |
|
|
|
int main(int argc, char** argv) |
|
{ |
|
const char* inputFilename = 0; |
|
const char* outputFilename = "out_camera_params.xml"; |
|
vector<string> imglist; |
|
vector<Mat> 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<Mat> objectPoints = finder.getObjectPoints(); |
|
vector<Mat> imagePoints = finder.getImagePoints(); |
|
|
|
Mat K; |
|
Mat D; |
|
vector<Mat> 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); |
|
}
|
|
|