1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
42 #include "test_precomp.hpp"
47 class CV_ProjectPointsTest : public cvtest::ArrayTest
50 CV_ProjectPointsTest();
53 int read_params( CvFileStorage* fs );
54 void fill_array( int test_case_idx, int i, int j, Mat& arr );
55 int prepare_test_case( int test_case_idx );
56 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
57 double get_success_error_level( int test_case_idx, int i, int j );
59 void prepare_to_validation( int );
65 CV_ProjectPointsTest::CV_ProjectPointsTest()
66 : cvtest::ArrayTest( "3d-ProjectPoints", "cvProjectPoints2", "" )
68 test_array[INPUT].push_back(NULL); // rotation vector
69 test_array[OUTPUT].push_back(NULL); // rotation matrix
70 test_array[OUTPUT].push_back(NULL); // jacobian (J)
71 test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)
72 test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)
73 test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)
74 test_array[REF_OUTPUT].push_back(NULL);
75 test_array[REF_OUTPUT].push_back(NULL);
76 test_array[REF_OUTPUT].push_back(NULL);
77 test_array[REF_OUTPUT].push_back(NULL);
78 test_array[REF_OUTPUT].push_back(NULL);
80 element_wise_relative_error = false;
81 calc_jacobians = false;
85 int CV_ProjectPointsTest::read_params( CvFileStorage* fs )
87 int code = cvtest::ArrayTest::read_params( fs );
92 void CV_ProjectPointsTest::get_test_array_types_and_sizes(
93 int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )
95 RNG& rng = ts->get_rng();
96 int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
99 code = cvtest::randInt(rng) % 3;
100 types[INPUT][0] = CV_MAKETYPE(depth, 1);
104 sizes[INPUT][0] = cvSize(1,1);
105 types[INPUT][0] = CV_MAKETYPE(depth, 3);
108 sizes[INPUT][0] = cvSize(3,1);
110 sizes[INPUT][0] = cvSize(1,3);
112 sizes[OUTPUT][0] = cvSize(3, 3);
113 types[OUTPUT][0] = CV_MAKETYPE(depth, 1);
115 types[OUTPUT][1] = CV_MAKETYPE(depth, 1);
117 if( cvtest::randInt(rng) % 2 )
118 sizes[OUTPUT][1] = cvSize(3,9);
120 sizes[OUTPUT][1] = cvSize(9,3);
122 types[OUTPUT][2] = types[INPUT][0];
123 sizes[OUTPUT][2] = sizes[INPUT][0];
125 types[OUTPUT][3] = types[OUTPUT][1];
126 sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);
128 types[OUTPUT][4] = types[OUTPUT][1];
129 sizes[OUTPUT][4] = cvSize(3,3);
131 calc_jacobians = 1;//cvtest::randInt(rng) % 3 != 0;
132 if( !calc_jacobians )
133 sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);
135 for( i = 0; i < 5; i++ )
137 types[REF_OUTPUT][i] = types[OUTPUT][i];
138 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
143 double CV_ProjectPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )
145 return j == 4 ? 1e-2 : 1e-2;
149 void CV_ProjectPointsTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, CvMat* arr )
151 double r[3], theta0, theta1, f;
152 CvMat _r = cvMat( arr->rows, arr->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(arr->type)), r );
153 RNG& rng = ts->get_rng();
155 r[0] = cvtest::randReal(rng)*CV_PI*2;
156 r[1] = cvtest::randReal(rng)*CV_PI*2;
157 r[2] = cvtest::randReal(rng)*CV_PI*2;
159 theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
160 theta1 = fmod(theta0, CV_PI*2);
163 theta1 = -(CV_PI*2 - theta1);
165 f = theta1/(theta0 ? theta0 : 1);
170 cvTsConvert( &_r, arr );
174 int CV_ProjectPointsTest::prepare_test_case( int test_case_idx )
176 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
181 void CV_ProjectPointsTest::run_func()
183 CvMat *v2m_jac = 0, *m2v_jac = 0;
186 v2m_jac = &test_mat[OUTPUT][1];
187 m2v_jac = &test_mat[OUTPUT][3];
190 cvProjectPoints2( &test_mat[INPUT][0], &test_mat[OUTPUT][0], v2m_jac );
191 cvProjectPoints2( &test_mat[OUTPUT][0], &test_mat[OUTPUT][2], m2v_jac );
195 void CV_ProjectPointsTest::prepare_to_validation( int /*test_case_idx*/ )
197 const CvMat* vec = &test_mat[INPUT][0];
198 CvMat* m = &test_mat[REF_OUTPUT][0];
199 CvMat* vec2 = &test_mat[REF_OUTPUT][2];
200 CvMat* v2m_jac = 0, *m2v_jac = 0;
201 double theta0, theta1;
205 v2m_jac = &test_mat[REF_OUTPUT][1];
206 m2v_jac = &test_mat[REF_OUTPUT][3];
210 cvTsProjectPoints( vec, m, v2m_jac );
211 cvTsProjectPoints( m, vec2, m2v_jac );
212 cvTsCopy( vec, vec2 );
214 theta0 = cvNorm( vec2, 0, CV_L2 );
215 theta1 = fmod( theta0, CV_PI*2 );
218 theta1 = -(CV_PI*2 - theta1);
219 cvScale( vec2, vec2, theta1/(theta0 ? theta0 : 1) );
223 //cvInvert( v2m_jac, m2v_jac, CV_SVD );
224 if( cvNorm(&test_mat[OUTPUT][3],0,CV_C) < 1000 )
226 cvTsGEMM( &test_mat[OUTPUT][1], &test_mat[OUTPUT][3],
227 1, 0, 0, &test_mat[OUTPUT][4],
228 v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );
232 cvTsSetIdentity( &test_mat[OUTPUT][4], cvScalarAll(1.) );
233 cvTsCopy( &test_mat[REF_OUTPUT][2], &test_mat[OUTPUT][2] );
235 cvTsSetIdentity( &test_mat[REF_OUTPUT][4], cvScalarAll(1.) );
240 CV_ProjectPointsTest ProjectPoints_test;
246 // --------------------------------- CV_CameraCalibrationTest --------------------------------------------
248 class CV_CameraCalibrationTest : public cvtest::BaseTest
251 CV_CameraCalibrationTest();
252 ~CV_CameraCalibrationTest();
255 int compare(double* val, double* refVal, int len,
256 double eps, const char* paramName);
257 virtual void calibrate( int imageCount, int* pointCounts,
258 CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
259 double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
260 double* rotationMatrices, int flags ) = 0;
261 virtual void project( int pointCount, CvPoint3D64f* objectPoints,
262 double* rotationMatrix, double* translationVector,
263 double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints ) = 0;
268 CV_CameraCalibrationTest::CV_CameraCalibrationTest()
272 CV_CameraCalibrationTest::~CV_CameraCalibrationTest()
277 void CV_CameraCalibrationTest::clear()
279 cvtest::BaseTest::clear();
282 int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len,
283 double eps, const char* param_name )
285 return cvtest::cmpEps2_64f( ts, val, ref_val, len, eps, param_name );
288 void CV_CameraCalibrationTest::run( int start_from )
290 int code = cvtest::TS::OK;
298 CvPoint2D64f* imagePoints;
299 CvPoint3D64f* objectPoints;
300 CvPoint2D64f* reprojectPoints;
305 double* goodTransVects;
306 double* goodRotMatrs;
308 double cameraMatrix[3*3];
309 double distortion[5]={0,0,0,0,0};
311 double goodDistortion[4];
321 char i_dat_file[100];
336 int values_read = -1;
338 sprintf( filepath, "%scameracalibration/", ts->get_data_path().c_str() );
339 sprintf( filename, "%sdatafiles.txt", filepath );
340 datafile = fopen( filename, "r" );
343 ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename );
344 code = cvtest::TS::FAIL_MISSING_TEST_DATA;
348 values_read = fscanf(datafile,"%d",&numTests);
349 CV_Assert(values_read == 1);
351 for( currTest = start_from; currTest < numTests; currTest++ )
353 values_read = fscanf(datafile,"%s",i_dat_file);
354 CV_Assert(values_read == 1);
355 sprintf(filename, "%s%s", filepath, i_dat_file);
356 file = fopen(filename,"r");
358 ts->update_context( this, currTest, true );
362 ts->printf( cvtest::TS::LOG,
363 "Can't open current test file: %s\n",filename);
366 code = cvtest::TS::FAIL_MISSING_TEST_DATA;
369 continue; // if there is more than one test, just skip the test
372 values_read = fscanf(file,"%d %d\n",&(imageSize.width),&(imageSize.height));
373 CV_Assert(values_read == 2);
374 if( imageSize.width <= 0 || imageSize.height <= 0 )
376 ts->printf( cvtest::TS::LOG, "Image size in test file is incorrect\n" );
377 code = cvtest::TS::FAIL_INVALID_TEST_DATA;
381 /* Read etalon size */
382 values_read = fscanf(file,"%d %d\n",&(etalonSize.width),&(etalonSize.height));
383 CV_Assert(values_read == 2);
384 if( etalonSize.width <= 0 || etalonSize.height <= 0 )
386 ts->printf( cvtest::TS::LOG, "Pattern size in test file is incorrect\n" );
387 code = cvtest::TS::FAIL_INVALID_TEST_DATA;
391 numPoints = etalonSize.width * etalonSize.height;
393 /* Read number of images */
394 values_read = fscanf(file,"%d\n",&numImages);
395 CV_Assert(values_read == 1);
398 ts->printf( cvtest::TS::LOG, "Number of images in test file is incorrect\n");
399 code = cvtest::TS::FAIL_INVALID_TEST_DATA;
403 /* Need to allocate memory */
404 imagePoints = (CvPoint2D64f*)cvAlloc( numPoints *
405 numImages * sizeof(CvPoint2D64f));
407 objectPoints = (CvPoint3D64f*)cvAlloc( numPoints *
408 numImages * sizeof(CvPoint3D64f));
410 reprojectPoints = (CvPoint2D64f*)cvAlloc( numPoints *
411 numImages * sizeof(CvPoint2D64f));
413 /* Alloc memory for numbers */
414 numbers = (int*)cvAlloc( numImages * sizeof(int));
416 /* Fill it by numbers of points of each image*/
417 for( currImage = 0; currImage < numImages; currImage++ )
419 numbers[currImage] = etalonSize.width * etalonSize.height;
422 /* Allocate memory for translate vectors and rotmatrixs*/
423 transVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double));
424 rotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double));
426 goodTransVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double));
427 goodRotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double));
429 /* Read object points */
430 i = 0;/* shift for current point */
431 for( currImage = 0; currImage < numImages; currImage++ )
433 for( currPoint = 0; currPoint < numPoints; currPoint++ )
436 values_read = fscanf(file,"%lf %lf %lf\n",&x,&y,&z);
437 CV_Assert(values_read == 3);
439 (objectPoints+i)->x = x;
440 (objectPoints+i)->y = y;
441 (objectPoints+i)->z = z;
446 /* Read image points */
447 i = 0;/* shift for current point */
448 for( currImage = 0; currImage < numImages; currImage++ )
450 for( currPoint = 0; currPoint < numPoints; currPoint++ )
453 values_read = fscanf(file,"%lf %lf\n",&x,&y);
454 CV_Assert(values_read == 2);
456 (imagePoints+i)->x = x;
457 (imagePoints+i)->y = y;
462 /* Read good data computed before */
465 double goodFcx,goodFcy;
466 values_read = fscanf(file,"%lf %lf",&goodFcx,&goodFcy);
467 CV_Assert(values_read == 2);
469 /* Principal points */
470 double goodCx,goodCy;
471 values_read = fscanf(file,"%lf %lf",&goodCx,&goodCy);
472 CV_Assert(values_read == 2);
474 /* Read distortion */
476 values_read = fscanf(file,"%lf",goodDistortion+0); CV_Assert(values_read == 1);
477 values_read = fscanf(file,"%lf",goodDistortion+1); CV_Assert(values_read == 1);
478 values_read = fscanf(file,"%lf",goodDistortion+2); CV_Assert(values_read == 1);
479 values_read = fscanf(file,"%lf",goodDistortion+3); CV_Assert(values_read == 1);
481 /* Read good Rot matrixes */
482 for( currImage = 0; currImage < numImages; currImage++ )
484 for( i = 0; i < 3; i++ )
485 for( j = 0; j < 3; j++ )
487 values_read = fscanf(file, "%lf", goodRotMatrs + currImage * 9 + j * 3 + i);
488 CV_Assert(values_read == 1);
492 /* Read good Trans vectors */
493 for( currImage = 0; currImage < numImages; currImage++ )
495 for( i = 0; i < 3; i++ )
497 values_read = fscanf(file, "%lf", goodTransVects + currImage * 3 + i);
498 CV_Assert(values_read == 1);
503 // + CV_CALIB_FIX_PRINCIPAL_POINT
504 // + CV_CALIB_ZERO_TANGENT_DIST
505 // + CV_CALIB_FIX_ASPECT_RATIO
506 // + CV_CALIB_USE_INTRINSIC_GUESS
508 + CV_CALIB_FIX_K4+CV_CALIB_FIX_K5
511 memset( cameraMatrix, 0, 9*sizeof(cameraMatrix[0]) );
512 cameraMatrix[0] = cameraMatrix[4] = 807.;
513 cameraMatrix[2] = (imageSize.width - 1)*0.5;
514 cameraMatrix[5] = (imageSize.height - 1)*0.5;
515 cameraMatrix[8] = 1.;
517 /* Now we can calibrate camera */
518 calibrate( numImages,
529 /* ---- Reproject points to the image ---- */
530 for( currImage = 0; currImage < numImages; currImage++ )
532 int nPoints = etalonSize.width * etalonSize.height;
534 objectPoints + currImage * nPoints,
535 rotMatrs + currImage * 9,
536 transVects + currImage * 3,
539 reprojectPoints + currImage * nPoints);
542 /* ----- Compute reprojection error ----- */
546 double meanDx,meanDy;
552 for( currImage = 0; currImage < numImages; currImage++ )
554 for( currPoint = 0; currPoint < etalonSize.width * etalonSize.height; currPoint++ )
556 rx = reprojectPoints[i].x;
557 ry = reprojectPoints[i].y;
558 dx = rx - imagePoints[i].x;
559 dy = ry - imagePoints[i].y;
576 meanDx /= numImages * etalonSize.width * etalonSize.height;
577 meanDy /= numImages * etalonSize.width * etalonSize.height;
579 /* ========= Compare parameters ========= */
581 /* ----- Compare focal lengths ----- */
582 code = compare(cameraMatrix+0,&goodFcx,1,0.1,"fx");
586 code = compare(cameraMatrix+4,&goodFcy,1,0.1,"fy");
590 /* ----- Compare principal points ----- */
591 code = compare(cameraMatrix+2,&goodCx,1,0.1,"cx");
595 code = compare(cameraMatrix+5,&goodCy,1,0.1,"cy");
599 /* ----- Compare distortion ----- */
600 code = compare(distortion,goodDistortion,4,0.1,"[k1,k2,p1,p2]");
604 /* ----- Compare rot matrixs ----- */
605 code = compare(rotMatrs,goodRotMatrs, 9*numImages,0.05,"rotation matrices");
609 /* ----- Compare rot matrixs ----- */
610 code = compare(transVects,goodTransVects, 3*numImages,0.1,"translation vectors");
616 ts->printf( cvtest::TS::LOG,
617 "Error in reprojection maxDx=%f > 1.0\n",maxDx);
618 code = cvtest::TS::FAIL_BAD_ACCURACY; goto _exit_;
623 ts->printf( cvtest::TS::LOG,
624 "Error in reprojection maxDy=%f > 1.0\n",maxDy);
625 code = cvtest::TS::FAIL_BAD_ACCURACY; goto _exit_;
628 progress = update_progress( progress, currTest, numTests, 0 );
630 cvFree(&imagePoints);
631 cvFree(&objectPoints);
632 cvFree(&reprojectPoints);
637 cvFree(&goodTransVects);
638 cvFree(&goodRotMatrs);
652 /* Free all allocated memory */
653 cvFree(&imagePoints);
654 cvFree(&objectPoints);
655 cvFree(&reprojectPoints);
660 cvFree(&goodTransVects);
661 cvFree(&goodRotMatrs);
664 ts->set_failed_test_info( code );
667 // --------------------------------- CV_CameraCalibrationTest_C --------------------------------------------
669 class CV_CameraCalibrationTest_C : public CV_CameraCalibrationTest
672 CV_CameraCalibrationTest_C(){}
674 virtual void calibrate( int imageCount, int* pointCounts,
675 CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
676 double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
677 double* rotationMatrices, int flags );
678 virtual void project( int pointCount, CvPoint3D64f* objectPoints,
679 double* rotationMatrix, double* translationVector,
680 double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints );
683 void CV_CameraCalibrationTest_C::calibrate( int imageCount, int* pointCounts,
684 CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
685 double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
686 double* rotationMatrices, int flags )
689 for( i = 0; i < imageCount; i++ )
690 total += pointCounts[i];
692 CvMat _objectPoints = cvMat(1, total, CV_64FC3, objectPoints);
693 CvMat _imagePoints = cvMat(1, total, CV_64FC2, imagePoints);
694 CvMat _pointCounts = cvMat(1, imageCount, CV_32S, pointCounts);
695 CvMat _cameraMatrix = cvMat(3, 3, CV_64F, cameraMatrix);
696 CvMat _distCoeffs = cvMat(4, 1, CV_64F, distortionCoeffs);
697 CvMat _rotationMatrices = cvMat(imageCount, 9, CV_64F, rotationMatrices);
698 CvMat _translationVectors = cvMat(imageCount, 3, CV_64F, translationVectors);
700 cvCalibrateCamera2(&_objectPoints, &_imagePoints, &_pointCounts, imageSize,
701 &_cameraMatrix, &_distCoeffs, &_rotationMatrices, &_translationVectors,
705 void CV_CameraCalibrationTest_C::project( int pointCount, CvPoint3D64f* objectPoints,
706 double* rotationMatrix, double* translationVector,
707 double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints )
709 CvMat _objectPoints = cvMat(1, pointCount, CV_64FC3, objectPoints);
710 CvMat _imagePoints = cvMat(1, pointCount, CV_64FC2, imagePoints);
711 CvMat _cameraMatrix = cvMat(3, 3, CV_64F, cameraMatrix);
712 CvMat _distCoeffs = cvMat(4, 1, CV_64F, distortion);
713 CvMat _rotationMatrix = cvMat(3, 3, CV_64F, rotationMatrix);
714 CvMat _translationVector = cvMat(1, 3, CV_64F, translationVector);
716 cvProjectPoints2(&_objectPoints, &_rotationMatrix, &_translationVector, &_cameraMatrix, &_distCoeffs, &_imagePoints);
719 // --------------------------------- CV_CameraCalibrationTest_CPP --------------------------------------------
721 class CV_CameraCalibrationTest_CPP : public CV_CameraCalibrationTest
724 CV_CameraCalibrationTest_CPP(){}
726 virtual void calibrate( int imageCount, int* pointCounts,
727 CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,
728 double* distortionCoeffs, double* cameraMatrix, double* translationVectors,
729 double* rotationMatrices, int flags );
730 virtual void project( int pointCount, CvPoint3D64f* objectPoints,
731 double* rotationMatrix, double* translationVector,
732 double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints );
735 void CV_CameraCalibrationTest_CPP::calibrate( int imageCount, int* pointCounts,
736 CvSize _imageSize, CvPoint2D64f* _imagePoints, CvPoint3D64f* _objectPoints,
737 double* _distortionCoeffs, double* _cameraMatrix, double* translationVectors,
738 double* rotationMatrices, int flags )
740 vector<vector<Point3f> > objectPoints( imageCount );
741 vector<vector<Point2f> > imagePoints( imageCount );
742 Size imageSize = _imageSize;
743 Mat cameraMatrix, distCoeffs(1,4,CV_64F,Scalar::all(0));
744 vector<Mat> rvecs, tvecs;
746 CvPoint3D64f* op = _objectPoints;
747 CvPoint2D64f* ip = _imagePoints;
748 vector<vector<Point3f> >::iterator objectPointsIt = objectPoints.begin();
749 vector<vector<Point2f> >::iterator imagePointsIt = imagePoints.begin();
750 for( int i = 0; i < imageCount; ++objectPointsIt, ++imagePointsIt, i++ )
752 int num = pointCounts[i];
753 objectPointsIt->resize( num );
754 imagePointsIt->resize( num );
755 vector<Point3f>::iterator oIt = objectPointsIt->begin();
756 vector<Point2f>::iterator iIt = imagePointsIt->begin();
757 for( int j = 0; j < num; ++oIt, ++iIt, j++, op++, ip++)
759 oIt->x = (float)op->x, oIt->y = (float)op->y, oIt->z = (float)op->z;
760 iIt->x = (float)ip->x, iIt->y = (float)ip->y;
764 calibrateCamera( objectPoints,
773 assert( cameraMatrix.type() == CV_64FC1 );
774 memcpy( _cameraMatrix, cameraMatrix.data, 9*sizeof(double) );
776 assert( cameraMatrix.type() == CV_64FC1 );
777 memcpy( _distortionCoeffs, distCoeffs.data, 4*sizeof(double) );
779 vector<Mat>::iterator rvecsIt = rvecs.begin();
780 vector<Mat>::iterator tvecsIt = tvecs.begin();
781 double *rm = rotationMatrices,
782 *tm = translationVectors;
783 assert( rvecsIt->type() == CV_64FC1 );
784 assert( tvecsIt->type() == CV_64FC1 );
785 for( int i = 0; i < imageCount; ++rvecsIt, ++tvecsIt, i++, rm+=9, tm+=3 )
787 Mat r9( 3, 3, CV_64FC1 );
788 Rodrigues( *rvecsIt, r9 );
789 memcpy( rm, r9.data, 9*sizeof(double) );
790 memcpy( tm, tvecsIt->data, 3*sizeof(double) );
794 void CV_CameraCalibrationTest_CPP::project( int pointCount, CvPoint3D64f* _objectPoints,
795 double* rotationMatrix, double* translationVector,
796 double* _cameraMatrix, double* distortion, CvPoint2D64f* _imagePoints )
798 Mat objectPoints( pointCount, 3, CV_64FC1, _objectPoints );
799 Mat rmat( 3, 3, CV_64FC1, rotationMatrix ),
800 rvec( 1, 3, CV_64FC1 ),
801 tvec( 1, 3, CV_64FC1, translationVector );
802 Mat cameraMatrix( 3, 3, CV_64FC1, _cameraMatrix );
803 Mat distCoeffs( 1, 4, CV_64FC1, distortion );
804 vector<Point2f> imagePoints;
805 Rodrigues( rmat, rvec );
807 objectPoints.convertTo( objectPoints, CV_32FC1 );
808 projectPoints( objectPoints, rvec, tvec,
809 cameraMatrix, distCoeffs, imagePoints );
810 vector<Point2f>::const_iterator it = imagePoints.begin();
811 for( int i = 0; it != imagePoints.end(); ++it, i++ )
813 _imagePoints[i] = cvPoint2D64f( it->x, it->y );
818 //----------------------------------------- CV_CalibrationMatrixValuesTest --------------------------------
820 class CV_CalibrationMatrixValuesTest : public cvtest::BaseTest
823 CV_CalibrationMatrixValuesTest() {}
826 virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
827 double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
828 Point2d& principalPoint, double& aspectRatio ) = 0;
831 void CV_CalibrationMatrixValuesTest::run(int)
833 int code = cvtest::TS::OK;
834 const double fcMinVal = 1e-5;
835 const double fcMaxVal = 1000;
836 const double apertureMaxVal = 0.01;
838 RNG rng = ts->get_rng();
840 double fx, fy, cx, cy, nx, ny;
841 Mat cameraMatrix( 3, 3, CV_64FC1 );
842 cameraMatrix.setTo( Scalar(0) );
843 fx = cameraMatrix.at<double>(0,0) = rng.uniform( fcMinVal, fcMaxVal );
844 fy = cameraMatrix.at<double>(1,1) = rng.uniform( fcMinVal, fcMaxVal );
845 cx = cameraMatrix.at<double>(0,2) = rng.uniform( fcMinVal, fcMaxVal );
846 cy = cameraMatrix.at<double>(1,2) = rng.uniform( fcMinVal, fcMaxVal );
847 cameraMatrix.at<double>(2,2) = 1;
849 Size imageSize( 600, 400 );
851 double apertureWidth = (double)rng * apertureMaxVal,
852 apertureHeight = (double)rng * apertureMaxVal;
854 double fovx, fovy, focalLength, aspectRatio,
855 goodFovx, goodFovy, goodFocalLength, goodAspectRatio;
856 Point2d principalPoint, goodPrincipalPoint;
859 calibMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,
860 fovx, fovy, focalLength, principalPoint, aspectRatio );
862 // calculate calibration matrix values
863 goodAspectRatio = fy / fx;
865 if( apertureWidth != 0.0 && apertureHeight != 0.0 )
867 nx = imageSize.width / apertureWidth;
868 ny = imageSize.height / apertureHeight;
873 ny = goodAspectRatio;
876 goodFovx = 2 * atan( imageSize.width / (2 * fx)) * 180.0 / CV_PI;
877 goodFovy = 2 * atan( imageSize.height / (2 * fy)) * 180.0 / CV_PI;
879 goodFocalLength = fx / nx;
881 goodPrincipalPoint.x = cx / nx;
882 goodPrincipalPoint.y = cy / ny;
885 if( fabs(fovx - goodFovx) > FLT_EPSILON )
887 ts->printf( cvtest::TS::LOG, "bad fovx (real=%f, good = %f\n", fovx, goodFovx );
888 code = cvtest::TS::FAIL_BAD_ACCURACY;
891 if( fabs(fovy - goodFovy) > FLT_EPSILON )
893 ts->printf( cvtest::TS::LOG, "bad fovy (real=%f, good = %f\n", fovy, goodFovy );
894 code = cvtest::TS::FAIL_BAD_ACCURACY;
897 if( fabs(focalLength - goodFocalLength) > FLT_EPSILON )
899 ts->printf( cvtest::TS::LOG, "bad focalLength (real=%f, good = %f\n", focalLength, goodFocalLength );
900 code = cvtest::TS::FAIL_BAD_ACCURACY;
903 if( fabs(aspectRatio - goodAspectRatio) > FLT_EPSILON )
905 ts->printf( cvtest::TS::LOG, "bad aspectRatio (real=%f, good = %f\n", aspectRatio, goodAspectRatio );
906 code = cvtest::TS::FAIL_BAD_ACCURACY;
909 if( norm( principalPoint - goodPrincipalPoint ) > FLT_EPSILON )
911 ts->printf( cvtest::TS::LOG, "bad principalPoint\n" );
912 code = cvtest::TS::FAIL_BAD_ACCURACY;
917 RNG& _rng = ts->get_rng();
919 ts->set_failed_test_info( code );
922 //----------------------------------------- CV_CalibrationMatrixValuesTest_C --------------------------------
924 class CV_CalibrationMatrixValuesTest_C : public CV_CalibrationMatrixValuesTest
927 CV_CalibrationMatrixValuesTest_C(){}
929 virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
930 double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
931 Point2d& principalPoint, double& aspectRatio );
934 void CV_CalibrationMatrixValuesTest_C::calibMatrixValues( const Mat& _cameraMatrix, Size imageSize,
935 double apertureWidth, double apertureHeight,
936 double& fovx, double& fovy, double& focalLength,
937 Point2d& principalPoint, double& aspectRatio )
939 CvMat cameraMatrix = _cameraMatrix;
941 cvCalibrationMatrixValues( &cameraMatrix, imageSize, apertureWidth, apertureHeight,
942 &fovx, &fovy, &focalLength, &pp, &aspectRatio );
943 principalPoint.x = pp.x;
944 principalPoint.y = pp.y;
948 //----------------------------------------- CV_CalibrationMatrixValuesTest_CPP --------------------------------
950 class CV_CalibrationMatrixValuesTest_CPP : public CV_CalibrationMatrixValuesTest
953 CV_CalibrationMatrixValuesTest_CPP() {}
955 virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
956 double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
957 Point2d& principalPoint, double& aspectRatio );
960 void CV_CalibrationMatrixValuesTest_CPP::calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
961 double apertureWidth, double apertureHeight,
962 double& fovx, double& fovy, double& focalLength,
963 Point2d& principalPoint, double& aspectRatio )
965 calibrationMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,
966 fovx, fovy, focalLength, principalPoint, aspectRatio );
970 //----------------------------------------- CV_ProjectPointsTest --------------------------------
971 void calcdfdx( const vector<vector<Point2f> >& leftF, const vector<vector<Point2f> >& rightF, double eps, Mat& dfdx )
974 CV_Assert( !leftF.empty() && !rightF.empty() && !leftF[0].empty() && !rightF[0].empty() );
975 CV_Assert( leftF[0].size() == rightF[0].size() );
976 CV_Assert( fabs(eps) > std::numeric_limits<double>::epsilon() );
977 int fcount = (int)leftF[0].size(), xdim = (int)leftF.size();
979 dfdx.create( fcount*fdim, xdim, CV_64FC1 );
981 vector<vector<Point2f> >::const_iterator arrLeftIt = leftF.begin();
982 vector<vector<Point2f> >::const_iterator arrRightIt = rightF.begin();
983 for( int xi = 0; xi < xdim; xi++, ++arrLeftIt, ++arrRightIt )
985 CV_Assert( (int)arrLeftIt->size() == fcount );
986 CV_Assert( (int)arrRightIt->size() == fcount );
987 vector<Point2f>::const_iterator lIt = arrLeftIt->begin();
988 vector<Point2f>::const_iterator rIt = arrRightIt->begin();
989 for( int fi = 0; fi < dfdx.rows; fi+=fdim, ++lIt, ++rIt )
991 dfdx.at<double>(fi, xi ) = 0.5 * ((double)(rIt->x - lIt->x)) / eps;
992 dfdx.at<double>(fi+1, xi ) = 0.5 * ((double)(rIt->y - lIt->y)) / eps;
997 class CV_ProjectPointsTest : public cvtest::BaseTest
1000 CV_ProjectPointsTest() {}
1003 virtual void project( const Mat& objectPoints,
1004 const Mat& rvec, const Mat& tvec,
1005 const Mat& cameraMatrix,
1006 const Mat& distCoeffs,
1007 vector<Point2f>& imagePoints,
1008 Mat& dpdrot, Mat& dpdt, Mat& dpdf,
1009 Mat& dpdc, Mat& dpddist,
1010 double aspectRatio=0 ) = 0;
1013 void CV_ProjectPointsTest::run(int)
1015 //typedef float matType;
1017 int code = cvtest::TS::OK;
1018 const int pointCount = 100;
1020 const float zMinVal = 10.0f, zMaxVal = 100.0f,
1021 rMinVal = -0.3f, rMaxVal = 0.3f,
1022 tMinVal = -2.0f, tMaxVal = 2.0f;
1024 const float imgPointErr = 1e-3f,
1029 Size imgSize( 600, 800 );
1030 Mat_<float> objPoints( pointCount, 3), rvec( 1, 3), rmat, tvec( 1, 3 ), cameraMatrix( 3, 3 ), distCoeffs( 1, 4 ),
1031 leftRvec, rightRvec, leftTvec, rightTvec, leftCameraMatrix, rightCameraMatrix, leftDistCoeffs, rightDistCoeffs;
1033 RNG rng = ts->get_rng();
1036 cameraMatrix << 300.f, 0.f, imgSize.width/2.f,
1037 0.f, 300.f, imgSize.height/2.f,
1039 distCoeffs << 0.1, 0.01, 0.001, 0.001;
1041 rvec(0,0) = rng.uniform( rMinVal, rMaxVal );
1042 rvec(0,1) = rng.uniform( rMinVal, rMaxVal );
1043 rvec(0,2) = rng.uniform( rMinVal, rMaxVal );
1044 Rodrigues( rvec, rmat );
1046 tvec(0,0) = rng.uniform( tMinVal, tMaxVal );
1047 tvec(0,1) = rng.uniform( tMinVal, tMaxVal );
1048 tvec(0,2) = rng.uniform( tMinVal, tMaxVal );
1050 for( int y = 0; y < objPoints.rows; y++ )
1052 Mat point(1, 3, CV_32FC1, objPoints.ptr(y) );
1053 float z = rng.uniform( zMinVal, zMaxVal );
1054 point.at<float>(0,2) = z;
1055 point.at<float>(0,0) = (rng.uniform(2.f,(float)(imgSize.width-2)) - cameraMatrix(0,2)) / cameraMatrix(0,0) * z;
1056 point.at<float>(0,1) = (rng.uniform(2.f,(float)(imgSize.height-2)) - cameraMatrix(1,2)) / cameraMatrix(1,1) * z;
1057 point = (point - tvec) * rmat;
1060 vector<Point2f> imgPoints;
1061 vector<vector<Point2f> > leftImgPoints;
1062 vector<vector<Point2f> > rightImgPoints;
1063 Mat dpdrot, dpdt, dpdf, dpdc, dpddist,
1064 valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist;
1066 project( objPoints, rvec, tvec, cameraMatrix, distCoeffs,
1067 imgPoints, dpdrot, dpdt, dpdf, dpdc, dpddist, 0 );
1069 // calculate and check image points
1070 assert( (int)imgPoints.size() == pointCount );
1071 vector<Point2f>::const_iterator it = imgPoints.begin();
1072 for( int i = 0; i < pointCount; i++, ++it )
1074 Point3d p( objPoints(i,0), objPoints(i,1), objPoints(i,2) );
1075 double z = p.x*rmat(2,0) + p.y*rmat(2,1) + p.z*rmat(2,2) + tvec(0,2),
1076 x = (p.x*rmat(0,0) + p.y*rmat(0,1) + p.z*rmat(0,2) + tvec(0,0)) / z,
1077 y = (p.x*rmat(1,0) + p.y*rmat(1,1) + p.z*rmat(1,2) + tvec(0,1)) / z,
1080 Point2f validImgPoint;
1084 cdist = 1+distCoeffs(0,0)*r2+distCoeffs(0,1)*r4;
1085 validImgPoint.x = static_cast<float>((double)cameraMatrix(0,0)*(x*cdist + (double)distCoeffs(0,2)*a1 + (double)distCoeffs(0,3)*a2)
1086 + (double)cameraMatrix(0,2));
1087 validImgPoint.y = static_cast<float>((double)cameraMatrix(1,1)*(y*cdist + (double)distCoeffs(0,2)*a3 + distCoeffs(0,3)*a1)
1088 + (double)cameraMatrix(1,2));
1090 if( fabs(it->x - validImgPoint.x) > imgPointErr ||
1091 fabs(it->y - validImgPoint.y) > imgPointErr )
1093 ts->printf( cvtest::TS::LOG, "bad image point\n" );
1094 code = cvtest::TS::FAIL_BAD_ACCURACY;
1099 // check derivatives
1101 leftImgPoints.resize(3);
1102 rightImgPoints.resize(3);
1103 for( int i = 0; i < 3; i++ )
1105 rvec.copyTo( leftRvec ); leftRvec(0,i) -= dEps;
1106 project( objPoints, leftRvec, tvec, cameraMatrix, distCoeffs,
1107 leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1108 rvec.copyTo( rightRvec ); rightRvec(0,i) += dEps;
1109 project( objPoints, rightRvec, tvec, cameraMatrix, distCoeffs,
1110 rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1112 calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdrot );
1113 err = norm( dpdrot, valDpdrot, NORM_INF );
1116 ts->printf( cvtest::TS::LOG, "bad dpdrot: too big difference = %g\n", err );
1117 code = cvtest::TS::FAIL_BAD_ACCURACY;
1121 for( int i = 0; i < 3; i++ )
1123 tvec.copyTo( leftTvec ); leftTvec(0,i) -= dEps;
1124 project( objPoints, rvec, leftTvec, cameraMatrix, distCoeffs,
1125 leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1126 tvec.copyTo( rightTvec ); rightTvec(0,i) += dEps;
1127 project( objPoints, rvec, rightTvec, cameraMatrix, distCoeffs,
1128 rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1130 calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdt );
1131 if( norm( dpdt, valDpdt, NORM_INF ) > 0.2 )
1133 ts->printf( cvtest::TS::LOG, "bad dpdtvec\n" );
1134 code = cvtest::TS::FAIL_BAD_ACCURACY;
1139 leftImgPoints.resize(2);
1140 rightImgPoints.resize(2);
1141 cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,0) -= dEps;
1142 project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
1143 leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1144 cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,1) -= dEps;
1145 project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
1146 leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1147 cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,0) += dEps;
1148 project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
1149 rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1150 cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,1) += dEps;
1151 project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
1152 rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1153 calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdf );
1154 if ( norm( dpdf, valDpdf ) > 0.2 )
1156 ts->printf( cvtest::TS::LOG, "bad dpdf\n" );
1157 code = cvtest::TS::FAIL_BAD_ACCURACY;
1159 // 3.2. principal point
1160 leftImgPoints.resize(2);
1161 rightImgPoints.resize(2);
1162 cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,2) -= dEps;
1163 project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
1164 leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1165 cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,2) -= dEps;
1166 project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
1167 leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1168 cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,2) += dEps;
1169 project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
1170 rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1171 cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,2) += dEps;
1172 project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
1173 rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1174 calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdc );
1175 if ( norm( dpdc, valDpdc ) > 0.2 )
1177 ts->printf( cvtest::TS::LOG, "bad dpdc\n" );
1178 code = cvtest::TS::FAIL_BAD_ACCURACY;
1182 leftImgPoints.resize(distCoeffs.cols);
1183 rightImgPoints.resize(distCoeffs.cols);
1184 for( int i = 0; i < distCoeffs.cols; i++ )
1186 distCoeffs.copyTo( leftDistCoeffs ); leftDistCoeffs(0,i) -= dEps;
1187 project( objPoints, rvec, tvec, cameraMatrix, leftDistCoeffs,
1188 leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1189 distCoeffs.copyTo( rightDistCoeffs ); rightDistCoeffs(0,i) += dEps;
1190 project( objPoints, rvec, tvec, cameraMatrix, rightDistCoeffs,
1191 rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
1193 calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpddist );
1194 if( norm( dpddist, valDpddist ) > 0.3 )
1196 ts->printf( cvtest::TS::LOG, "bad dpddist\n" );
1197 code = cvtest::TS::FAIL_BAD_ACCURACY;
1201 RNG& _rng = ts->get_rng();
1203 ts->set_failed_test_info( code );
1206 //----------------------------------------- CV_ProjectPointsTest_C --------------------------------
1207 class CV_ProjectPointsTest_C : public CV_ProjectPointsTest
1210 CV_ProjectPointsTest_C() {}
1212 virtual void project( const Mat& objectPoints,
1213 const Mat& rvec, const Mat& tvec,
1214 const Mat& cameraMatrix,
1215 const Mat& distCoeffs,
1216 vector<Point2f>& imagePoints,
1217 Mat& dpdrot, Mat& dpdt, Mat& dpdf,
1218 Mat& dpdc, Mat& dpddist,
1219 double aspectRatio=0 );
1222 void CV_ProjectPointsTest_C::project( const Mat& opoints, const Mat& rvec, const Mat& tvec,
1223 const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& ipoints,
1224 Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)
1226 int npoints = opoints.cols*opoints.rows*opoints.channels()/3;
1227 ipoints.resize(npoints);
1228 dpdrot.create(npoints*2, 3, CV_64F);
1229 dpdt.create(npoints*2, 3, CV_64F);
1230 dpdf.create(npoints*2, 2, CV_64F);
1231 dpdc.create(npoints*2, 2, CV_64F);
1232 dpddist.create(npoints*2, distCoeffs.rows + distCoeffs.cols - 1, CV_64F);
1233 CvMat _objectPoints = opoints, _imagePoints = Mat(ipoints);
1234 CvMat _rvec = rvec, _tvec = tvec, _cameraMatrix = cameraMatrix, _distCoeffs = distCoeffs;
1235 CvMat _dpdrot = dpdrot, _dpdt = dpdt, _dpdf = dpdf, _dpdc = dpdc, _dpddist = dpddist;
1237 cvProjectPoints2( &_objectPoints, &_rvec, &_tvec, &_cameraMatrix, &_distCoeffs,
1238 &_imagePoints, &_dpdrot, &_dpdt, &_dpdf, &_dpdc, &_dpddist, aspectRatio );
1242 //----------------------------------------- CV_ProjectPointsTest_CPP --------------------------------
1243 class CV_ProjectPointsTest_CPP : public CV_ProjectPointsTest
1246 CV_ProjectPointsTest_CPP() {}
1248 virtual void project( const Mat& objectPoints,
1249 const Mat& rvec, const Mat& tvec,
1250 const Mat& cameraMatrix,
1251 const Mat& distCoeffs,
1252 vector<Point2f>& imagePoints,
1253 Mat& dpdrot, Mat& dpdt, Mat& dpdf,
1254 Mat& dpdc, Mat& dpddist,
1255 double aspectRatio=0 );
1258 void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec, const Mat& tvec,
1259 const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& imagePoints,
1260 Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)
1263 projectPoints( objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, J, aspectRatio);
1264 J.colRange(0, 3).copyTo(dpdrot);
1265 J.colRange(3, 6).copyTo(dpdt);
1266 J.colRange(6, 8).copyTo(dpdf);
1267 J.colRange(8, 10).copyTo(dpdc);
1268 J.colRange(10, J.cols).copyTo(dpddist);
1271 ///////////////////////////////// Stereo Calibration /////////////////////////////////////
1273 class CV_StereoCalibrationTest : public cvtest::BaseTest
1276 CV_StereoCalibrationTest();
1277 ~CV_StereoCalibrationTest();
1280 bool checkPandROI( int test_case_idx,
1281 const Mat& M, const Mat& D, const Mat& R,
1282 const Mat& P, Size imgsize, Rect roi );
1284 // covers of tested functions
1285 virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
1286 const vector<vector<Point2f> >& imagePoints1,
1287 const vector<vector<Point2f> >& imagePoints2,
1288 Mat& cameraMatrix1, Mat& distCoeffs1,
1289 Mat& cameraMatrix2, Mat& distCoeffs2,
1290 Size imageSize, Mat& R, Mat& T,
1291 Mat& E, Mat& F, TermCriteria criteria, int flags ) = 0;
1292 virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
1293 const Mat& cameraMatrix2, const Mat& distCoeffs2,
1294 Size imageSize, const Mat& R, const Mat& T,
1295 Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
1296 double alpha, Size newImageSize,
1297 Rect* validPixROI1, Rect* validPixROI2, int flags ) = 0;
1298 virtual bool rectifyUncalibrated( const Mat& points1,
1299 const Mat& points2, const Mat& F, Size imgSize,
1300 Mat& H1, Mat& H2, double threshold=5 ) = 0;
1301 virtual void triangulate( const Mat& P1, const Mat& P2,
1302 const Mat &points1, const Mat &points2,
1303 Mat &points4D ) = 0;
1304 virtual void correct( const Mat& F,
1305 const Mat &points1, const Mat &points2,
1306 Mat &newPoints1, Mat &newPoints2 ) = 0;
1312 CV_StereoCalibrationTest::CV_StereoCalibrationTest()
1317 CV_StereoCalibrationTest::~CV_StereoCalibrationTest()
1322 void CV_StereoCalibrationTest::clear()
1324 cvtest::BaseTest::clear();
1327 bool CV_StereoCalibrationTest::checkPandROI( int test_case_idx, const Mat& M, const Mat& D, const Mat& R,
1328 const Mat& P, Size imgsize, Rect roi )
1330 const double eps = 0.05;
1333 vector<Point2f> pts, upts;
1335 // step 1. check that all the original points belong to the destination image
1336 for( y = 0; y < N; y++ )
1337 for( x = 0; x < N; x++ )
1338 pts.push_back(Point2f((float)x*imgsize.width/(N-1), (float)y*imgsize.height/(N-1)));
1340 undistortPoints(Mat(pts), upts, M, D, R, P );
1341 for( k = 0; k < N*N; k++ )
1342 if( upts[k].x < -imgsize.width*eps || upts[k].x > imgsize.width*(1+eps) ||
1343 upts[k].y < -imgsize.height*eps || upts[k].y > imgsize.height*(1+eps) )
1345 ts->printf(cvtest::TS::LOG, "Test #%d. The point (%g, %g) was mapped to (%g, %g) which is out of image\n",
1346 test_case_idx, pts[k].x, pts[k].y, upts[k].x, upts[k].y);
1350 // step 2. check that all the points inside ROI belong to the original source image
1351 Mat temp(imgsize, CV_8U), utemp, map1, map2;
1352 temp = Scalar::all(1);
1353 initUndistortRectifyMap(M, D, R, P, imgsize, CV_16SC2, map1, map2);
1354 remap(temp, utemp, map1, map2, INTER_LINEAR);
1356 if(roi.x < 0 || roi.y < 0 || roi.x + roi.width > imgsize.width || roi.y + roi.height > imgsize.height)
1358 ts->printf(cvtest::TS::LOG, "Test #%d. The ROI=(%d, %d, %d, %d) is outside of the imge rectangle\n",
1359 test_case_idx, roi.x, roi.y, roi.width, roi.height);
1362 double s = sum(utemp(roi))[0];
1363 if( s > roi.area() || roi.area() - s > roi.area()*(1-eps) )
1365 ts->printf(cvtest::TS::LOG, "Test #%d. The ratio of black pixels inside the valid ROI (~%g%%) is too large\n",
1366 test_case_idx, s*100./roi.area());
1373 void CV_StereoCalibrationTest::run( int )
1375 const int ntests = 1;
1376 const double maxReprojErr = 2;
1377 const double maxScanlineDistErr_c = 3;
1378 const double maxScanlineDistErr_uc = 4;
1381 for(int testcase = 1; testcase <= ntests; testcase++)
1383 char filepath[1000];
1385 sprintf( filepath, "%sstereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase );
1386 f = fopen(filepath, "rt");
1388 vector<string> imglist;
1390 if( !f || !fgets(buf, sizeof(buf)-3, f) || sscanf(buf, "%d%d", &patternSize.width, &patternSize.height) != 2 )
1392 ts->printf( cvtest::TS::LOG, "The file %s can not be opened or has invalid content\n", filepath );
1393 ts->set_failed_test_info( f ? cvtest::TS::FAIL_INVALID_TEST_DATA : cvtest::TS::FAIL_MISSING_TEST_DATA );
1399 if( !fgets( buf, sizeof(buf)-3, f ))
1401 size_t len = strlen(buf);
1402 while( len > 0 && isspace(buf[len-1]))
1406 sprintf(filepath, "%sstereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf );
1407 imglist.push_back(string(filepath));
1411 if( imglist.size() == 0 || imglist.size() % 2 != 0 )
1413 ts->printf( cvtest::TS::LOG, "The number of images is 0 or an odd number in the case #%d\n", testcase );
1414 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
1418 int nframes = (int)(imglist.size()/2);
1419 int npoints = patternSize.width*patternSize.height;
1420 vector<vector<Point3f> > objpt(nframes);
1421 vector<vector<Point2f> > imgpt1(nframes);
1422 vector<vector<Point2f> > imgpt2(nframes);
1426 for( int i = 0; i < nframes; i++ )
1428 Mat left = imread(imglist[i*2]);
1429 Mat right = imread(imglist[i*2+1]);
1430 if(!left.data || !right.data)
1432 ts->printf( cvtest::TS::LOG, "Can not load images %s and %s, testcase %d\n",
1433 imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase );
1434 ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
1437 imgsize = left.size();
1438 bool found1 = findChessboardCorners(left, patternSize, imgpt1[i]);
1439 bool found2 = findChessboardCorners(right, patternSize, imgpt2[i]);
1440 if(!found1 || !found2)
1442 ts->printf( cvtest::TS::LOG, "The function could not detect boards on the images %s and %s, testcase %d\n",
1443 imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase );
1444 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
1447 total += (int)imgpt1[i].size();
1448 for( int j = 0; j < npoints; j++ )
1449 objpt[i].push_back(Point3f((float)(j%patternSize.width), (float)(j/patternSize.width), 0.f));
1452 // rectify (calibrated)
1453 Mat M1 = Mat::eye(3,3,CV_64F), M2 = Mat::eye(3,3,CV_64F), D1(5,1,CV_64F), D2(5,1,CV_64F), R, T, E, F;
1454 M1.at<double>(0,2) = M2.at<double>(0,2)=(imgsize.width-1)*0.5;
1455 M1.at<double>(1,2) = M2.at<double>(1,2)=(imgsize.height-1)*0.5;
1456 D1 = Scalar::all(0);
1457 D2 = Scalar::all(0);
1458 double err = calibrateStereoCamera(objpt, imgpt1, imgpt2, M1, D1, M2, D2, imgsize, R, T, E, F,
1459 TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 1e-6),
1460 CV_CALIB_SAME_FOCAL_LENGTH
1461 //+ CV_CALIB_FIX_ASPECT_RATIO
1462 + CV_CALIB_FIX_PRINCIPAL_POINT
1463 + CV_CALIB_ZERO_TANGENT_DIST
1465 + CV_CALIB_FIX_K4 + CV_CALIB_FIX_K5 //+ CV_CALIB_FIX_K6
1467 err /= nframes*npoints;
1468 if( err > maxReprojErr )
1470 ts->printf( cvtest::TS::LOG, "The average reprojection error is too big (=%g), testcase %d\n", err, testcase);
1471 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
1475 Mat R1, R2, P1, P2, Q;
1477 rectify(M1, D1, M2, D2, imgsize, R, T, R1, R2, P1, P2, Q, 1, imgsize, &roi1, &roi2, 0);
1478 Mat eye33 = Mat::eye(3,3,CV_64F);
1479 Mat R1t = R1.t(), R2t = R2.t();
1481 if( norm(R1t*R1 - eye33) > 0.01 ||
1482 norm(R2t*R2 - eye33) > 0.01 ||
1483 abs(determinant(F)) > 0.01)
1485 ts->printf( cvtest::TS::LOG, "The computed (by rectify) R1 and R2 are not orthogonal,"
1486 "or the computed (by calibrate) F is not singular, testcase %d\n", testcase);
1487 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
1491 if(!checkPandROI(testcase, M1, D1, R1, P1, imgsize, roi1))
1493 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
1497 if(!checkPandROI(testcase, M2, D2, R2, P2, imgsize, roi2))
1499 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
1503 //check that Tx after rectification is equal to distance between cameras
1504 double tx = fabs(P2.at<double>(0, 3) / P2.at<double>(0, 0));
1505 if (fabs(tx - norm(T)) > 1e-5)
1507 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
1511 //check that Q reprojects points before the camera
1512 double testPoint[4] = {0.0, 0.0, 100.0, 1.0};
1513 Mat reprojectedTestPoint = Q * Mat_<double>(4, 1, testPoint);
1514 CV_Assert(reprojectedTestPoint.type() == CV_64FC1);
1515 if( reprojectedTestPoint.at<double>(2) / reprojectedTestPoint.at<double>(3) < 0 )
1517 ts->printf( cvtest::TS::LOG, "A point after rectification is reprojected behind the camera, testcase %d\n", testcase);
1518 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
1521 //check that Q reprojects the same points as reconstructed by triangulation
1522 const float minCoord = -300.0f;
1523 const float maxCoord = 300.0f;
1524 const float minDisparity = 0.1f;
1525 const float maxDisparity = 600.0f;
1526 const int pointsCount = 500;
1527 const float requiredAccuracy = 1e-3f;
1528 RNG& rng = ts->get_rng();
1530 Mat projectedPoints_1(2, pointsCount, CV_32FC1);
1531 Mat projectedPoints_2(2, pointsCount, CV_32FC1);
1532 Mat disparities(1, pointsCount, CV_32FC1);
1534 rng.fill(projectedPoints_1, RNG::UNIFORM, minCoord, maxCoord);
1535 rng.fill(disparities, RNG::UNIFORM, minDisparity, maxDisparity);
1536 projectedPoints_2.row(0) = projectedPoints_1.row(0) - disparities;
1537 Mat ys_2 = projectedPoints_2.row(1);
1538 projectedPoints_1.row(1).copyTo(ys_2);
1541 triangulate(P1, P2, projectedPoints_1, projectedPoints_2, points4d);
1542 Mat homogeneousPoints4d = points4d.t();
1543 const int dimension = 4;
1544 homogeneousPoints4d = homogeneousPoints4d.reshape(dimension);
1545 Mat triangulatedPoints;
1546 convertPointsFromHomogeneous(homogeneousPoints4d, triangulatedPoints);
1549 sparsePoints.push_back(projectedPoints_1);
1550 sparsePoints.push_back(disparities);
1551 sparsePoints = sparsePoints.t();
1552 sparsePoints = sparsePoints.reshape(3);
1553 Mat reprojectedPoints;
1554 perspectiveTransform(sparsePoints, reprojectedPoints, Q);
1556 if (norm(triangulatedPoints - reprojectedPoints) / sqrt((double)pointsCount) > requiredAccuracy)
1558 ts->printf( cvtest::TS::LOG, "Points reprojected with a matrix Q and points reconstructed by triangulation are different, testcase %d\n", testcase);
1559 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
1562 //check correctMatches
1563 const float constraintAccuracy = 1e-5f;
1564 Mat newPoints1, newPoints2;
1565 Mat points1 = projectedPoints_1.t();
1566 points1 = points1.reshape(2, 1);
1567 Mat points2 = projectedPoints_2.t();
1568 points2 = points2.reshape(2, 1);
1569 correctMatches(F, points1, points2, newPoints1, newPoints2);
1570 Mat newHomogeneousPoints1, newHomogeneousPoints2;
1571 convertPointsToHomogeneous(newPoints1, newHomogeneousPoints1);
1572 convertPointsToHomogeneous(newPoints2, newHomogeneousPoints2);
1573 newHomogeneousPoints1 = newHomogeneousPoints1.reshape(1);
1574 newHomogeneousPoints2 = newHomogeneousPoints2.reshape(1);
1576 F.convertTo(typedF, newHomogeneousPoints1.type());
1577 for (int i = 0; i < newHomogeneousPoints1.rows; ++i)
1579 Mat error = newHomogeneousPoints2.row(i) * typedF * newHomogeneousPoints1.row(i).t();
1580 CV_Assert(error.rows == 1 && error.cols == 1);
1581 if (norm(error) > constraintAccuracy)
1583 ts->printf( cvtest::TS::LOG, "Epipolar constraint is violated after correctMatches, testcase %d\n", testcase);
1584 ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
1588 // rectifyUncalibrated
1589 CV_Assert( imgpt1.size() == imgpt2.size() );
1590 Mat _imgpt1( total, 1, CV_32FC2 ), _imgpt2( total, 1, CV_32FC2 );
1591 vector<vector<Point2f> >::const_iterator iit1 = imgpt1.begin();
1592 vector<vector<Point2f> >::const_iterator iit2 = imgpt2.begin();
1593 for( int pi = 0; iit1 != imgpt1.end(); ++iit1, ++iit2 )
1595 vector<Point2f>::const_iterator pit1 = iit1->begin();
1596 vector<Point2f>::const_iterator pit2 = iit2->begin();
1597 CV_Assert( iit1->size() == iit2->size() );
1598 for( ; pit1 != iit1->end(); ++pit1, ++pit2, pi++ )
1600 _imgpt1.at<Point2f>(pi,0) = Point2f( pit1->x, pit1->y );
1601 _imgpt2.at<Point2f>(pi,0) = Point2f( pit2->x, pit2->y );
1605 Mat _M1, _M2, _D1, _D2;
1606 vector<Mat> _R1, _R2, _T1, _T2;
1607 calibrateCamera( objpt, imgpt1, imgsize, _M1, _D1, _R1, _T1, 0 );
1608 calibrateCamera( objpt, imgpt2, imgsize, _M2, _D2, _R2, _T1, 0 );
1609 undistortPoints( _imgpt1, _imgpt1, _M1, _D1, Mat(), _M1 );
1610 undistortPoints( _imgpt2, _imgpt2, _M2, _D2, Mat(), _M2 );
1613 matF = findFundamentalMat( _imgpt1, _imgpt2 );
1614 rectifyUncalibrated( _imgpt1, _imgpt2, matF, imgsize, _H1, _H2 );
1616 Mat rectifPoints1, rectifPoints2;
1617 perspectiveTransform( _imgpt1, rectifPoints1, _H1 );
1618 perspectiveTransform( _imgpt2, rectifPoints2, _H2 );
1620 bool verticalStereo = abs(P2.at<double>(0,3)) < abs(P2.at<double>(1,3));
1621 double maxDiff_c = 0, maxDiff_uc = 0;
1622 for( int i = 0, k = 0; i < nframes; i++ )
1624 vector<Point2f> temp[2];
1625 undistortPoints(Mat(imgpt1[i]), temp[0], M1, D1, R1, P1);
1626 undistortPoints(Mat(imgpt2[i]), temp[1], M2, D2, R2, P2);
1628 for( int j = 0; j < npoints; j++, k++ )
1630 double diff_c = verticalStereo ? abs(temp[0][j].x - temp[1][j].x) : abs(temp[0][j].y - temp[1][j].y);
1631 Point2f d = rectifPoints1.at<Point2f>(k,0) - rectifPoints2.at<Point2f>(k,0);
1632 double diff_uc = verticalStereo ? abs(d.x) : abs(d.y);
1633 maxDiff_c = max(maxDiff_c, diff_c);
1634 maxDiff_uc = max(maxDiff_uc, diff_uc);
1635 if( maxDiff_c > maxScanlineDistErr_c )
1637 ts->printf( cvtest::TS::LOG, "The distance between %s coordinates is too big(=%g) (used calibrated stereo), testcase %d\n",
1638 verticalStereo ? "x" : "y", diff_c, testcase);
1639 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
1642 if( maxDiff_uc > maxScanlineDistErr_uc )
1644 ts->printf( cvtest::TS::LOG, "The distance between %s coordinates is too big(=%g) (used uncalibrated stereo), testcase %d\n",
1645 verticalStereo ? "x" : "y", diff_uc, testcase);
1646 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
1652 ts->printf( cvtest::TS::LOG, "Testcase %d. Max distance (calibrated) =%g\n"
1653 "Max distance (uncalibrated) =%g\n", testcase, maxDiff_c, maxDiff_uc );
1657 //-------------------------------- CV_StereoCalibrationTest_C ------------------------------
1659 class CV_StereoCalibrationTest_C : public CV_StereoCalibrationTest
1662 CV_StereoCalibrationTest_C() {}
1664 virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
1665 const vector<vector<Point2f> >& imagePoints1,
1666 const vector<vector<Point2f> >& imagePoints2,
1667 Mat& cameraMatrix1, Mat& distCoeffs1,
1668 Mat& cameraMatrix2, Mat& distCoeffs2,
1669 Size imageSize, Mat& R, Mat& T,
1670 Mat& E, Mat& F, TermCriteria criteria, int flags );
1671 virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
1672 const Mat& cameraMatrix2, const Mat& distCoeffs2,
1673 Size imageSize, const Mat& R, const Mat& T,
1674 Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
1675 double alpha, Size newImageSize,
1676 Rect* validPixROI1, Rect* validPixROI2, int flags );
1677 virtual bool rectifyUncalibrated( const Mat& points1,
1678 const Mat& points2, const Mat& F, Size imgSize,
1679 Mat& H1, Mat& H2, double threshold=5 );
1680 virtual void triangulate( const Mat& P1, const Mat& P2,
1681 const Mat &points1, const Mat &points2,
1683 virtual void correct( const Mat& F,
1684 const Mat &points1, const Mat &points2,
1685 Mat &newPoints1, Mat &newPoints2 );
1688 double CV_StereoCalibrationTest_C::calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
1689 const vector<vector<Point2f> >& imagePoints1,
1690 const vector<vector<Point2f> >& imagePoints2,
1691 Mat& cameraMatrix1, Mat& distCoeffs1,
1692 Mat& cameraMatrix2, Mat& distCoeffs2,
1693 Size imageSize, Mat& R, Mat& T,
1694 Mat& E, Mat& F, TermCriteria criteria, int flags )
1696 cameraMatrix1.create( 3, 3, CV_64F );
1697 cameraMatrix2.create( 3, 3, CV_64F);
1698 distCoeffs1.create( 1, 5, CV_64F);
1699 distCoeffs2.create( 1, 5, CV_64F);
1700 R.create(3, 3, CV_64F);
1701 T.create(3, 1, CV_64F);
1702 E.create(3, 3, CV_64F);
1703 F.create(3, 3, CV_64F);
1705 int nimages = (int)objectPoints.size(), total = 0;
1706 for( int i = 0; i < nimages; i++ )
1708 total += (int)objectPoints[i].size();
1711 Mat npoints( 1, nimages, CV_32S ),
1712 objPt( 1, total, DataType<Point3f>::type ),
1713 imgPt( 1, total, DataType<Point2f>::type ),
1714 imgPt2( 1, total, DataType<Point2f>::type );
1716 Point2f* imgPtData2 = imgPt2.ptr<Point2f>();
1717 Point3f* objPtData = objPt.ptr<Point3f>();
1718 Point2f* imgPtData = imgPt.ptr<Point2f>();
1719 for( int i = 0, ni = 0, j = 0; i < nimages; i++, j += ni )
1721 ni = (int)objectPoints[i].size();
1722 ((int*)npoints.data)[i] = ni;
1723 std::copy(objectPoints[i].begin(), objectPoints[i].end(), objPtData + j);
1724 std::copy(imagePoints1[i].begin(), imagePoints1[i].end(), imgPtData + j);
1725 std::copy(imagePoints2[i].begin(), imagePoints2[i].end(), imgPtData2 + j);
1727 CvMat _objPt = objPt, _imgPt = imgPt, _imgPt2 = imgPt2, _npoints = npoints;
1728 CvMat _cameraMatrix1 = cameraMatrix1, _distCoeffs1 = distCoeffs1;
1729 CvMat _cameraMatrix2 = cameraMatrix2, _distCoeffs2 = distCoeffs2;
1730 CvMat matR = R, matT = T, matE = E, matF = F;
1732 return cvStereoCalibrate(&_objPt, &_imgPt, &_imgPt2, &_npoints, &_cameraMatrix1,
1733 &_distCoeffs1, &_cameraMatrix2, &_distCoeffs2, imageSize,
1734 &matR, &matT, &matE, &matF, criteria, flags );
1737 void CV_StereoCalibrationTest_C::rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
1738 const Mat& cameraMatrix2, const Mat& distCoeffs2,
1739 Size imageSize, const Mat& R, const Mat& T,
1740 Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
1741 double alpha, Size newImageSize,
1742 Rect* validPixROI1, Rect* validPixROI2, int flags )
1745 R1.create(3, 3, rtype);
1746 R2.create(3, 3, rtype);
1747 P1.create(3, 4, rtype);
1748 P2.create(3, 4, rtype);
1749 Q.create(4, 4, rtype);
1750 CvMat _cameraMatrix1 = cameraMatrix1, _distCoeffs1 = distCoeffs1;
1751 CvMat _cameraMatrix2 = cameraMatrix2, _distCoeffs2 = distCoeffs2;
1752 CvMat matR = R, matT = T, _R1 = R1, _R2 = R2, _P1 = P1, _P2 = P2, matQ = Q;
1753 cvStereoRectify( &_cameraMatrix1, &_cameraMatrix2, &_distCoeffs1, &_distCoeffs2,
1754 imageSize, &matR, &matT, &_R1, &_R2, &_P1, &_P2, &matQ, flags,
1755 alpha, newImageSize, (CvRect*)validPixROI1, (CvRect*)validPixROI2);
1758 bool CV_StereoCalibrationTest_C::rectifyUncalibrated( const Mat& points1,
1759 const Mat& points2, const Mat& F, Size imgSize, Mat& H1, Mat& H2, double threshold )
1761 H1.create(3, 3, CV_64F);
1762 H2.create(3, 3, CV_64F);
1763 CvMat _pt1 = points1, _pt2 = points2, matF, *pF=0, _H1 = H1, _H2 = H2;
1764 if( F.size() == Size(3, 3) )
1766 return cvStereoRectifyUncalibrated(&_pt1, &_pt2, pF, imgSize, &_H1, &_H2, threshold) > 0;
1769 void CV_StereoCalibrationTest_C::triangulate( const Mat& P1, const Mat& P2,
1770 const Mat &points1, const Mat &points2,
1773 CvMat _P1 = P1, _P2 = P2, _points1 = points1, _points2 = points2;
1774 points4D.create(4, points1.cols, points1.type());
1775 CvMat _points4D = points4D;
1776 cvTriangulatePoints(&_P1, &_P2, &_points1, &_points2, &_points4D);
1779 void CV_StereoCalibrationTest_C::correct( const Mat& F,
1780 const Mat &points1, const Mat &points2,
1781 Mat &newPoints1, Mat &newPoints2 )
1783 CvMat _F = F, _points1 = points1, _points2 = points2;
1784 newPoints1.create(1, points1.cols, points1.type());
1785 newPoints2.create(1, points2.cols, points2.type());
1786 CvMat _newPoints1 = newPoints1, _newPoints2 = newPoints2;
1787 cvCorrectMatches(&_F, &_points1, &_points2, &_newPoints1, &_newPoints2);
1790 //-------------------------------- CV_StereoCalibrationTest_CPP ------------------------------
1792 class CV_StereoCalibrationTest_CPP : public CV_StereoCalibrationTest
1795 CV_StereoCalibrationTest_CPP() {}
1797 virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
1798 const vector<vector<Point2f> >& imagePoints1,
1799 const vector<vector<Point2f> >& imagePoints2,
1800 Mat& cameraMatrix1, Mat& distCoeffs1,
1801 Mat& cameraMatrix2, Mat& distCoeffs2,
1802 Size imageSize, Mat& R, Mat& T,
1803 Mat& E, Mat& F, TermCriteria criteria, int flags );
1804 virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
1805 const Mat& cameraMatrix2, const Mat& distCoeffs2,
1806 Size imageSize, const Mat& R, const Mat& T,
1807 Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
1808 double alpha, Size newImageSize,
1809 Rect* validPixROI1, Rect* validPixROI2, int flags );
1810 virtual bool rectifyUncalibrated( const Mat& points1,
1811 const Mat& points2, const Mat& F, Size imgSize,
1812 Mat& H1, Mat& H2, double threshold=5 );
1813 virtual void triangulate( const Mat& P1, const Mat& P2,
1814 const Mat &points1, const Mat &points2,
1816 virtual void correct( const Mat& F,
1817 const Mat &points1, const Mat &points2,
1818 Mat &newPoints1, Mat &newPoints2 );
1821 double CV_StereoCalibrationTest_CPP::calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
1822 const vector<vector<Point2f> >& imagePoints1,
1823 const vector<vector<Point2f> >& imagePoints2,
1824 Mat& cameraMatrix1, Mat& distCoeffs1,
1825 Mat& cameraMatrix2, Mat& distCoeffs2,
1826 Size imageSize, Mat& R, Mat& T,
1827 Mat& E, Mat& F, TermCriteria criteria, int flags )
1829 return stereoCalibrate( objectPoints, imagePoints1, imagePoints2,
1830 cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,
1831 imageSize, R, T, E, F, criteria, flags );
1834 void CV_StereoCalibrationTest_CPP::rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
1835 const Mat& cameraMatrix2, const Mat& distCoeffs2,
1836 Size imageSize, const Mat& R, const Mat& T,
1837 Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
1838 double alpha, Size newImageSize,
1839 Rect* validPixROI1, Rect* validPixROI2, int flags )
1841 stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,
1842 imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize,validPixROI1, validPixROI2 );
1845 bool CV_StereoCalibrationTest_CPP::rectifyUncalibrated( const Mat& points1,
1846 const Mat& points2, const Mat& F, Size imgSize, Mat& H1, Mat& H2, double threshold )
1848 return stereoRectifyUncalibrated( points1, points2, F, imgSize, H1, H2, threshold );
1851 void CV_StereoCalibrationTest_CPP::triangulate( const Mat& P1, const Mat& P2,
1852 const Mat &points1, const Mat &points2,
1855 triangulatePoints(P1, P2, points1, points2, points4D);
1858 void CV_StereoCalibrationTest_CPP::correct( const Mat& F,
1859 const Mat &points1, const Mat &points2,
1860 Mat &newPoints1, Mat &newPoints2 )
1862 correctMatches(F, points1, points2, newPoints1, newPoints2);
1865 ///////////////////////////////////////////////////////////////////////////////////////////////////
1867 TEST(Calib3d_CalibrateCamera_C, regression) { CV_CameraCalibrationTest_C test; test.safe_run(); }
1868 TEST(Calib3d_CalibrateCamera_CPP, regression) { CV_CameraCalibrationTest_CPP test; test.safe_run(); }
1869 TEST(Calib3d_CalibrationMatrixValues_C, accuracy) { CV_CalibrationMatrixValuesTest_C test; test.safe_run(); }
1870 TEST(Calib3d_CalibrationMatrixValues_CPP, accuracy) { CV_CalibrationMatrixValuesTest_CPP test; test.safe_run(); }
1871 TEST(Calib3d_ProjectPoints_C, accuracy) { CV_ProjectPointsTest_C test; test.safe_run(); }
1872 TEST(Calib3d_ProjectPoints_CPP, regression) { CV_ProjectPointsTest_CPP test; test.safe_run(); }
1873 TEST(Calib3d_StereoCalibrate_C, regression) { CV_StereoCalibrationTest_C test; test.safe_run(); }
1874 TEST(Calib3d_StereoCalibrate_CPP, regression) { CV_StereoCalibrationTest_CPP test; test.safe_run(); }