PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/calib3d/test/test_cameracalibration.cpp

https://gitlab.com/gaurav1981/opencv
C++ | 1876 lines | 1513 code | 259 blank | 104 comment | 169 complexity | bf20b820b5007ca338bfd5f0794ff677 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // Intel License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000, Intel Corporation, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of Intel Corporation may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. #include "test_precomp.hpp"
  42. #include "opencv2/calib3d/calib3d_c.h"
  43. #include <limits>
  44. using namespace std;
  45. using namespace cv;
  46. #if 0
  47. class CV_ProjectPointsTest : public cvtest::ArrayTest
  48. {
  49. public:
  50. CV_ProjectPointsTest();
  51. protected:
  52. int read_params( CvFileStorage* fs );
  53. void fill_array( int test_case_idx, int i, int j, Mat& arr );
  54. int prepare_test_case( int test_case_idx );
  55. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  56. double get_success_error_level( int test_case_idx, int i, int j );
  57. void run_func();
  58. void prepare_to_validation( int );
  59. bool calc_jacobians;
  60. };
  61. CV_ProjectPointsTest::CV_ProjectPointsTest()
  62. : cvtest::ArrayTest( "3d-ProjectPoints", "cvProjectPoints2", "" )
  63. {
  64. test_array[INPUT].push_back(NULL); // rotation vector
  65. test_array[OUTPUT].push_back(NULL); // rotation matrix
  66. test_array[OUTPUT].push_back(NULL); // jacobian (J)
  67. test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)
  68. test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)
  69. test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)
  70. test_array[REF_OUTPUT].push_back(NULL);
  71. test_array[REF_OUTPUT].push_back(NULL);
  72. test_array[REF_OUTPUT].push_back(NULL);
  73. test_array[REF_OUTPUT].push_back(NULL);
  74. test_array[REF_OUTPUT].push_back(NULL);
  75. element_wise_relative_error = false;
  76. calc_jacobians = false;
  77. }
  78. int CV_ProjectPointsTest::read_params( CvFileStorage* fs )
  79. {
  80. int code = cvtest::ArrayTest::read_params( fs );
  81. return code;
  82. }
  83. void CV_ProjectPointsTest::get_test_array_types_and_sizes(
  84. int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  85. {
  86. RNG& rng = ts->get_rng();
  87. int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
  88. int i, code;
  89. code = cvtest::randInt(rng) % 3;
  90. types[INPUT][0] = CV_MAKETYPE(depth, 1);
  91. if( code == 0 )
  92. {
  93. sizes[INPUT][0] = cvSize(1,1);
  94. types[INPUT][0] = CV_MAKETYPE(depth, 3);
  95. }
  96. else if( code == 1 )
  97. sizes[INPUT][0] = cvSize(3,1);
  98. else
  99. sizes[INPUT][0] = cvSize(1,3);
  100. sizes[OUTPUT][0] = cvSize(3, 3);
  101. types[OUTPUT][0] = CV_MAKETYPE(depth, 1);
  102. types[OUTPUT][1] = CV_MAKETYPE(depth, 1);
  103. if( cvtest::randInt(rng) % 2 )
  104. sizes[OUTPUT][1] = cvSize(3,9);
  105. else
  106. sizes[OUTPUT][1] = cvSize(9,3);
  107. types[OUTPUT][2] = types[INPUT][0];
  108. sizes[OUTPUT][2] = sizes[INPUT][0];
  109. types[OUTPUT][3] = types[OUTPUT][1];
  110. sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);
  111. types[OUTPUT][4] = types[OUTPUT][1];
  112. sizes[OUTPUT][4] = cvSize(3,3);
  113. calc_jacobians = 1;//cvtest::randInt(rng) % 3 != 0;
  114. if( !calc_jacobians )
  115. sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);
  116. for( i = 0; i < 5; i++ )
  117. {
  118. types[REF_OUTPUT][i] = types[OUTPUT][i];
  119. sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
  120. }
  121. }
  122. double CV_ProjectPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )
  123. {
  124. return j == 4 ? 1e-2 : 1e-2;
  125. }
  126. void CV_ProjectPointsTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, CvMat* arr )
  127. {
  128. double r[3], theta0, theta1, f;
  129. CvMat _r = cvMat( arr->rows, arr->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(arr->type)), r );
  130. RNG& rng = ts->get_rng();
  131. r[0] = cvtest::randReal(rng)*CV_PI*2;
  132. r[1] = cvtest::randReal(rng)*CV_PI*2;
  133. r[2] = cvtest::randReal(rng)*CV_PI*2;
  134. theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
  135. theta1 = fmod(theta0, CV_PI*2);
  136. if( theta1 > CV_PI )
  137. theta1 = -(CV_PI*2 - theta1);
  138. f = theta1/(theta0 ? theta0 : 1);
  139. r[0] *= f;
  140. r[1] *= f;
  141. r[2] *= f;
  142. cvTsConvert( &_r, arr );
  143. }
  144. int CV_ProjectPointsTest::prepare_test_case( int test_case_idx )
  145. {
  146. int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
  147. return code;
  148. }
  149. void CV_ProjectPointsTest::run_func()
  150. {
  151. CvMat *v2m_jac = 0, *m2v_jac = 0;
  152. if( calc_jacobians )
  153. {
  154. v2m_jac = &test_mat[OUTPUT][1];
  155. m2v_jac = &test_mat[OUTPUT][3];
  156. }
  157. cvProjectPoints2( &test_mat[INPUT][0], &test_mat[OUTPUT][0], v2m_jac );
  158. cvProjectPoints2( &test_mat[OUTPUT][0], &test_mat[OUTPUT][2], m2v_jac );
  159. }
  160. void CV_ProjectPointsTest::prepare_to_validation( int /*test_case_idx*/ )
  161. {
  162. const CvMat* vec = &test_mat[INPUT][0];
  163. CvMat* m = &test_mat[REF_OUTPUT][0];
  164. CvMat* vec2 = &test_mat[REF_OUTPUT][2];
  165. CvMat* v2m_jac = 0, *m2v_jac = 0;
  166. double theta0, theta1;
  167. if( calc_jacobians )
  168. {
  169. v2m_jac = &test_mat[REF_OUTPUT][1];
  170. m2v_jac = &test_mat[REF_OUTPUT][3];
  171. }
  172. cvTsProjectPoints( vec, m, v2m_jac );
  173. cvTsProjectPoints( m, vec2, m2v_jac );
  174. cvTsCopy( vec, vec2 );
  175. theta0 = cvNorm( vec2, 0, CV_L2 );
  176. theta1 = fmod( theta0, CV_PI*2 );
  177. if( theta1 > CV_PI )
  178. theta1 = -(CV_PI*2 - theta1);
  179. cvScale( vec2, vec2, theta1/(theta0 ? theta0 : 1) );
  180. if( calc_jacobians )
  181. {
  182. //cvInvert( v2m_jac, m2v_jac, CV_SVD );
  183. if( cvNorm(&test_mat[OUTPUT][3],0,CV_C) < 1000 )
  184. {
  185. cvTsGEMM( &test_mat[OUTPUT][1], &test_mat[OUTPUT][3],
  186. 1, 0, 0, &test_mat[OUTPUT][4],
  187. v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );
  188. }
  189. else
  190. {
  191. cvTsSetIdentity( &test_mat[OUTPUT][4], cvScalarAll(1.) );
  192. cvTsCopy( &test_mat[REF_OUTPUT][2], &test_mat[OUTPUT][2] );
  193. }
  194. cvTsSetIdentity( &test_mat[REF_OUTPUT][4], cvScalarAll(1.) );
  195. }
  196. }
  197. CV_ProjectPointsTest ProjectPoints_test;
  198. #endif
  199. // --------------------------------- CV_CameraCalibrationTest --------------------------------------------
  200. class CV_CameraCalibrationTest : public cvtest::BaseTest
  201. {
  202. public:
  203. CV_CameraCalibrationTest();
  204. ~CV_CameraCalibrationTest();
  205. void clear();
  206. protected:
  207. int compare(double* val, double* refVal, int len,
  208. double eps, const char* paramName);
  209. virtual void calibrate( int imageCount, int* pointCounts,
  210. CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
  211. double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
  212. double* rotationMatrices, int flags ) = 0;
  213. virtual void project( int pointCount, CvPoint3D64f* objectPoints,
  214. double* rotationMatrix, double* translationVector,
  215. double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints ) = 0;
  216. void run(int);
  217. };
  218. CV_CameraCalibrationTest::CV_CameraCalibrationTest()
  219. {
  220. }
  221. CV_CameraCalibrationTest::~CV_CameraCalibrationTest()
  222. {
  223. clear();
  224. }
  225. void CV_CameraCalibrationTest::clear()
  226. {
  227. cvtest::BaseTest::clear();
  228. }
  229. int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len,
  230. double eps, const char* param_name )
  231. {
  232. return cvtest::cmpEps2_64f( ts, val, ref_val, len, eps, param_name );
  233. }
  234. void CV_CameraCalibrationTest::run( int start_from )
  235. {
  236. int code = cvtest::TS::OK;
  237. cv::String filepath;
  238. cv::String filename;
  239. CvSize imageSize;
  240. CvSize etalonSize;
  241. int numImages;
  242. CvPoint2D64f* imagePoints;
  243. CvPoint3D64f* objectPoints;
  244. CvPoint2D64f* reprojectPoints;
  245. double* transVects;
  246. double* rotMatrs;
  247. double* goodTransVects;
  248. double* goodRotMatrs;
  249. double cameraMatrix[3*3];
  250. double distortion[5]={0,0,0,0,0};
  251. double goodDistortion[4];
  252. int* numbers;
  253. FILE* file = 0;
  254. FILE* datafile = 0;
  255. int i,j;
  256. int currImage;
  257. int currPoint;
  258. int calibFlags;
  259. char i_dat_file[100];
  260. int numPoints;
  261. int numTests;
  262. int currTest;
  263. imagePoints = 0;
  264. objectPoints = 0;
  265. reprojectPoints = 0;
  266. numbers = 0;
  267. transVects = 0;
  268. rotMatrs = 0;
  269. goodTransVects = 0;
  270. goodRotMatrs = 0;
  271. int progress = 0;
  272. int values_read = -1;
  273. filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() );
  274. filename = cv::format("%sdatafiles.txt", filepath.c_str() );
  275. datafile = fopen( filename.c_str(), "r" );
  276. if( datafile == 0 )
  277. {
  278. ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename.c_str() );
  279. code = cvtest::TS::FAIL_MISSING_TEST_DATA;
  280. goto _exit_;
  281. }
  282. values_read = fscanf(datafile,"%d",&numTests);
  283. CV_Assert(values_read == 1);
  284. for( currTest = start_from; currTest < numTests; currTest++ )
  285. {
  286. values_read = fscanf(datafile,"%s",i_dat_file);
  287. CV_Assert(values_read == 1);
  288. filename = cv::format("%s%s", filepath.c_str(), i_dat_file);
  289. file = fopen(filename.c_str(),"r");
  290. ts->update_context( this, currTest, true );
  291. if( file == 0 )
  292. {
  293. ts->printf( cvtest::TS::LOG,
  294. "Can't open current test file: %s\n",filename.c_str());
  295. if( numTests == 1 )
  296. {
  297. code = cvtest::TS::FAIL_MISSING_TEST_DATA;
  298. goto _exit_;
  299. }
  300. continue; // if there is more than one test, just skip the test
  301. }
  302. values_read = fscanf(file,"%d %d\n",&(imageSize.width),&(imageSize.height));
  303. CV_Assert(values_read == 2);
  304. if( imageSize.width <= 0 || imageSize.height <= 0 )
  305. {
  306. ts->printf( cvtest::TS::LOG, "Image size in test file is incorrect\n" );
  307. code = cvtest::TS::FAIL_INVALID_TEST_DATA;
  308. goto _exit_;
  309. }
  310. /* Read etalon size */
  311. values_read = fscanf(file,"%d %d\n",&(etalonSize.width),&(etalonSize.height));
  312. CV_Assert(values_read == 2);
  313. if( etalonSize.width <= 0 || etalonSize.height <= 0 )
  314. {
  315. ts->printf( cvtest::TS::LOG, "Pattern size in test file is incorrect\n" );
  316. code = cvtest::TS::FAIL_INVALID_TEST_DATA;
  317. goto _exit_;
  318. }
  319. numPoints = etalonSize.width * etalonSize.height;
  320. /* Read number of images */
  321. values_read = fscanf(file,"%d\n",&numImages);
  322. CV_Assert(values_read == 1);
  323. if( numImages <=0 )
  324. {
  325. ts->printf( cvtest::TS::LOG, "Number of images in test file is incorrect\n");
  326. code = cvtest::TS::FAIL_INVALID_TEST_DATA;
  327. goto _exit_;
  328. }
  329. /* Need to allocate memory */
  330. imagePoints = (CvPoint2D64f*)cvAlloc( numPoints *
  331. numImages * sizeof(CvPoint2D64f));
  332. objectPoints = (CvPoint3D64f*)cvAlloc( numPoints *
  333. numImages * sizeof(CvPoint3D64f));
  334. reprojectPoints = (CvPoint2D64f*)cvAlloc( numPoints *
  335. numImages * sizeof(CvPoint2D64f));
  336. /* Alloc memory for numbers */
  337. numbers = (int*)cvAlloc( numImages * sizeof(int));
  338. /* Fill it by numbers of points of each image*/
  339. for( currImage = 0; currImage < numImages; currImage++ )
  340. {
  341. numbers[currImage] = etalonSize.width * etalonSize.height;
  342. }
  343. /* Allocate memory for translate vectors and rotmatrixs*/
  344. transVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double));
  345. rotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double));
  346. goodTransVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double));
  347. goodRotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double));
  348. /* Read object points */
  349. i = 0;/* shift for current point */
  350. for( currImage = 0; currImage < numImages; currImage++ )
  351. {
  352. for( currPoint = 0; currPoint < numPoints; currPoint++ )
  353. {
  354. double x,y,z;
  355. values_read = fscanf(file,"%lf %lf %lf\n",&x,&y,&z);
  356. CV_Assert(values_read == 3);
  357. (objectPoints+i)->x = x;
  358. (objectPoints+i)->y = y;
  359. (objectPoints+i)->z = z;
  360. i++;
  361. }
  362. }
  363. /* Read image points */
  364. i = 0;/* shift for current point */
  365. for( currImage = 0; currImage < numImages; currImage++ )
  366. {
  367. for( currPoint = 0; currPoint < numPoints; currPoint++ )
  368. {
  369. double x,y;
  370. values_read = fscanf(file,"%lf %lf\n",&x,&y);
  371. CV_Assert(values_read == 2);
  372. (imagePoints+i)->x = x;
  373. (imagePoints+i)->y = y;
  374. i++;
  375. }
  376. }
  377. /* Read good data computed before */
  378. /* Focal lengths */
  379. double goodFcx,goodFcy;
  380. values_read = fscanf(file,"%lf %lf",&goodFcx,&goodFcy);
  381. CV_Assert(values_read == 2);
  382. /* Principal points */
  383. double goodCx,goodCy;
  384. values_read = fscanf(file,"%lf %lf",&goodCx,&goodCy);
  385. CV_Assert(values_read == 2);
  386. /* Read distortion */
  387. values_read = fscanf(file,"%lf",goodDistortion+0); CV_Assert(values_read == 1);
  388. values_read = fscanf(file,"%lf",goodDistortion+1); CV_Assert(values_read == 1);
  389. values_read = fscanf(file,"%lf",goodDistortion+2); CV_Assert(values_read == 1);
  390. values_read = fscanf(file,"%lf",goodDistortion+3); CV_Assert(values_read == 1);
  391. /* Read good Rot matrixes */
  392. for( currImage = 0; currImage < numImages; currImage++ )
  393. {
  394. for( i = 0; i < 3; i++ )
  395. for( j = 0; j < 3; j++ )
  396. {
  397. values_read = fscanf(file, "%lf", goodRotMatrs + currImage * 9 + j * 3 + i);
  398. CV_Assert(values_read == 1);
  399. }
  400. }
  401. /* Read good Trans vectors */
  402. for( currImage = 0; currImage < numImages; currImage++ )
  403. {
  404. for( i = 0; i < 3; i++ )
  405. {
  406. values_read = fscanf(file, "%lf", goodTransVects + currImage * 3 + i);
  407. CV_Assert(values_read == 1);
  408. }
  409. }
  410. calibFlags = 0
  411. // + CV_CALIB_FIX_PRINCIPAL_POINT
  412. // + CV_CALIB_ZERO_TANGENT_DIST
  413. // + CV_CALIB_FIX_ASPECT_RATIO
  414. // + CV_CALIB_USE_INTRINSIC_GUESS
  415. + CV_CALIB_FIX_K3
  416. + CV_CALIB_FIX_K4+CV_CALIB_FIX_K5
  417. + CV_CALIB_FIX_K6
  418. ;
  419. memset( cameraMatrix, 0, 9*sizeof(cameraMatrix[0]) );
  420. cameraMatrix[0] = cameraMatrix[4] = 807.;
  421. cameraMatrix[2] = (imageSize.width - 1)*0.5;
  422. cameraMatrix[5] = (imageSize.height - 1)*0.5;
  423. cameraMatrix[8] = 1.;
  424. /* Now we can calibrate camera */
  425. calibrate( numImages,
  426. numbers,
  427. imageSize,
  428. imagePoints,
  429. objectPoints,
  430. distortion,
  431. cameraMatrix,
  432. transVects,
  433. rotMatrs,
  434. calibFlags );
  435. /* ---- Reproject points to the image ---- */
  436. for( currImage = 0; currImage < numImages; currImage++ )
  437. {
  438. int nPoints = etalonSize.width * etalonSize.height;
  439. project( nPoints,
  440. objectPoints + currImage * nPoints,
  441. rotMatrs + currImage * 9,
  442. transVects + currImage * 3,
  443. cameraMatrix,
  444. distortion,
  445. reprojectPoints + currImage * nPoints);
  446. }
  447. /* ----- Compute reprojection error ----- */
  448. i = 0;
  449. double dx,dy;
  450. double rx,ry;
  451. double meanDx,meanDy;
  452. double maxDx = 0.0;
  453. double maxDy = 0.0;
  454. meanDx = 0;
  455. meanDy = 0;
  456. for( currImage = 0; currImage < numImages; currImage++ )
  457. {
  458. for( currPoint = 0; currPoint < etalonSize.width * etalonSize.height; currPoint++ )
  459. {
  460. rx = reprojectPoints[i].x;
  461. ry = reprojectPoints[i].y;
  462. dx = rx - imagePoints[i].x;
  463. dy = ry - imagePoints[i].y;
  464. meanDx += dx;
  465. meanDy += dy;
  466. dx = fabs(dx);
  467. dy = fabs(dy);
  468. if( dx > maxDx )
  469. maxDx = dx;
  470. if( dy > maxDy )
  471. maxDy = dy;
  472. i++;
  473. }
  474. }
  475. meanDx /= numImages * etalonSize.width * etalonSize.height;
  476. meanDy /= numImages * etalonSize.width * etalonSize.height;
  477. /* ========= Compare parameters ========= */
  478. /* ----- Compare focal lengths ----- */
  479. code = compare(cameraMatrix+0,&goodFcx,1,0.1,"fx");
  480. if( code < 0 )
  481. goto _exit_;
  482. code = compare(cameraMatrix+4,&goodFcy,1,0.1,"fy");
  483. if( code < 0 )
  484. goto _exit_;
  485. /* ----- Compare principal points ----- */
  486. code = compare(cameraMatrix+2,&goodCx,1,0.1,"cx");
  487. if( code < 0 )
  488. goto _exit_;
  489. code = compare(cameraMatrix+5,&goodCy,1,0.1,"cy");
  490. if( code < 0 )
  491. goto _exit_;
  492. /* ----- Compare distortion ----- */
  493. code = compare(distortion,goodDistortion,4,0.1,"[k1,k2,p1,p2]");
  494. if( code < 0 )
  495. goto _exit_;
  496. /* ----- Compare rot matrixs ----- */
  497. code = compare(rotMatrs,goodRotMatrs, 9*numImages,0.05,"rotation matrices");
  498. if( code < 0 )
  499. goto _exit_;
  500. /* ----- Compare rot matrixs ----- */
  501. code = compare(transVects,goodTransVects, 3*numImages,0.1,"translation vectors");
  502. if( code < 0 )
  503. goto _exit_;
  504. if( maxDx > 1.0 )
  505. {
  506. ts->printf( cvtest::TS::LOG,
  507. "Error in reprojection maxDx=%f > 1.0\n",maxDx);
  508. code = cvtest::TS::FAIL_BAD_ACCURACY; goto _exit_;
  509. }
  510. if( maxDy > 1.0 )
  511. {
  512. ts->printf( cvtest::TS::LOG,
  513. "Error in reprojection maxDy=%f > 1.0\n",maxDy);
  514. code = cvtest::TS::FAIL_BAD_ACCURACY; goto _exit_;
  515. }
  516. progress = update_progress( progress, currTest, numTests, 0 );
  517. cvFree(&imagePoints);
  518. cvFree(&objectPoints);
  519. cvFree(&reprojectPoints);
  520. cvFree(&numbers);
  521. cvFree(&transVects);
  522. cvFree(&rotMatrs);
  523. cvFree(&goodTransVects);
  524. cvFree(&goodRotMatrs);
  525. fclose(file);
  526. file = 0;
  527. }
  528. _exit_:
  529. if( file )
  530. fclose(file);
  531. if( datafile )
  532. fclose(datafile);
  533. /* Free all allocated memory */
  534. cvFree(&imagePoints);
  535. cvFree(&objectPoints);
  536. cvFree(&reprojectPoints);
  537. cvFree(&numbers);
  538. cvFree(&transVects);
  539. cvFree(&rotMatrs);
  540. cvFree(&goodTransVects);
  541. cvFree(&goodRotMatrs);
  542. if( code < 0 )
  543. ts->set_failed_test_info( code );
  544. }
  545. // --------------------------------- CV_CameraCalibrationTest_C --------------------------------------------
  546. class CV_CameraCalibrationTest_C : public CV_CameraCalibrationTest
  547. {
  548. public:
  549. CV_CameraCalibrationTest_C(){}
  550. protected:
  551. virtual void calibrate( int imageCount, int* pointCounts,
  552. CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
  553. double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
  554. double* rotationMatrices, int flags );
  555. virtual void project( int pointCount, CvPoint3D64f* objectPoints,
  556. double* rotationMatrix, double* translationVector,
  557. double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints );
  558. };
  559. void CV_CameraCalibrationTest_C::calibrate( int imageCount, int* pointCounts,
  560. CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
  561. double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
  562. double* rotationMatrices, int flags )
  563. {
  564. int i, total = 0;
  565. for( i = 0; i < imageCount; i++ )
  566. total += pointCounts[i];
  567. CvMat _objectPoints = cvMat(1, total, CV_64FC3, objectPoints);
  568. CvMat _imagePoints = cvMat(1, total, CV_64FC2, imagePoints);
  569. CvMat _pointCounts = cvMat(1, imageCount, CV_32S, pointCounts);
  570. CvMat _cameraMatrix = cvMat(3, 3, CV_64F, cameraMatrix);
  571. CvMat _distCoeffs = cvMat(4, 1, CV_64F, distortionCoeffs);
  572. CvMat _rotationMatrices = cvMat(imageCount, 9, CV_64F, rotationMatrices);
  573. CvMat _translationVectors = cvMat(imageCount, 3, CV_64F, translationVectors);
  574. cvCalibrateCamera2(&_objectPoints, &_imagePoints, &_pointCounts, imageSize,
  575. &_cameraMatrix, &_distCoeffs, &_rotationMatrices, &_translationVectors,
  576. flags);
  577. }
  578. void CV_CameraCalibrationTest_C::project( int pointCount, CvPoint3D64f* objectPoints,
  579. double* rotationMatrix, double* translationVector,
  580. double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints )
  581. {
  582. CvMat _objectPoints = cvMat(1, pointCount, CV_64FC3, objectPoints);
  583. CvMat _imagePoints = cvMat(1, pointCount, CV_64FC2, imagePoints);
  584. CvMat _cameraMatrix = cvMat(3, 3, CV_64F, cameraMatrix);
  585. CvMat _distCoeffs = cvMat(4, 1, CV_64F, distortion);
  586. CvMat _rotationMatrix = cvMat(3, 3, CV_64F, rotationMatrix);
  587. CvMat _translationVector = cvMat(1, 3, CV_64F, translationVector);
  588. cvProjectPoints2(&_objectPoints, &_rotationMatrix, &_translationVector, &_cameraMatrix, &_distCoeffs, &_imagePoints);
  589. }
  590. // --------------------------------- CV_CameraCalibrationTest_CPP --------------------------------------------
  591. class CV_CameraCalibrationTest_CPP : public CV_CameraCalibrationTest
  592. {
  593. public:
  594. CV_CameraCalibrationTest_CPP(){}
  595. protected:
  596. virtual void calibrate( int imageCount, int* pointCounts,
  597. CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
  598. double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
  599. double* rotationMatrices, int flags );
  600. virtual void project( int pointCount, CvPoint3D64f* objectPoints,
  601. double* rotationMatrix, double* translationVector,
  602. double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints );
  603. };
  604. void CV_CameraCalibrationTest_CPP::calibrate( int imageCount, int* pointCounts,
  605. CvSize _imageSize, CvPoint2D64f* _imagePoints, CvPoint3D64f* _objectPoints,
  606. double* _distortionCoeffs, double* _cameraMatrix, double* translationVectors,
  607. double* rotationMatrices, int flags )
  608. {
  609. vector<vector<Point3f> > objectPoints( imageCount );
  610. vector<vector<Point2f> > imagePoints( imageCount );
  611. Size imageSize = _imageSize;
  612. Mat cameraMatrix, distCoeffs(1,4,CV_64F,Scalar::all(0));
  613. vector<Mat> rvecs, tvecs;
  614. CvPoint3D64f* op = _objectPoints;
  615. CvPoint2D64f* ip = _imagePoints;
  616. vector<vector<Point3f> >::iterator objectPointsIt = objectPoints.begin();
  617. vector<vector<Point2f> >::iterator imagePointsIt = imagePoints.begin();
  618. for( int i = 0; i < imageCount; ++objectPointsIt, ++imagePointsIt, i++ )
  619. {
  620. int num = pointCounts[i];
  621. objectPointsIt->resize( num );
  622. imagePointsIt->resize( num );
  623. vector<Point3f>::iterator oIt = objectPointsIt->begin();
  624. vector<Point2f>::iterator iIt = imagePointsIt->begin();
  625. for( int j = 0; j < num; ++oIt, ++iIt, j++, op++, ip++)
  626. {
  627. oIt->x = (float)op->x, oIt->y = (float)op->y, oIt->z = (float)op->z;
  628. iIt->x = (float)ip->x, iIt->y = (float)ip->y;
  629. }
  630. }
  631. calibrateCamera( objectPoints,
  632. imagePoints,
  633. imageSize,
  634. cameraMatrix,
  635. distCoeffs,
  636. rvecs,
  637. tvecs,
  638. flags );
  639. assert( cameraMatrix.type() == CV_64FC1 );
  640. memcpy( _cameraMatrix, cameraMatrix.data, 9*sizeof(double) );
  641. assert( cameraMatrix.type() == CV_64FC1 );
  642. memcpy( _distortionCoeffs, distCoeffs.data, 4*sizeof(double) );
  643. vector<Mat>::iterator rvecsIt = rvecs.begin();
  644. vector<Mat>::iterator tvecsIt = tvecs.begin();
  645. double *rm = rotationMatrices,
  646. *tm = translationVectors;
  647. assert( rvecsIt->type() == CV_64FC1 );
  648. assert( tvecsIt->type() == CV_64FC1 );
  649. for( int i = 0; i < imageCount; ++rvecsIt, ++tvecsIt, i++, rm+=9, tm+=3 )
  650. {
  651. Mat r9( 3, 3, CV_64FC1 );
  652. Rodrigues( *rvecsIt, r9 );
  653. memcpy( rm, r9.data, 9*sizeof(double) );
  654. memcpy( tm, tvecsIt->data, 3*sizeof(double) );
  655. }
  656. }
  657. void CV_CameraCalibrationTest_CPP::project( int pointCount, CvPoint3D64f* _objectPoints,
  658. double* rotationMatrix, double* translationVector,
  659. double* _cameraMatrix, double* distortion, CvPoint2D64f* _imagePoints )
  660. {
  661. Mat objectPoints( pointCount, 3, CV_64FC1, _objectPoints );
  662. Mat rmat( 3, 3, CV_64FC1, rotationMatrix ),
  663. rvec( 1, 3, CV_64FC1 ),
  664. tvec( 1, 3, CV_64FC1, translationVector );
  665. Mat cameraMatrix( 3, 3, CV_64FC1, _cameraMatrix );
  666. Mat distCoeffs( 1, 4, CV_64FC1, distortion );
  667. vector<Point2f> imagePoints;
  668. Rodrigues( rmat, rvec );
  669. objectPoints.convertTo( objectPoints, CV_32FC1 );
  670. projectPoints( objectPoints, rvec, tvec,
  671. cameraMatrix, distCoeffs, imagePoints );
  672. vector<Point2f>::const_iterator it = imagePoints.begin();
  673. for( int i = 0; it != imagePoints.end(); ++it, i++ )
  674. {
  675. _imagePoints[i] = cvPoint2D64f( it->x, it->y );
  676. }
  677. }
  678. //----------------------------------------- CV_CalibrationMatrixValuesTest --------------------------------
  679. class CV_CalibrationMatrixValuesTest : public cvtest::BaseTest
  680. {
  681. public:
  682. CV_CalibrationMatrixValuesTest() {}
  683. protected:
  684. void run(int);
  685. virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  686. double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
  687. Point2d& principalPoint, double& aspectRatio ) = 0;
  688. };
  689. void CV_CalibrationMatrixValuesTest::run(int)
  690. {
  691. int code = cvtest::TS::OK;
  692. const double fcMinVal = 1e-5;
  693. const double fcMaxVal = 1000;
  694. const double apertureMaxVal = 0.01;
  695. RNG rng = ts->get_rng();
  696. double fx, fy, cx, cy, nx, ny;
  697. Mat cameraMatrix( 3, 3, CV_64FC1 );
  698. cameraMatrix.setTo( Scalar(0) );
  699. fx = cameraMatrix.at<double>(0,0) = rng.uniform( fcMinVal, fcMaxVal );
  700. fy = cameraMatrix.at<double>(1,1) = rng.uniform( fcMinVal, fcMaxVal );
  701. cx = cameraMatrix.at<double>(0,2) = rng.uniform( fcMinVal, fcMaxVal );
  702. cy = cameraMatrix.at<double>(1,2) = rng.uniform( fcMinVal, fcMaxVal );
  703. cameraMatrix.at<double>(2,2) = 1;
  704. Size imageSize( 600, 400 );
  705. double apertureWidth = (double)rng * apertureMaxVal,
  706. apertureHeight = (double)rng * apertureMaxVal;
  707. double fovx, fovy, focalLength, aspectRatio,
  708. goodFovx, goodFovy, goodFocalLength, goodAspectRatio;
  709. Point2d principalPoint, goodPrincipalPoint;
  710. calibMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,
  711. fovx, fovy, focalLength, principalPoint, aspectRatio );
  712. // calculate calibration matrix values
  713. goodAspectRatio = fy / fx;
  714. if( apertureWidth != 0.0 && apertureHeight != 0.0 )
  715. {
  716. nx = imageSize.width / apertureWidth;
  717. ny = imageSize.height / apertureHeight;
  718. }
  719. else
  720. {
  721. nx = 1.0;
  722. ny = goodAspectRatio;
  723. }
  724. goodFovx = 2 * atan( imageSize.width / (2 * fx)) * 180.0 / CV_PI;
  725. goodFovy = 2 * atan( imageSize.height / (2 * fy)) * 180.0 / CV_PI;
  726. goodFocalLength = fx / nx;
  727. goodPrincipalPoint.x = cx / nx;
  728. goodPrincipalPoint.y = cy / ny;
  729. // check results
  730. if( fabs(fovx - goodFovx) > FLT_EPSILON )
  731. {
  732. ts->printf( cvtest::TS::LOG, "bad fovx (real=%f, good = %f\n", fovx, goodFovx );
  733. code = cvtest::TS::FAIL_BAD_ACCURACY;
  734. goto _exit_;
  735. }
  736. if( fabs(fovy - goodFovy) > FLT_EPSILON )
  737. {
  738. ts->printf( cvtest::TS::LOG, "bad fovy (real=%f, good = %f\n", fovy, goodFovy );
  739. code = cvtest::TS::FAIL_BAD_ACCURACY;
  740. goto _exit_;
  741. }
  742. if( fabs(focalLength - goodFocalLength) > FLT_EPSILON )
  743. {
  744. ts->printf( cvtest::TS::LOG, "bad focalLength (real=%f, good = %f\n", focalLength, goodFocalLength );
  745. code = cvtest::TS::FAIL_BAD_ACCURACY;
  746. goto _exit_;
  747. }
  748. if( fabs(aspectRatio - goodAspectRatio) > FLT_EPSILON )
  749. {
  750. ts->printf( cvtest::TS::LOG, "bad aspectRatio (real=%f, good = %f\n", aspectRatio, goodAspectRatio );
  751. code = cvtest::TS::FAIL_BAD_ACCURACY;
  752. goto _exit_;
  753. }
  754. if( norm( principalPoint - goodPrincipalPoint ) > FLT_EPSILON )
  755. {
  756. ts->printf( cvtest::TS::LOG, "bad principalPoint\n" );
  757. code = cvtest::TS::FAIL_BAD_ACCURACY;
  758. goto _exit_;
  759. }
  760. _exit_:
  761. RNG& _rng = ts->get_rng();
  762. _rng = rng;
  763. ts->set_failed_test_info( code );
  764. }
  765. //----------------------------------------- CV_CalibrationMatrixValuesTest_C --------------------------------
  766. class CV_CalibrationMatrixValuesTest_C : public CV_CalibrationMatrixValuesTest
  767. {
  768. public:
  769. CV_CalibrationMatrixValuesTest_C(){}
  770. protected:
  771. virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  772. double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
  773. Point2d& principalPoint, double& aspectRatio );
  774. };
  775. void CV_CalibrationMatrixValuesTest_C::calibMatrixValues( const Mat& _cameraMatrix, Size imageSize,
  776. double apertureWidth, double apertureHeight,
  777. double& fovx, double& fovy, double& focalLength,
  778. Point2d& principalPoint, double& aspectRatio )
  779. {
  780. CvMat cameraMatrix = _cameraMatrix;
  781. CvPoint2D64f pp;
  782. cvCalibrationMatrixValues( &cameraMatrix, imageSize, apertureWidth, apertureHeight,
  783. &fovx, &fovy, &focalLength, &pp, &aspectRatio );
  784. principalPoint.x = pp.x;
  785. principalPoint.y = pp.y;
  786. }
  787. //----------------------------------------- CV_CalibrationMatrixValuesTest_CPP --------------------------------
  788. class CV_CalibrationMatrixValuesTest_CPP : public CV_CalibrationMatrixValuesTest
  789. {
  790. public:
  791. CV_CalibrationMatrixValuesTest_CPP() {}
  792. protected:
  793. virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  794. double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
  795. Point2d& principalPoint, double& aspectRatio );
  796. };
  797. void CV_CalibrationMatrixValuesTest_CPP::calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  798. double apertureWidth, double apertureHeight,
  799. double& fovx, double& fovy, double& focalLength,
  800. Point2d& principalPoint, double& aspectRatio )
  801. {
  802. calibrationMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,
  803. fovx, fovy, focalLength, principalPoint, aspectRatio );
  804. }
  805. //----------------------------------------- CV_ProjectPointsTest --------------------------------
  806. void calcdfdx( const vector<vector<Point2f> >& leftF, const vector<vector<Point2f> >& rightF, double eps, Mat& dfdx )
  807. {
  808. const int fdim = 2;
  809. CV_Assert( !leftF.empty() && !rightF.empty() && !leftF[0].empty() && !rightF[0].empty() );
  810. CV_Assert( leftF[0].size() == rightF[0].size() );
  811. CV_Assert( fabs(eps) > std::numeric_limits<double>::epsilon() );
  812. int fcount = (int)leftF[0].size(), xdim = (int)leftF.size();
  813. dfdx.create( fcount*fdim, xdim, CV_64FC1 );
  814. vector<vector<Point2f> >::const_iterator arrLeftIt = leftF.begin();
  815. vector<vector<Point2f> >::const_iterator arrRightIt = rightF.begin();
  816. for( int xi = 0; xi < xdim; xi++, ++arrLeftIt, ++arrRightIt )
  817. {
  818. CV_Assert( (int)arrLeftIt->size() == fcount );
  819. CV_Assert( (int)arrRightIt->size() == fcount );
  820. vector<Point2f>::const_iterator lIt = arrLeftIt->begin();
  821. vector<Point2f>::const_iterator rIt = arrRightIt->begin();
  822. for( int fi = 0; fi < dfdx.rows; fi+=fdim, ++lIt, ++rIt )
  823. {
  824. dfdx.at<double>(fi, xi ) = 0.5 * ((double)(rIt->x - lIt->x)) / eps;
  825. dfdx.at<double>(fi+1, xi ) = 0.5 * ((double)(rIt->y - lIt->y)) / eps;
  826. }
  827. }
  828. }
  829. class CV_ProjectPointsTest : public cvtest::BaseTest
  830. {
  831. public:
  832. CV_ProjectPointsTest() {}
  833. protected:
  834. void run(int);
  835. virtual void project( const Mat& objectPoints,
  836. const Mat& rvec, const Mat& tvec,
  837. const Mat& cameraMatrix,
  838. const Mat& distCoeffs,
  839. vector<Point2f>& imagePoints,
  840. Mat& dpdrot, Mat& dpdt, Mat& dpdf,
  841. Mat& dpdc, Mat& dpddist,
  842. double aspectRatio=0 ) = 0;
  843. };
  844. void CV_ProjectPointsTest::run(int)
  845. {
  846. //typedef float matType;
  847. int code = cvtest::TS::OK;
  848. const int pointCount = 100;
  849. const float zMinVal = 10.0f, zMaxVal = 100.0f,
  850. rMinVal = -0.3f, rMaxVal = 0.3f,
  851. tMinVal = -2.0f, tMaxVal = 2.0f;
  852. const float imgPointErr = 1e-3f,
  853. dEps = 1e-3f;
  854. double err;
  855. Size imgSize( 600, 800 );
  856. Mat_<float> objPoints( pointCount, 3), rvec( 1, 3), rmat, tvec( 1, 3 ), cameraMatrix( 3, 3 ), distCoeffs( 1, 4 ),
  857. leftRvec, rightRvec, leftTvec, rightTvec, leftCameraMatrix, rightCameraMatrix, leftDistCoeffs, rightDistCoeffs;
  858. RNG rng = ts->get_rng();
  859. // generate data
  860. cameraMatrix << 300.f, 0.f, imgSize.width/2.f,
  861. 0.f, 300.f, imgSize.height/2.f,
  862. 0.f, 0.f, 1.f;
  863. distCoeffs << 0.1, 0.01, 0.001, 0.001;
  864. rvec(0,0) = rng.uniform( rMinVal, rMaxVal );
  865. rvec(0,1) = rng.uniform( rMinVal, rMaxVal );
  866. rvec(0,2) = rng.uniform( rMinVal, rMaxVal );
  867. Rodrigues( rvec, rmat );
  868. tvec(0,0) = rng.uniform( tMinVal, tMaxVal );
  869. tvec(0,1) = rng.uniform( tMinVal, tMaxVal );
  870. tvec(0,2) = rng.uniform( tMinVal, tMaxVal );
  871. for( int y = 0; y < objPoints.rows; y++ )
  872. {
  873. Mat point(1, 3, CV_32FC1, objPoints.ptr(y) );
  874. float z = rng.uniform( zMinVal, zMaxVal );
  875. point.at<float>(0,2) = z;
  876. point.at<float>(0,0) = (rng.uniform(2.f,(float)(imgSize.width-2)) - cameraMatrix(0,2)) / cameraMatrix(0,0) * z;
  877. point.at<float>(0,1) = (rng.uniform(2.f,(float)(imgSize.height-2)) - cameraMatrix(1,2)) / cameraMatrix(1,1) * z;
  878. point = (point - tvec) * rmat;
  879. }
  880. vector<Point2f> imgPoints;
  881. vector<vector<Point2f> > leftImgPoints;
  882. vector<vector<Point2f> > rightImgPoints;
  883. Mat dpdrot, dpdt, dpdf, dpdc, dpddist,
  884. valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist;
  885. project( objPoints, rvec, tvec, cameraMatrix, distCoeffs,
  886. imgPoints, dpdrot, dpdt, dpdf, dpdc, dpddist, 0 );
  887. // calculate and check image points
  888. assert( (int)imgPoints.size() == pointCount );
  889. vector<Point2f>::const_iterator it = imgPoints.begin();
  890. for( int i = 0; i < pointCount; i++, ++it )
  891. {
  892. Point3d p( objPoints(i,0), objPoints(i,1), objPoints(i,2) );
  893. double z = p.x*rmat(2,0) + p.y*rmat(2,1) + p.z*rmat(2,2) + tvec(0,2),
  894. x = (p.x*rmat(0,0) + p.y*rmat(0,1) + p.z*rmat(0,2) + tvec(0,0)) / z,
  895. y = (p.x*rmat(1,0) + p.y*rmat(1,1) + p.z*rmat(1,2) + tvec(0,1)) / z,
  896. r2 = x*x + y*y,
  897. r4 = r2*r2;
  898. Point2f validImgPoint;
  899. double a1 = 2*x*y,
  900. a2 = r2 + 2*x*x,
  901. a3 = r2 + 2*y*y,
  902. cdist = 1+distCoeffs(0,0)*r2+distCoeffs(0,1)*r4;
  903. validImgPoint.x = static_cast<float>((double)cameraMatrix(0,0)*(x*cdist + (double)distCoeffs(0,2)*a1 + (double)distCoeffs(0,3)*a2)
  904. + (double)cameraMatrix(0,2));
  905. validImgPoint.y = static_cast<float>((double)cameraMatrix(1,1)*(y*cdist + (double)distCoeffs(0,2)*a3 + distCoeffs(0,3)*a1)
  906. + (double)cameraMatrix(1,2));
  907. if( fabs(it->x - validImgPoint.x) > imgPointErr ||
  908. fabs(it->y - validImgPoint.y) > imgPointErr )
  909. {
  910. ts->printf( cvtest::TS::LOG, "bad image point\n" );
  911. code = cvtest::TS::FAIL_BAD_ACCURACY;
  912. goto _exit_;
  913. }
  914. }
  915. // check derivatives
  916. // 1. rotation
  917. leftImgPoints.resize(3);
  918. rightImgPoints.resize(3);
  919. for( int i = 0; i < 3; i++ )
  920. {
  921. rvec.copyTo( leftRvec ); leftRvec(0,i) -= dEps;
  922. project( objPoints, leftRvec, tvec, cameraMatrix, distCoeffs,
  923. leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  924. rvec.copyTo( rightRvec ); rightRvec(0,i) += dEps;
  925. project( objPoints, rightRvec, tvec, cameraMatrix, distCoeffs,
  926. rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  927. }
  928. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdrot );
  929. err = norm( dpdrot, valDpdrot, NORM_INF );
  930. if( err > 3 )
  931. {
  932. ts->printf( cvtest::TS::LOG, "bad dpdrot: too big difference = %g\n", err );
  933. code = cvtest::TS::FAIL_BAD_ACCURACY;
  934. }
  935. // 2. translation
  936. for( int i = 0; i < 3; i++ )
  937. {
  938. tvec.copyTo( leftTvec ); leftTvec(0,i) -= dEps;
  939. project( objPoints, rvec, leftTvec, cameraMatrix, distCoeffs,
  940. leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  941. tvec.copyTo( rightTvec ); rightTvec(0,i) += dEps;
  942. project( objPoints, rvec, rightTvec, cameraMatrix, distCoeffs,
  943. rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  944. }
  945. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdt );
  946. if( norm( dpdt, valDpdt, NORM_INF ) > 0.2 )
  947. {
  948. ts->printf( cvtest::TS::LOG, "bad dpdtvec\n" );
  949. code = cvtest::TS::FAIL_BAD_ACCURACY;
  950. }
  951. // 3. camera matrix
  952. // 3.1. focus
  953. leftImgPoints.resize(2);
  954. rightImgPoints.resize(2);
  955. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,0) -= dEps;
  956. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  957. leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  958. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,1) -= dEps;
  959. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  960. leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  961. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,0) += dEps;
  962. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  963. rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  964. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,1) += dEps;
  965. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  966. rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  967. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdf );
  968. if ( norm( dpdf, valDpdf ) > 0.2 )
  969. {
  970. ts->printf( cvtest::TS::LOG, "bad dpdf\n" );
  971. code = cvtest::TS::FAIL_BAD_ACCURACY;
  972. }
  973. // 3.2. principal point
  974. leftImgPoints.resize(2);
  975. rightImgPoints.resize(2);
  976. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,2) -= dEps;
  977. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  978. leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  979. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,2) -= dEps;
  980. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  981. leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  982. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,2) += dEps;
  983. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  984. rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  985. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,2) += dEps;
  986. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  987. rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  988. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdc );
  989. if ( norm( dpdc, valDpdc ) > 0.2 )
  990. {
  991. ts->printf( cvtest::TS::LOG, "bad dpdc\n" );
  992. code = cvtest::TS::FAIL_BAD_ACCURACY;
  993. }
  994. // 4. distortion
  995. leftImgPoints.resize(distCoeffs.cols);
  996. rightImgPoints.resize(distCoeffs.cols);
  997. for( int i = 0; i < distCoeffs.cols; i++ )
  998. {
  999. distCoeffs.copyTo( leftDistCoeffs ); leftDistCoeffs(0,i) -= dEps;
  1000. project( objPoints, rvec, tvec, cameraMatrix, leftDistCoeffs,
  1001. leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  1002. distCoeffs.copyTo( rightDistCoeffs ); rightDistCoeffs(0,i) += dEps;
  1003. project( objPoints, rvec, tvec, cameraMatrix, rightDistCoeffs,
  1004. rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  1005. }
  1006. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpddist );
  1007. if( norm( dpddist, valDpddist ) > 0.3 )
  1008. {
  1009. ts->printf( cvtest::TS::LOG, "bad dpddist\n" );
  1010. code = cvtest::TS::FAIL_BAD_ACCURACY;
  1011. }
  1012. _exit_:
  1013. RNG& _rng = ts->get_rng();
  1014. _rng = rng;
  1015. ts->set_failed_test_info( code );
  1016. }
  1017. //----------------------------------------- CV_ProjectPointsTest_C --------------------------------
  1018. class CV_ProjectPointsTest_C : public CV_ProjectPointsTest
  1019. {
  1020. public:
  1021. CV_ProjectPointsTest_C() {}
  1022. protected:
  1023. virtual void project( const Mat& objectPoints,
  1024. const Mat& rvec, const Mat& tvec,
  1025. const Mat& cameraMatrix,
  1026. const Mat& distCoeffs,
  1027. vector<Point2f>& imagePoints,
  1028. Mat& dpdrot, Mat& dpdt, Mat& dpdf,
  1029. Mat& dpdc, Mat& dpddist,
  1030. double aspectRatio=0 );
  1031. };
  1032. void CV_ProjectPointsTest_C::project( const Mat& opoints, const Mat& rvec, const Mat& tvec,
  1033. const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& ipoints,
  1034. Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)
  1035. {
  1036. int npoints = opoints.cols*opoints.rows*opoints.channels()/3;
  1037. ipoints.resize(npoints);
  1038. dpdrot.create(npoints*2, 3, CV_64F);
  1039. dpdt.create(npoints*2, 3, CV_64F);
  1040. dpdf.create(npoints*2, 2, CV_64F);
  1041. dpdc.create(npoints*2, 2, CV_64F);
  1042. dpddist.create(npoints*2, distCoeffs.rows + distCoeffs.cols - 1, CV_64F);
  1043. CvMat _objectPoints = opoints, _imagePoints = Mat(ipoints);
  1044. CvMat _rvec = rvec, _tvec = tvec, _cameraMatrix = cameraMatrix, _distCoeffs = distCoeffs;
  1045. CvMat _dpdrot = dpdrot, _dpdt = dpdt, _dpdf = dpdf, _dpdc = dpdc, _dpddist = dpddist;
  1046. cvProjectPoints2( &_objectPoints, &_rvec, &_tvec, &_cameraMatrix, &_distCoeffs,
  1047. &_imagePoints, &_dpdrot, &_dpdt, &_dpdf, &_dpdc, &_dpddist, aspectRatio );
  1048. }
  1049. //----------------------------------------- CV_ProjectPointsTest_CPP --------------------------------
  1050. class CV_ProjectPointsTest_CPP : public CV_ProjectPointsTest
  1051. {
  1052. public:
  1053. CV_ProjectPointsTest_CPP() {}
  1054. protected:
  1055. virtual void project( const Mat& objectPoints,
  1056. const Mat& rvec, const Mat& tvec,
  1057. const Mat& cameraMatrix,
  1058. const Mat& distCoeffs,
  1059. vector<Point2f>& imagePoints,
  1060. Mat& dpdrot, Mat& dpdt, Mat& dpdf,
  1061. Mat& dpdc, Mat& dpddist,
  1062. double aspectRatio=0 );
  1063. };
  1064. void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec, const Mat& tvec,
  1065. const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& imagePoints,
  1066. Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)
  1067. {
  1068. Mat J;
  1069. projectPoints( objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, J, aspectRatio);
  1070. J.colRange(0, 3).copyTo(dpdrot);
  1071. J.colRange(3, 6).copyTo(dpdt);
  1072. J.colRange(6, 8).copyTo(dpdf);
  1073. J.colRange(8, 10).copyTo(dpdc);
  1074. J.colRange(10, J.cols).copyTo(dpddist);
  1075. }
  1076. ///////////////////////////////// Stereo Calibration /////////////////////////////////////
  1077. class CV_StereoCalibrationTest : public cvtest::BaseTest
  1078. {
  1079. public:
  1080. CV_StereoCalibrationTest();
  1081. ~CV_StereoCalibrationTest();
  1082. void clear();
  1083. protected:
  1084. bool checkPandROI( int test_case_idx,
  1085. const Mat& M, const Mat& D, const Mat& R,
  1086. const Mat& P, Size imgsize, Rect roi );
  1087. // covers of tested functions
  1088. virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
  1089. const vector<vector<Point2f> >& imagePoints1,
  1090. const vector<vector<Point2f> >& imagePoints2,
  1091. Mat& cameraMatrix1, Mat& distCoeffs1,
  1092. Mat& cameraMatrix2, Mat& distCoeffs2,
  1093. Size imageSize, Mat& R, Mat& T,
  1094. Mat& E, Mat& F, TermCriteria criteria, int flags ) = 0;
  1095. virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
  1096. const Mat& cameraMatrix2, const Mat& distCoeffs2,
  1097. Size imageSize, const Mat& R, const Mat& T,
  1098. Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
  1099. double alpha, Size newImageSize,
  1100. Rect* validPixROI1, Rect* validPixROI2, int flags ) = 0;
  1101. virtual bool rectifyUncalibrated( const Mat& points1,
  1102. const Mat& points2, const Mat& F, Size imgSize,
  1103. Mat& H1, Mat& H2, double threshold=5 ) = 0;
  1104. virtual void triangulate( const Mat& P1, const Mat& P2,
  1105. const Mat &points1, const Mat &points2,
  1106. Mat &points4D ) = 0;
  1107. virtual void correct( const Mat& F,
  1108. const Mat &points1, const Mat &points2,
  1109. Mat &newPoints1, Mat &newPoints2 ) = 0;
  1110. void run(int);
  1111. };
  1112. CV_StereoCalibrationTest::CV_StereoCalibrationTest()
  1113. {
  1114. }
  1115. CV_StereoCalibrationTest::~CV_StereoCalibrationTest()
  1116. {
  1117. clear();
  1118. }
  1119. void CV_StereoCalibrationTest::clear()
  1120. {
  1121. cvtest::BaseTest::clear();
  1122. }
  1123. bool CV_StereoCalibrationTest::checkPandROI( int test_case_idx, const Mat& M, const Mat& D, const Mat& R,
  1124. const Mat& P, Size imgsize, Rect roi )
  1125. {
  1126. const double eps = 0.05;
  1127. const int N = 21;
  1128. int x, y, k;
  1129. vector<Point2f> pts, upts;
  1130. // step 1. check that all the original points belong to the destination image
  1131. for( y = 0; y < N; y++ )
  1132. for( x = 0; x < N; x++ )
  1133. pts.push_back(Point2f((float)x*imgsize.width/(N-1), (float)y*imgsize.height/(N-1)));
  1134. undistortPoints(Mat(pts), upts, M, D, R, P );
  1135. for( k = 0; k < N*N; k++ )
  1136. if( upts[k].x < -imgsize.width*eps || upts[k].x > imgsize.width*(1+eps) ||
  1137. upts[k].y < -imgsize.height*eps || upts[k].y > imgsize.height*(1+eps) )
  1138. {
  1139. ts->printf(cvtest::TS::LOG, "Test #%d. The point (%g, %g) was mapped to (%g, %g) which is out of image\n",
  1140. test_case_idx, pts[k].x, pts[k].y, upts[k].x, upts[k].y);
  1141. return false;
  1142. }
  1143. // step 2. check that all the points inside ROI belong to the original source image
  1144. Mat temp(imgsize, CV_8U), utemp, map1, map2;
  1145. temp = Scalar::all(1);
  1146. initUndistortRectifyMap(M, D, R, P, imgsize, CV_16SC2, map1, map2);
  1147. remap(temp, utemp, map1, map2, INTER_LINEAR);
  1148. if(roi.x < 0 || roi.y < 0 || roi.x + roi.width > imgsize.width || roi.y + roi.height > imgsize.height)
  1149. {
  1150. ts->printf(cvtest::TS::LOG, "Test #%d. The ROI=(%d, %d, %d, %d) is outside of the imge rectangle\n",
  1151. test_case_idx, roi.x, roi.y, roi.width, roi.height);
  1152. return false;
  1153. }
  1154. double s = sum(utemp(roi))[0];
  1155. if( s > roi.area() || roi.area() - s > roi.area()*(1-eps) )
  1156. {
  1157. ts->printf(cvtest::TS::LOG, "Test #%d. Th…

Large files files are truncated, but you can click here to view the full file