random_pattern_calibration.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include "opencv2/ccalib/randpattern.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include "opencv2/imgproc.hpp"
  4. #include "opencv2/calib3d.hpp"
  5. #include <vector>
  6. #include <iostream>
  7. #include <time.h>
  8. using namespace std;
  9. using namespace cv;
  10. const char * usage =
  11. "\n example command line for calibrate a camera by random pattern. \n"
  12. " random_pattern_calibration -pw 600 -ph 850 -mm 20 image_list.xml \n"
  13. "\n"
  14. " the file image_list.xml is generated by imagelist_creator as\n"
  15. "imagelist_creator image_list.xml *.*";
  16. static void help()
  17. {
  18. printf("\n This is a sample for camera calibration by a random pattern.\n"
  19. "Usage: random_pattern_calibration\n"
  20. " -pw <pattern_width> # the physical width of random pattern\n"
  21. " -ph <pattern_height> # the physical height of random pattern\n"
  22. " -mm <minimal_match> # minimal number of matches\n"
  23. " [-fp ] # fix the principal point at the center \n"
  24. " input_data # input data - text file with a list of the images of the board, which is generated by imagelist_creator"
  25. );
  26. printf("\n %s", usage);
  27. }
  28. static bool readStringList( const string& filename, vector<string>& l )
  29. {
  30. l.resize(0);
  31. FileStorage fs(filename, FileStorage::READ);
  32. if( !fs.isOpened() )
  33. return false;
  34. FileNode n = fs.getFirstTopLevelNode();
  35. if( n.type() != FileNode::SEQ )
  36. return false;
  37. FileNodeIterator it = n.begin(), it_end = n.end();
  38. for( ; it != it_end; ++it )
  39. l.push_back((string)*it);
  40. return true;
  41. }
  42. static void saveCameraParams(const string& filename, Size imageSize, float patternWidth,
  43. float patternHeight, int flags, const Mat& cameraMatrix, const Mat& distCoeffs,
  44. const vector<Mat>& rvecs, const vector<Mat>& tvecs, double rms)
  45. {
  46. FileStorage fs (filename, FileStorage::WRITE );
  47. time_t tt;
  48. time( &tt );
  49. struct tm *t2 = localtime( &tt );
  50. char buf[1024];
  51. strftime( buf, sizeof(buf)-1, "%c", t2 );
  52. fs << "calibration_time" << buf;
  53. if( !rvecs.empty())
  54. fs << "nframes" << (int)rvecs.size();
  55. fs << "image_width" << imageSize.width;
  56. fs << "image_height" << imageSize.height;
  57. fs << "pattern_width" << patternWidth;
  58. fs << "pattern_height" << patternHeight;
  59. fs << "flags" <<flags;
  60. fs << "camera_matrix" << cameraMatrix;
  61. fs << "distortion_coefficients" << distCoeffs;
  62. fs << "rms" << rms;
  63. if( !rvecs.empty() && !tvecs.empty() )
  64. {
  65. CV_Assert(rvecs[0].type() == tvecs[0].type());
  66. Mat bigmat((int)rvecs.size(), 6, rvecs[0].type());
  67. for( int i = 0; i < (int)rvecs.size(); i++ )
  68. {
  69. Mat r = bigmat(Range(i, i+1), Range(0,3));
  70. Mat t = bigmat(Range(i, i+1), Range(3,6));
  71. CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1);
  72. CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1);
  73. //*.t() is MatExpr (not Mat) so we can use assignment operator
  74. r = rvecs[i].t();
  75. t = tvecs[i].t();
  76. }
  77. //cvWriteComment( *fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0 );
  78. fs << "extrinsic_parameters" << bigmat;
  79. }
  80. }
  81. int main(int argc, char** argv)
  82. {
  83. const char* inputFilename = 0;
  84. const char* outputFilename = "out_camera_params.xml";
  85. vector<string> imglist;
  86. vector<Mat> vecImg;
  87. int flags = 0;
  88. float patternWidth = 0.0f, patternHeight = 0.0f;
  89. int nMiniMatches = 0;
  90. if(argc < 2)
  91. {
  92. help();
  93. return 1;
  94. }
  95. for (int i = 1; i < argc; ++i)
  96. {
  97. const char* s = argv[i];
  98. if(strcmp(s, "-pw") == 0)
  99. {
  100. if(sscanf(argv[++i], "%f", &patternWidth) != 1 || patternWidth <= 0)
  101. return fprintf( stderr, "Invalid pattern width\n"), -1;
  102. }
  103. else if(strcmp(s, "-ph") == 0)
  104. {
  105. if(sscanf(argv[++i], "%f", &patternHeight) != 1 || patternHeight <= 0)
  106. return fprintf( stderr, "Invalid pattern height\n"), -1;
  107. }
  108. else if (strcmp(s, "-mm") == 0)
  109. {
  110. if (sscanf(argv[++i], "%d", &nMiniMatches) != 1 || nMiniMatches < 15)
  111. return fprintf( stderr, "Invalid number of minimal matches or number is too small"), -1;
  112. }
  113. else if( strcmp( s, "-fp" ) == 0 )
  114. {
  115. flags |= CALIB_FIX_PRINCIPAL_POINT;
  116. }
  117. else if( s[0] != '-')
  118. {
  119. inputFilename = s;
  120. }
  121. else
  122. {
  123. return fprintf( stderr, "Unknown option %s\n", s ), -1;
  124. }
  125. }
  126. readStringList(inputFilename, imglist);
  127. // the first image is the pattern
  128. Mat pattern = cv::imread(imglist[0], cv::IMREAD_GRAYSCALE);
  129. for (int i = 1; i < (int)imglist.size(); ++i)
  130. {
  131. Mat img;
  132. img = cv::imread(imglist[i], cv::IMREAD_GRAYSCALE);
  133. vecImg.push_back(img);
  134. }
  135. randpattern::RandomPatternCornerFinder finder(patternWidth, patternHeight, nMiniMatches);
  136. finder.loadPattern(pattern);
  137. finder.computeObjectImagePoints(vecImg);
  138. vector<Mat> objectPoints = finder.getObjectPoints();
  139. vector<Mat> imagePoints = finder.getImagePoints();
  140. Mat K;
  141. Mat D;
  142. vector<Mat> rvec, tvec;
  143. double rms = calibrateCamera(objectPoints, imagePoints, vecImg[0].size(), K, D, rvec, tvec);
  144. saveCameraParams(outputFilename, vecImg[0].size(), patternWidth, patternHeight, flags, K, D, rvec, tvec, rms);
  145. }