PageRenderTime 271ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/santa/OpenCV/samples/c/stereo_calib.cpp

https://github.com/siegleal/iSanta
C++ | 378 lines | 308 code | 8 blank | 62 comment | 52 complexity | 240a821215dcfc1c62aa4f29ca6d8d74 MD5 | raw file
  1. /* This is sample from the OpenCV book. The copyright notice is below */
  2. /* *************** License:**************************
  3. Oct. 3, 2008
  4. Right to use this code in any way you want without warrenty, support or any guarentee of it working.
  5. BOOK: It would be nice if you cited it:
  6. Learning OpenCV: Computer Vision with the OpenCV Library
  7. by Gary Bradski and Adrian Kaehler
  8. Published by O'Reilly Media, October 3, 2008
  9. AVAILABLE AT:
  10. http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
  11. Or: http://oreilly.com/catalog/9780596516130/
  12. ISBN-10: 0596516134 or: ISBN-13: 978-0596516130
  13. OTHER OPENCV SITES:
  14. * The source code is on sourceforge at:
  15. http://sourceforge.net/projects/opencvlibrary/
  16. * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
  17. http://opencvlibrary.sourceforge.net/
  18. * An active user group is at:
  19. http://tech.groups.yahoo.com/group/OpenCV/
  20. * The minutes of weekly OpenCV development meetings are at:
  21. http://pr.willowgarage.com/wiki/OpenCV
  22. ************************************************** */
  23. #include "cv.h"
  24. #include "cxmisc.h"
  25. #include "highgui.h"
  26. #include <vector>
  27. #include <string>
  28. #include <algorithm>
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. using namespace std;
  32. //
  33. // Given a list of chessboard images, the number of corners (nx, ny)
  34. // on the chessboards, and a flag: useCalibrated for calibrated (0) or
  35. // uncalibrated (1: use cvStereoCalibrate(), 2: compute fundamental
  36. // matrix separately) stereo. Calibrate the cameras and display the
  37. // rectified results along with the computed disparity images.
  38. //
  39. static void
  40. StereoCalib(const char* imageList, int nx, int ny, int useUncalibrated)
  41. {
  42. int displayCorners = 0;
  43. int showUndistorted = 1;
  44. bool isVerticalStereo = false;//OpenCV can handle left-right
  45. //or up-down camera arrangements
  46. const int maxScale = 1;
  47. const float squareSize = 1.f; //Set this to your actual square size
  48. FILE* f = fopen(imageList, "rt");
  49. int i, j, lr, nframes, n = nx*ny, N = 0;
  50. vector<string> imageNames[2];
  51. vector<CvPoint3D32f> objectPoints;
  52. vector<CvPoint2D32f> points[2];
  53. vector<int> npoints;
  54. vector<uchar> active[2];
  55. vector<CvPoint2D32f> temp(n);
  56. CvSize imageSize = {0,0};
  57. // ARRAY AND VECTOR STORAGE:
  58. double M1[3][3], M2[3][3], D1[5], D2[5];
  59. double R[3][3], T[3], E[3][3], F[3][3];
  60. CvMat _M1 = cvMat(3, 3, CV_64F, M1 );
  61. CvMat _M2 = cvMat(3, 3, CV_64F, M2 );
  62. CvMat _D1 = cvMat(1, 5, CV_64F, D1 );
  63. CvMat _D2 = cvMat(1, 5, CV_64F, D2 );
  64. CvMat _R = cvMat(3, 3, CV_64F, R );
  65. CvMat _T = cvMat(3, 1, CV_64F, T );
  66. CvMat _E = cvMat(3, 3, CV_64F, E );
  67. CvMat _F = cvMat(3, 3, CV_64F, F );
  68. if( displayCorners )
  69. cvNamedWindow( "corners", 1 );
  70. // READ IN THE LIST OF CHESSBOARDS:
  71. if( !f )
  72. {
  73. fprintf(stderr, "can not open file %s\n", imageList );
  74. return;
  75. }
  76. for(i=0;;i++)
  77. {
  78. char buf[1024];
  79. int count = 0, result=0;
  80. lr = i % 2;
  81. vector<CvPoint2D32f>& pts = points[lr];
  82. if( !fgets( buf, sizeof(buf)-3, f ))
  83. break;
  84. size_t len = strlen(buf);
  85. while( len > 0 && isspace(buf[len-1]))
  86. buf[--len] = '\0';
  87. if( buf[0] == '#')
  88. continue;
  89. IplImage* img = cvLoadImage( buf, 0 );
  90. if( !img )
  91. break;
  92. imageSize = cvGetSize(img);
  93. imageNames[lr].push_back(buf);
  94. //FIND CHESSBOARDS AND CORNERS THEREIN:
  95. for( int s = 1; s <= maxScale; s++ )
  96. {
  97. IplImage* timg = img;
  98. if( s > 1 )
  99. {
  100. timg = cvCreateImage(cvSize(img->width*s,img->height*s),
  101. img->depth, img->nChannels );
  102. cvResize( img, timg, CV_INTER_CUBIC );
  103. }
  104. result = cvFindChessboardCorners( timg, cvSize(nx, ny),
  105. &temp[0], &count,
  106. CV_CALIB_CB_ADAPTIVE_THRESH |
  107. CV_CALIB_CB_NORMALIZE_IMAGE);
  108. if( timg != img )
  109. cvReleaseImage( &timg );
  110. if( result || s == maxScale )
  111. for( j = 0; j < count; j++ )
  112. {
  113. temp[j].x /= s;
  114. temp[j].y /= s;
  115. }
  116. if( result )
  117. break;
  118. }
  119. if( displayCorners )
  120. {
  121. printf("%s\n", buf);
  122. IplImage* cimg = cvCreateImage( imageSize, 8, 3 );
  123. cvCvtColor( img, cimg, CV_GRAY2BGR );
  124. cvDrawChessboardCorners( cimg, cvSize(nx, ny), &temp[0],
  125. count, result );
  126. cvShowImage( "corners", cimg );
  127. cvReleaseImage( &cimg );
  128. int c = cvWaitKey(1000);
  129. if( c == 27 || c == 'q' || c == 'Q' ) //Allow ESC to quit
  130. exit(-1);
  131. }
  132. else
  133. putchar('.');
  134. N = pts.size();
  135. pts.resize(N + n, cvPoint2D32f(0,0));
  136. active[lr].push_back((uchar)result);
  137. //assert( result != 0 );
  138. if( result )
  139. {
  140. //Calibration will suffer without subpixel interpolation
  141. cvFindCornerSubPix( img, &temp[0], count,
  142. cvSize(11, 11), cvSize(-1,-1),
  143. cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,
  144. 30, 0.01) );
  145. copy( temp.begin(), temp.end(), pts.begin() + N );
  146. }
  147. cvReleaseImage( &img );
  148. }
  149. fclose(f);
  150. printf("\n");
  151. // HARVEST CHESSBOARD 3D OBJECT POINT LIST:
  152. nframes = active[0].size();//Number of good chessboads found
  153. objectPoints.resize(nframes*n);
  154. for( i = 0; i < ny; i++ )
  155. for( j = 0; j < nx; j++ )
  156. objectPoints[i*nx + j] =
  157. cvPoint3D32f(i*squareSize, j*squareSize, 0);
  158. for( i = 1; i < nframes; i++ )
  159. copy( objectPoints.begin(), objectPoints.begin() + n,
  160. objectPoints.begin() + i*n );
  161. npoints.resize(nframes,n);
  162. N = nframes*n;
  163. CvMat _objectPoints = cvMat(1, N, CV_32FC3, &objectPoints[0] );
  164. CvMat _imagePoints1 = cvMat(1, N, CV_32FC2, &points[0][0] );
  165. CvMat _imagePoints2 = cvMat(1, N, CV_32FC2, &points[1][0] );
  166. CvMat _npoints = cvMat(1, npoints.size(), CV_32S, &npoints[0] );
  167. cvSetIdentity(&_M1);
  168. cvSetIdentity(&_M2);
  169. cvZero(&_D1);
  170. cvZero(&_D2);
  171. // CALIBRATE THE STEREO CAMERAS
  172. printf("Running stereo calibration ...");
  173. fflush(stdout);
  174. cvStereoCalibrate( &_objectPoints, &_imagePoints1,
  175. &_imagePoints2, &_npoints,
  176. &_M1, &_D1, &_M2, &_D2,
  177. imageSize, &_R, &_T, &_E, &_F,
  178. cvTermCriteria(CV_TERMCRIT_ITER+
  179. CV_TERMCRIT_EPS, 100, 1e-5),
  180. CV_CALIB_FIX_ASPECT_RATIO +
  181. CV_CALIB_ZERO_TANGENT_DIST +
  182. CV_CALIB_SAME_FOCAL_LENGTH );
  183. printf(" done\n");
  184. // CALIBRATION QUALITY CHECK
  185. // because the output fundamental matrix implicitly
  186. // includes all the output information,
  187. // we can check the quality of calibration using the
  188. // epipolar geometry constraint: m2^t*F*m1=0
  189. vector<CvPoint3D32f> lines[2];
  190. points[0].resize(N);
  191. points[1].resize(N);
  192. _imagePoints1 = cvMat(1, N, CV_32FC2, &points[0][0] );
  193. _imagePoints2 = cvMat(1, N, CV_32FC2, &points[1][0] );
  194. lines[0].resize(N);
  195. lines[1].resize(N);
  196. CvMat _L1 = cvMat(1, N, CV_32FC3, &lines[0][0]);
  197. CvMat _L2 = cvMat(1, N, CV_32FC3, &lines[1][0]);
  198. //Always work in undistorted space
  199. cvUndistortPoints( &_imagePoints1, &_imagePoints1,
  200. &_M1, &_D1, 0, &_M1 );
  201. cvUndistortPoints( &_imagePoints2, &_imagePoints2,
  202. &_M2, &_D2, 0, &_M2 );
  203. cvComputeCorrespondEpilines( &_imagePoints1, 1, &_F, &_L1 );
  204. cvComputeCorrespondEpilines( &_imagePoints2, 2, &_F, &_L2 );
  205. double avgErr = 0;
  206. for( i = 0; i < N; i++ )
  207. {
  208. double err = fabs(points[0][i].x*lines[1][i].x +
  209. points[0][i].y*lines[1][i].y + lines[1][i].z)
  210. + fabs(points[1][i].x*lines[0][i].x +
  211. points[1][i].y*lines[0][i].y + lines[0][i].z);
  212. avgErr += err;
  213. }
  214. printf( "avg err = %g\n", avgErr/(nframes*n) );
  215. //COMPUTE AND DISPLAY RECTIFICATION
  216. if( showUndistorted )
  217. {
  218. CvMat* mx1 = cvCreateMat( imageSize.height,
  219. imageSize.width, CV_32F );
  220. CvMat* my1 = cvCreateMat( imageSize.height,
  221. imageSize.width, CV_32F );
  222. CvMat* mx2 = cvCreateMat( imageSize.height,
  223. imageSize.width, CV_32F );
  224. CvMat* my2 = cvCreateMat( imageSize.height,
  225. imageSize.width, CV_32F );
  226. CvMat* img1r = cvCreateMat( imageSize.height,
  227. imageSize.width, CV_8U );
  228. CvMat* img2r = cvCreateMat( imageSize.height,
  229. imageSize.width, CV_8U );
  230. CvMat* disp = cvCreateMat( imageSize.height,
  231. imageSize.width, CV_16S );
  232. CvMat* vdisp = cvCreateMat( imageSize.height,
  233. imageSize.width, CV_8U );
  234. CvMat* pair;
  235. double R1[3][3], R2[3][3], P1[3][4], P2[3][4];
  236. CvMat _R1 = cvMat(3, 3, CV_64F, R1);
  237. CvMat _R2 = cvMat(3, 3, CV_64F, R2);
  238. // IF BY CALIBRATED (BOUGUET'S METHOD)
  239. if( useUncalibrated == 0 )
  240. {
  241. CvMat _P1 = cvMat(3, 4, CV_64F, P1);
  242. CvMat _P2 = cvMat(3, 4, CV_64F, P2);
  243. cvStereoRectify( &_M1, &_M2, &_D1, &_D2, imageSize,
  244. &_R, &_T,
  245. &_R1, &_R2, &_P1, &_P2, 0,
  246. 0/*CV_CALIB_ZERO_DISPARITY*/ );
  247. isVerticalStereo = fabs(P2[1][3]) > fabs(P2[0][3]);
  248. //Precompute maps for cvRemap()
  249. cvInitUndistortRectifyMap(&_M1,&_D1,&_R1,&_P1,mx1,my1);
  250. cvInitUndistortRectifyMap(&_M2,&_D2,&_R2,&_P2,mx2,my2);
  251. }
  252. //OR ELSE HARTLEY'S METHOD
  253. else if( useUncalibrated == 1 || useUncalibrated == 2 )
  254. // use intrinsic parameters of each camera, but
  255. // compute the rectification transformation directly
  256. // from the fundamental matrix
  257. {
  258. double H1[3][3], H2[3][3], iM[3][3];
  259. CvMat _H1 = cvMat(3, 3, CV_64F, H1);
  260. CvMat _H2 = cvMat(3, 3, CV_64F, H2);
  261. CvMat _iM = cvMat(3, 3, CV_64F, iM);
  262. //Just to show you could have independently used F
  263. if( useUncalibrated == 2 )
  264. cvFindFundamentalMat( &_imagePoints1,
  265. &_imagePoints2, &_F);
  266. cvStereoRectifyUncalibrated( &_imagePoints1,
  267. &_imagePoints2, &_F,
  268. imageSize,
  269. &_H1, &_H2, 3);
  270. cvInvert(&_M1, &_iM);
  271. cvMatMul(&_H1, &_M1, &_R1);
  272. cvMatMul(&_iM, &_R1, &_R1);
  273. cvInvert(&_M2, &_iM);
  274. cvMatMul(&_H2, &_M2, &_R2);
  275. cvMatMul(&_iM, &_R2, &_R2);
  276. //Precompute map for cvRemap()
  277. cvInitUndistortRectifyMap(&_M1,&_D1,&_R1,&_M1,mx1,my1);
  278. cvInitUndistortRectifyMap(&_M2,&_D1,&_R2,&_M2,mx2,my2);
  279. }
  280. else
  281. assert(0);
  282. cvNamedWindow( "rectified", 1 );
  283. // RECTIFY THE IMAGES AND FIND DISPARITY MAPS
  284. if( !isVerticalStereo )
  285. pair = cvCreateMat( imageSize.height, imageSize.width*2,
  286. CV_8UC3 );
  287. else
  288. pair = cvCreateMat( imageSize.height*2, imageSize.width,
  289. CV_8UC3 );
  290. //Setup for finding stereo corrrespondences
  291. CvStereoBMState *BMState = cvCreateStereoBMState();
  292. assert(BMState != 0);
  293. BMState->preFilterSize=41;
  294. BMState->preFilterCap=31;
  295. BMState->SADWindowSize=41;
  296. BMState->minDisparity=-64;
  297. BMState->numberOfDisparities=128;
  298. BMState->textureThreshold=10;
  299. BMState->uniquenessRatio=15;
  300. for( i = 0; i < nframes; i++ )
  301. {
  302. IplImage* img1=cvLoadImage(imageNames[0][i].c_str(),0);
  303. IplImage* img2=cvLoadImage(imageNames[1][i].c_str(),0);
  304. if( img1 && img2 )
  305. {
  306. CvMat part;
  307. cvRemap( img1, img1r, mx1, my1 );
  308. cvRemap( img2, img2r, mx2, my2 );
  309. if( !isVerticalStereo || useUncalibrated != 0 )
  310. {
  311. // When the stereo camera is oriented vertically,
  312. // useUncalibrated==0 does not transpose the
  313. // image, so the epipolar lines in the rectified
  314. // images are vertical. Stereo correspondence
  315. // function does not support such a case.
  316. cvFindStereoCorrespondenceBM( img1r, img2r, disp,
  317. BMState);
  318. cvNormalize( disp, vdisp, 0, 256, CV_MINMAX );
  319. cvNamedWindow( "disparity" );
  320. cvShowImage( "disparity", vdisp );
  321. }
  322. if( !isVerticalStereo )
  323. {
  324. cvGetCols( pair, &part, 0, imageSize.width );
  325. cvCvtColor( img1r, &part, CV_GRAY2BGR );
  326. cvGetCols( pair, &part, imageSize.width,
  327. imageSize.width*2 );
  328. cvCvtColor( img2r, &part, CV_GRAY2BGR );
  329. for( j = 0; j < imageSize.height; j += 16 )
  330. cvLine( pair, cvPoint(0,j),
  331. cvPoint(imageSize.width*2,j),
  332. CV_RGB(0,255,0));
  333. }
  334. else
  335. {
  336. cvGetRows( pair, &part, 0, imageSize.height );
  337. cvCvtColor( img1r, &part, CV_GRAY2BGR );
  338. cvGetRows( pair, &part, imageSize.height,
  339. imageSize.height*2 );
  340. cvCvtColor( img2r, &part, CV_GRAY2BGR );
  341. for( j = 0; j < imageSize.width; j += 16 )
  342. cvLine( pair, cvPoint(j,0),
  343. cvPoint(j,imageSize.height*2),
  344. CV_RGB(0,255,0));
  345. }
  346. cvShowImage( "rectified", pair );
  347. if( cvWaitKey() == 27 )
  348. break;
  349. }
  350. cvReleaseImage( &img1 );
  351. cvReleaseImage( &img2 );
  352. }
  353. cvReleaseStereoBMState(&BMState);
  354. cvReleaseMat( &mx1 );
  355. cvReleaseMat( &my1 );
  356. cvReleaseMat( &mx2 );
  357. cvReleaseMat( &my2 );
  358. cvReleaseMat( &img1r );
  359. cvReleaseMat( &img2r );
  360. cvReleaseMat( &disp );
  361. }
  362. }
  363. int main(void)
  364. {
  365. StereoCalib("stereo_calib.txt", 9, 6, 1);
  366. return 0;
  367. }