Path: blob/master/modules/calib3d/test/test_cameracalibration.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#include "test_precomp.hpp"42#include "opencv2/calib3d/calib3d_c.h"4344namespace opencv_test { namespace {4546#if 047class CV_ProjectPointsTest : public cvtest::ArrayTest48{49public:50CV_ProjectPointsTest();5152protected:53int read_params( CvFileStorage* fs );54void fill_array( int test_case_idx, int i, int j, Mat& arr );55int prepare_test_case( int test_case_idx );56void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );57double get_success_error_level( int test_case_idx, int i, int j );58void run_func();59void prepare_to_validation( int );6061bool calc_jacobians;62};636465CV_ProjectPointsTest::CV_ProjectPointsTest()66: cvtest::ArrayTest( "3d-ProjectPoints", "cvProjectPoints2", "" )67{68test_array[INPUT].push_back(NULL); // rotation vector69test_array[OUTPUT].push_back(NULL); // rotation matrix70test_array[OUTPUT].push_back(NULL); // jacobian (J)71test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)72test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)73test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)74test_array[REF_OUTPUT].push_back(NULL);75test_array[REF_OUTPUT].push_back(NULL);76test_array[REF_OUTPUT].push_back(NULL);77test_array[REF_OUTPUT].push_back(NULL);78test_array[REF_OUTPUT].push_back(NULL);7980element_wise_relative_error = false;81calc_jacobians = false;82}838485int CV_ProjectPointsTest::read_params( CvFileStorage* fs )86{87int code = cvtest::ArrayTest::read_params( fs );88return code;89}909192void CV_ProjectPointsTest::get_test_array_types_and_sizes(93int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )94{95RNG& rng = ts->get_rng();96int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;97int i, code;9899code = cvtest::randInt(rng) % 3;100types[INPUT][0] = CV_MAKETYPE(depth, 1);101102if( code == 0 )103{104sizes[INPUT][0] = cvSize(1,1);105types[INPUT][0] = CV_MAKETYPE(depth, 3);106}107else if( code == 1 )108sizes[INPUT][0] = cvSize(3,1);109else110sizes[INPUT][0] = cvSize(1,3);111112sizes[OUTPUT][0] = cvSize(3, 3);113types[OUTPUT][0] = CV_MAKETYPE(depth, 1);114115types[OUTPUT][1] = CV_MAKETYPE(depth, 1);116117if( cvtest::randInt(rng) % 2 )118sizes[OUTPUT][1] = cvSize(3,9);119else120sizes[OUTPUT][1] = cvSize(9,3);121122types[OUTPUT][2] = types[INPUT][0];123sizes[OUTPUT][2] = sizes[INPUT][0];124125types[OUTPUT][3] = types[OUTPUT][1];126sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);127128types[OUTPUT][4] = types[OUTPUT][1];129sizes[OUTPUT][4] = cvSize(3,3);130131calc_jacobians = 1;//cvtest::randInt(rng) % 3 != 0;132if( !calc_jacobians )133sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);134135for( i = 0; i < 5; i++ )136{137types[REF_OUTPUT][i] = types[OUTPUT][i];138sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];139}140}141142143double CV_ProjectPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )144{145return j == 4 ? 1e-2 : 1e-2;146}147148149void CV_ProjectPointsTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, CvMat* arr )150{151double r[3], theta0, theta1, f;152CvMat _r = cvMat( arr->rows, arr->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(arr->type)), r );153RNG& rng = ts->get_rng();154155r[0] = cvtest::randReal(rng)*CV_PI*2;156r[1] = cvtest::randReal(rng)*CV_PI*2;157r[2] = cvtest::randReal(rng)*CV_PI*2;158159theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);160theta1 = fmod(theta0, CV_PI*2);161162if( theta1 > CV_PI )163theta1 = -(CV_PI*2 - theta1);164165f = theta1/(theta0 ? theta0 : 1);166r[0] *= f;167r[1] *= f;168r[2] *= f;169170cvTsConvert( &_r, arr );171}172173174int CV_ProjectPointsTest::prepare_test_case( int test_case_idx )175{176int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );177return code;178}179180181void CV_ProjectPointsTest::run_func()182{183CvMat *v2m_jac = 0, *m2v_jac = 0;184if( calc_jacobians )185{186v2m_jac = &test_mat[OUTPUT][1];187m2v_jac = &test_mat[OUTPUT][3];188}189190cvProjectPoints2( &test_mat[INPUT][0], &test_mat[OUTPUT][0], v2m_jac );191cvProjectPoints2( &test_mat[OUTPUT][0], &test_mat[OUTPUT][2], m2v_jac );192}193194195void CV_ProjectPointsTest::prepare_to_validation( int /*test_case_idx*/ )196{197const CvMat* vec = &test_mat[INPUT][0];198CvMat* m = &test_mat[REF_OUTPUT][0];199CvMat* vec2 = &test_mat[REF_OUTPUT][2];200CvMat* v2m_jac = 0, *m2v_jac = 0;201double theta0, theta1;202203if( calc_jacobians )204{205v2m_jac = &test_mat[REF_OUTPUT][1];206m2v_jac = &test_mat[REF_OUTPUT][3];207}208209210cvTsProjectPoints( vec, m, v2m_jac );211cvTsProjectPoints( m, vec2, m2v_jac );212cvTsCopy( vec, vec2 );213214theta0 = cvtest::norm( cvarrtomat(vec2), 0, CV_L2 );215theta1 = fmod( theta0, CV_PI*2 );216217if( theta1 > CV_PI )218theta1 = -(CV_PI*2 - theta1);219cvScale( vec2, vec2, theta1/(theta0 ? theta0 : 1) );220221if( calc_jacobians )222{223//cvInvert( v2m_jac, m2v_jac, CV_SVD );224if( cvtest::norm(cvarrtomat(&test_mat[OUTPUT][3]), 0, CV_C) < 1000 )225{226cvTsGEMM( &test_mat[OUTPUT][1], &test_mat[OUTPUT][3],2271, 0, 0, &test_mat[OUTPUT][4],228v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );229}230else231{232cvTsSetIdentity( &test_mat[OUTPUT][4], cvScalarAll(1.) );233cvTsCopy( &test_mat[REF_OUTPUT][2], &test_mat[OUTPUT][2] );234}235cvTsSetIdentity( &test_mat[REF_OUTPUT][4], cvScalarAll(1.) );236}237}238239240CV_ProjectPointsTest ProjectPoints_test;241242#endif243244// --------------------------------- CV_CameraCalibrationTest --------------------------------------------245246class CV_CameraCalibrationTest : public cvtest::BaseTest247{248public:249CV_CameraCalibrationTest();250~CV_CameraCalibrationTest();251void clear();252protected:253int compare(double* val, double* refVal, int len,254double eps, const char* paramName);255virtual void calibrate( int imageCount, int* pointCounts,256CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints,257int iFixedPoint, double* distortionCoeffs, double* cameraMatrix, double* translationVectors,258double* rotationMatrices, double* newObjPoints, double *stdDevs, double* perViewErrors,259int flags ) = 0;260virtual void project( int pointCount, CvPoint3D64f* objectPoints,261double* rotationMatrix, double* translationVector,262double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints ) = 0;263264void run(int);265};266267CV_CameraCalibrationTest::CV_CameraCalibrationTest()268{269}270271CV_CameraCalibrationTest::~CV_CameraCalibrationTest()272{273clear();274}275276void CV_CameraCalibrationTest::clear()277{278cvtest::BaseTest::clear();279}280281int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len,282double eps, const char* param_name )283{284return cvtest::cmpEps2_64f( ts, val, ref_val, len, eps, param_name );285}286287void CV_CameraCalibrationTest::run( int start_from )288{289int code = cvtest::TS::OK;290cv::String filepath;291cv::String filename;292293Size imageSize;294Size etalonSize;295int numImages;296297CvPoint2D64f* imagePoints;298CvPoint3D64f* objectPoints;299CvPoint2D64f* reprojectPoints;300301double* transVects;302double* rotMatrs;303double* newObjPoints;304double* stdDevs;305double* perViewErrors;306307double* goodTransVects;308double* goodRotMatrs;309double* goodObjPoints;310double* goodPerViewErrors;311double* goodStdDevs;312313double cameraMatrix[3*3];314double distortion[5]={0,0,0,0,0};315316double goodDistortion[4];317318int* numbers;319FILE* file = 0;320FILE* datafile = 0;321int i,j;322int currImage;323int currPoint;324325int calibFlags;326char i_dat_file[100];327int numPoints;328int numTests;329int currTest;330331imagePoints = 0;332objectPoints = 0;333reprojectPoints = 0;334numbers = 0;335336transVects = 0;337rotMatrs = 0;338goodTransVects = 0;339goodRotMatrs = 0;340int progress = 0;341int values_read = -1;342343filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() );344filename = cv::format("%sdatafiles.txt", filepath.c_str() );345datafile = fopen( filename.c_str(), "r" );346if( datafile == 0 )347{348ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename.c_str() );349code = cvtest::TS::FAIL_MISSING_TEST_DATA;350goto _exit_;351}352353values_read = fscanf(datafile,"%d",&numTests);354CV_Assert(values_read == 1);355356for( currTest = start_from; currTest < numTests; currTest++ )357{358values_read = fscanf(datafile,"%s",i_dat_file);359CV_Assert(values_read == 1);360filename = cv::format("%s%s", filepath.c_str(), i_dat_file);361file = fopen(filename.c_str(),"r");362363ts->update_context( this, currTest, true );364365if( file == 0 )366{367ts->printf( cvtest::TS::LOG,368"Can't open current test file: %s\n",filename.c_str());369if( numTests == 1 )370{371code = cvtest::TS::FAIL_MISSING_TEST_DATA;372goto _exit_;373}374continue; // if there is more than one test, just skip the test375}376377values_read = fscanf(file,"%d %d\n",&(imageSize.width),&(imageSize.height));378CV_Assert(values_read == 2);379if( imageSize.width <= 0 || imageSize.height <= 0 )380{381ts->printf( cvtest::TS::LOG, "Image size in test file is incorrect\n" );382code = cvtest::TS::FAIL_INVALID_TEST_DATA;383goto _exit_;384}385386/* Read etalon size */387values_read = fscanf(file,"%d %d\n",&(etalonSize.width),&(etalonSize.height));388CV_Assert(values_read == 2);389if( etalonSize.width <= 0 || etalonSize.height <= 0 )390{391ts->printf( cvtest::TS::LOG, "Pattern size in test file is incorrect\n" );392code = cvtest::TS::FAIL_INVALID_TEST_DATA;393goto _exit_;394}395396numPoints = etalonSize.width * etalonSize.height;397398/* Read number of images */399values_read = fscanf(file,"%d\n",&numImages);400CV_Assert(values_read == 1);401if( numImages <=0 )402{403ts->printf( cvtest::TS::LOG, "Number of images in test file is incorrect\n");404code = cvtest::TS::FAIL_INVALID_TEST_DATA;405goto _exit_;406}407408/* Read calibration flags */409values_read = fscanf(file,"%d\n",&calibFlags);410CV_Assert(values_read == 1);411412/* Read index of the fixed point */413int iFixedPoint;414values_read = fscanf(file,"%d\n",&iFixedPoint);415CV_Assert(values_read == 1);416417/* Need to allocate memory */418imagePoints = (CvPoint2D64f*)cvAlloc( numPoints *419numImages * sizeof(CvPoint2D64f));420421objectPoints = (CvPoint3D64f*)cvAlloc( numPoints *422numImages * sizeof(CvPoint3D64f));423424reprojectPoints = (CvPoint2D64f*)cvAlloc( numPoints *425numImages * sizeof(CvPoint2D64f));426427/* Alloc memory for numbers */428numbers = (int*)cvAlloc( numImages * sizeof(int));429430/* Fill it by numbers of points of each image*/431for( currImage = 0; currImage < numImages; currImage++ )432{433numbers[currImage] = etalonSize.width * etalonSize.height;434}435436/* Allocate memory for translate vectors and rotmatrixs*/437transVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double));438rotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double));439newObjPoints = (double*)cvAlloc(3 * numbers[0] * sizeof(double));440stdDevs = (double*)cvAlloc((CV_CALIB_NINTRINSIC + 6*numImages + 3*numbers[0])441* sizeof(double));442perViewErrors = (double*)cvAlloc(numImages * sizeof(double));443444goodTransVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double));445goodRotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double));446goodObjPoints = (double*)cvAlloc(3 * numbers[0] * sizeof(double));447goodPerViewErrors = (double*)cvAlloc(numImages * sizeof(double));448goodStdDevs = (double*)cvAlloc((CV_CALIB_NINTRINSIC + 6*numImages + 3*numbers[0])449* sizeof(double));450451/* Read object points */452i = 0;/* shift for current point */453for( currImage = 0; currImage < numImages; currImage++ )454{455for( currPoint = 0; currPoint < numPoints; currPoint++ )456{457double x,y,z;458values_read = fscanf(file,"%lf %lf %lf\n",&x,&y,&z);459CV_Assert(values_read == 3);460461(objectPoints+i)->x = x;462(objectPoints+i)->y = y;463(objectPoints+i)->z = z;464i++;465}466}467468/* Read image points */469i = 0;/* shift for current point */470for( currImage = 0; currImage < numImages; currImage++ )471{472for( currPoint = 0; currPoint < numPoints; currPoint++ )473{474double x,y;475values_read = fscanf(file,"%lf %lf\n",&x,&y);476CV_Assert(values_read == 2);477478(imagePoints+i)->x = x;479(imagePoints+i)->y = y;480i++;481}482}483484/* Read good data computed before */485486/* Focal lengths */487double goodFcx,goodFcy;488values_read = fscanf(file,"%lf %lf",&goodFcx,&goodFcy);489CV_Assert(values_read == 2);490491/* Principal points */492double goodCx,goodCy;493values_read = fscanf(file,"%lf %lf",&goodCx,&goodCy);494CV_Assert(values_read == 2);495496/* Read distortion */497498values_read = fscanf(file,"%lf",goodDistortion+0); CV_Assert(values_read == 1);499values_read = fscanf(file,"%lf",goodDistortion+1); CV_Assert(values_read == 1);500values_read = fscanf(file,"%lf",goodDistortion+2); CV_Assert(values_read == 1);501values_read = fscanf(file,"%lf",goodDistortion+3); CV_Assert(values_read == 1);502503/* Read good Rot matrices */504for( currImage = 0; currImage < numImages; currImage++ )505{506for( i = 0; i < 3; i++ )507for( j = 0; j < 3; j++ )508{509values_read = fscanf(file, "%lf", goodRotMatrs + currImage * 9 + j * 3 + i);510CV_Assert(values_read == 1);511}512}513514/* Read good Trans vectors */515for( currImage = 0; currImage < numImages; currImage++ )516{517for( i = 0; i < 3; i++ )518{519values_read = fscanf(file, "%lf", goodTransVects + currImage * 3 + i);520CV_Assert(values_read == 1);521}522}523524bool releaseObject = iFixedPoint > 0 && iFixedPoint < numPoints - 1;525/* Read good refined 3D object points */526if( releaseObject )527{528for( i = 0; i < numbers[0]; i++ )529{530for( j = 0; j < 3; j++ )531{532values_read = fscanf(file, "%lf", goodObjPoints + i * 3 + j);533CV_Assert(values_read == 1);534}535}536}537538/* Read good stdDeviations */539for (i = 0; i < CV_CALIB_NINTRINSIC + numImages*6; i++)540{541values_read = fscanf(file, "%lf", goodStdDevs + i);542CV_Assert(values_read == 1);543}544if( releaseObject )545{546for( i = CV_CALIB_NINTRINSIC + numImages*6; i < CV_CALIB_NINTRINSIC + numImages*6547+ numbers[0]*3; i++ )548{549values_read = fscanf(file, "%lf", goodStdDevs + i);550CV_Assert(values_read == 1);551}552}553554memset( cameraMatrix, 0, 9*sizeof(cameraMatrix[0]) );555cameraMatrix[0] = cameraMatrix[4] = 807.;556cameraMatrix[2] = (imageSize.width - 1)*0.5;557cameraMatrix[5] = (imageSize.height - 1)*0.5;558cameraMatrix[8] = 1.;559560/* Now we can calibrate camera */561calibrate( numImages,562numbers,563cvSize(imageSize),564imagePoints,565objectPoints,566iFixedPoint,567distortion,568cameraMatrix,569transVects,570rotMatrs,571newObjPoints,572stdDevs,573perViewErrors,574calibFlags );575576/* ---- Reproject points to the image ---- */577for( currImage = 0; currImage < numImages; currImage++ )578{579int nPoints = etalonSize.width * etalonSize.height;580if( releaseObject )581{582memcpy( objectPoints + currImage * nPoints, newObjPoints,583nPoints * 3 * sizeof(double) );584}585project( nPoints,586objectPoints + currImage * nPoints,587rotMatrs + currImage * 9,588transVects + currImage * 3,589cameraMatrix,590distortion,591reprojectPoints + currImage * nPoints);592}593594/* ----- Compute reprojection error ----- */595i = 0;596double dx,dy;597double rx,ry;598double meanDx,meanDy;599double maxDx = 0.0;600double maxDy = 0.0;601602meanDx = 0;603meanDy = 0;604for( currImage = 0; currImage < numImages; currImage++ )605{606double imageMeanDx = 0;607double imageMeanDy = 0;608for( currPoint = 0; currPoint < etalonSize.width * etalonSize.height; currPoint++ )609{610rx = reprojectPoints[i].x;611ry = reprojectPoints[i].y;612dx = rx - imagePoints[i].x;613dy = ry - imagePoints[i].y;614615meanDx += dx;616meanDy += dy;617618imageMeanDx += dx*dx;619imageMeanDy += dy*dy;620621dx = fabs(dx);622dy = fabs(dy);623624if( dx > maxDx )625maxDx = dx;626627if( dy > maxDy )628maxDy = dy;629i++;630}631goodPerViewErrors[currImage] = sqrt( (imageMeanDx + imageMeanDy) /632(etalonSize.width * etalonSize.height));633634//only for c-version of test (it does not provides evaluation of perViewErrors635//and returns zeros)636if(perViewErrors[currImage] == 0.0)637perViewErrors[currImage] = goodPerViewErrors[currImage];638}639640meanDx /= numImages * etalonSize.width * etalonSize.height;641meanDy /= numImages * etalonSize.width * etalonSize.height;642643/* ========= Compare parameters ========= */644645/* ----- Compare focal lengths ----- */646code = compare(cameraMatrix+0,&goodFcx,1,0.1,"fx");647if( code < 0 )648goto _exit_;649650code = compare(cameraMatrix+4,&goodFcy,1,0.1,"fy");651if( code < 0 )652goto _exit_;653654/* ----- Compare principal points ----- */655code = compare(cameraMatrix+2,&goodCx,1,0.1,"cx");656if( code < 0 )657goto _exit_;658659code = compare(cameraMatrix+5,&goodCy,1,0.1,"cy");660if( code < 0 )661goto _exit_;662663/* ----- Compare distortion ----- */664code = compare(distortion,goodDistortion,4,0.1,"[k1,k2,p1,p2]");665if( code < 0 )666goto _exit_;667668/* ----- Compare rot matrixs ----- */669code = compare(rotMatrs,goodRotMatrs, 9*numImages,0.05,"rotation matrices");670if( code < 0 )671goto _exit_;672673/* ----- Compare rot matrixs ----- */674code = compare(transVects,goodTransVects, 3*numImages,0.1,"translation vectors");675if( code < 0 )676goto _exit_;677678/* ----- Compare refined 3D object points ----- */679if( releaseObject )680{681code = compare(newObjPoints,goodObjPoints, 3*numbers[0],0.1,"refined 3D object points");682if( code < 0 )683goto _exit_;684}685686/* ----- Compare per view re-projection errors ----- */687code = compare(perViewErrors,goodPerViewErrors, numImages,0.1,"per view errors vector");688if( code < 0 )689goto _exit_;690691/* ----- Compare standard deviations of parameters ----- */692//only for c-version of test (it does not provides evaluation of stdDevs693//and returns zeros)694for ( i = 0; i < CV_CALIB_NINTRINSIC + 6*numImages + 3*numbers[0]; i++)695{696if(stdDevs[i] == 0.0)697stdDevs[i] = goodStdDevs[i];698}699code = compare(stdDevs,goodStdDevs, CV_CALIB_NINTRINSIC + 6*numImages + 3*numbers[0],.5,700"stdDevs vector");701if( code < 0 )702goto _exit_;703704if( maxDx > 1.0 )705{706ts->printf( cvtest::TS::LOG,707"Error in reprojection maxDx=%f > 1.0\n",maxDx);708code = cvtest::TS::FAIL_BAD_ACCURACY; goto _exit_;709}710711if( maxDy > 1.0 )712{713ts->printf( cvtest::TS::LOG,714"Error in reprojection maxDy=%f > 1.0\n",maxDy);715code = cvtest::TS::FAIL_BAD_ACCURACY; goto _exit_;716}717718progress = update_progress( progress, currTest, numTests, 0 );719720cvFree(&imagePoints);721cvFree(&objectPoints);722cvFree(&reprojectPoints);723cvFree(&numbers);724725cvFree(&transVects);726cvFree(&rotMatrs);727cvFree(&newObjPoints);728cvFree(&stdDevs);729cvFree(&perViewErrors);730cvFree(&goodTransVects);731cvFree(&goodRotMatrs);732cvFree(&goodObjPoints);733cvFree(&goodPerViewErrors);734cvFree(&goodStdDevs);735736fclose(file);737file = 0;738}739740_exit_:741742if( file )743fclose(file);744745if( datafile )746fclose(datafile);747748/* Free all allocated memory */749cvFree(&imagePoints);750cvFree(&objectPoints);751cvFree(&reprojectPoints);752cvFree(&numbers);753754cvFree(&transVects);755cvFree(&rotMatrs);756cvFree(&goodTransVects);757cvFree(&goodRotMatrs);758759if( code < 0 )760ts->set_failed_test_info( code );761}762763// --------------------------------- CV_CameraCalibrationTest_C --------------------------------------------764765class CV_CameraCalibrationTest_C : public CV_CameraCalibrationTest766{767public:768CV_CameraCalibrationTest_C(){}769protected:770virtual void calibrate( int imageCount, int* pointCounts,771CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, int iFixedPoint,772double* distortionCoeffs, double* cameraMatrix, double* translationVectors,773double* rotationMatrices, double* newObjPoints, double *stdDevs, double* perViewErrors,774int flags );775virtual void project( int pointCount, CvPoint3D64f* objectPoints,776double* rotationMatrix, double* translationVector,777double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints );778};779780void CV_CameraCalibrationTest_C::calibrate(int imageCount, int* pointCounts,781CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, int iFixedPoint,782double* distortionCoeffs, double* cameraMatrix, double* translationVectors,783double* rotationMatrices, double* newObjPoints, double *stdDevs, double *perViewErrors,784int flags )785{786int i, total = 0;787for( i = 0; i < imageCount; i++ )788{789perViewErrors[i] = 0.0;790total += pointCounts[i];791}792793for( i = 0; i < CV_CALIB_NINTRINSIC + imageCount*6 + pointCounts[0]*3; i++)794{795stdDevs[i] = 0.0;796}797798CvMat _objectPoints = cvMat(1, total, CV_64FC3, objectPoints);799CvMat _imagePoints = cvMat(1, total, CV_64FC2, imagePoints);800CvMat _pointCounts = cvMat(1, imageCount, CV_32S, pointCounts);801CvMat _cameraMatrix = cvMat(3, 3, CV_64F, cameraMatrix);802CvMat _distCoeffs = cvMat(4, 1, CV_64F, distortionCoeffs);803CvMat _rotationMatrices = cvMat(imageCount, 9, CV_64F, rotationMatrices);804CvMat _translationVectors = cvMat(imageCount, 3, CV_64F, translationVectors);805CvMat _newObjPoints = cvMat(1, pointCounts[0], CV_64FC3, newObjPoints);806807cvCalibrateCamera4(&_objectPoints, &_imagePoints, &_pointCounts, imageSize, iFixedPoint,808&_cameraMatrix, &_distCoeffs, &_rotationMatrices, &_translationVectors,809&_newObjPoints, flags);810}811812void CV_CameraCalibrationTest_C::project( int pointCount, CvPoint3D64f* objectPoints,813double* rotationMatrix, double* translationVector,814double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints )815{816CvMat _objectPoints = cvMat(1, pointCount, CV_64FC3, objectPoints);817CvMat _imagePoints = cvMat(1, pointCount, CV_64FC2, imagePoints);818CvMat _cameraMatrix = cvMat(3, 3, CV_64F, cameraMatrix);819CvMat _distCoeffs = cvMat(4, 1, CV_64F, distortion);820CvMat _rotationMatrix = cvMat(3, 3, CV_64F, rotationMatrix);821CvMat _translationVector = cvMat(1, 3, CV_64F, translationVector);822823cvProjectPoints2(&_objectPoints, &_rotationMatrix, &_translationVector, &_cameraMatrix, &_distCoeffs, &_imagePoints);824}825826// --------------------------------- CV_CameraCalibrationTest_CPP --------------------------------------------827828class CV_CameraCalibrationTest_CPP : public CV_CameraCalibrationTest829{830public:831CV_CameraCalibrationTest_CPP(){}832protected:833virtual void calibrate( int imageCount, int* pointCounts,834CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, int iFixedPoint,835double* distortionCoeffs, double* cameraMatrix, double* translationVectors,836double* rotationMatrices, double* newObjPoints, double *stdDevs, double* perViewErrors,837int flags );838virtual void project( int pointCount, CvPoint3D64f* objectPoints,839double* rotationMatrix, double* translationVector,840double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints );841};842843void CV_CameraCalibrationTest_CPP::calibrate(int imageCount, int* pointCounts,844CvSize _imageSize, CvPoint2D64f* _imagePoints, CvPoint3D64f* _objectPoints, int iFixedPoint,845double* _distortionCoeffs, double* _cameraMatrix, double* translationVectors,846double* rotationMatrices, double* newObjPoints, double *stdDevs, double *perViewErrors,847int flags )848{849vector<vector<Point3f> > objectPoints( imageCount );850vector<vector<Point2f> > imagePoints( imageCount );851Size imageSize = _imageSize;852Mat cameraMatrix, distCoeffs(1,4,CV_64F,Scalar::all(0));853vector<Mat> rvecs, tvecs;854Mat newObjMat;855Mat stdDevsMatInt, stdDevsMatExt;856Mat stdDevsMatObj;857Mat perViewErrorsMat;858859CvPoint3D64f* op = _objectPoints;860CvPoint2D64f* ip = _imagePoints;861vector<vector<Point3f> >::iterator objectPointsIt = objectPoints.begin();862vector<vector<Point2f> >::iterator imagePointsIt = imagePoints.begin();863for( int i = 0; i < imageCount; ++objectPointsIt, ++imagePointsIt, i++ )864{865int num = pointCounts[i];866objectPointsIt->resize( num );867imagePointsIt->resize( num );868vector<Point3f>::iterator oIt = objectPointsIt->begin();869vector<Point2f>::iterator iIt = imagePointsIt->begin();870for( int j = 0; j < num; ++oIt, ++iIt, j++, op++, ip++)871{872oIt->x = (float)op->x, oIt->y = (float)op->y, oIt->z = (float)op->z;873iIt->x = (float)ip->x, iIt->y = (float)ip->y;874}875}876877for( int i = CV_CALIB_NINTRINSIC + imageCount*6; i < CV_CALIB_NINTRINSIC + imageCount*6878+ pointCounts[0]*3; i++)879{880stdDevs[i] = 0.0;881}882883calibrateCameraRO( objectPoints,884imagePoints,885imageSize,886iFixedPoint,887cameraMatrix,888distCoeffs,889rvecs,890tvecs,891newObjMat,892stdDevsMatInt,893stdDevsMatExt,894stdDevsMatObj,895perViewErrorsMat,896flags );897898bool releaseObject = iFixedPoint > 0 && iFixedPoint < pointCounts[0] - 1;899if( releaseObject )900{901newObjMat.convertTo( newObjMat, CV_64F );902assert( newObjMat.total() * newObjMat.channels() == static_cast<size_t>(3*pointCounts[0]) );903memcpy( newObjPoints, newObjMat.ptr(), 3*pointCounts[0]*sizeof(double) );904}905906assert( stdDevsMatInt.type() == CV_64F );907assert( stdDevsMatInt.total() == static_cast<size_t>(CV_CALIB_NINTRINSIC) );908memcpy( stdDevs, stdDevsMatInt.ptr(), CV_CALIB_NINTRINSIC*sizeof(double) );909910assert( stdDevsMatExt.type() == CV_64F );911assert( stdDevsMatExt.total() == static_cast<size_t>(6*imageCount) );912memcpy( stdDevs + CV_CALIB_NINTRINSIC, stdDevsMatExt.ptr(), 6*imageCount*sizeof(double) );913914if( releaseObject )915{916assert( stdDevsMatObj.type() == CV_64F );917assert( stdDevsMatObj.total() == static_cast<size_t>(3*pointCounts[0]) );918memcpy( stdDevs + CV_CALIB_NINTRINSIC + 6*imageCount, stdDevsMatObj.ptr(),9193*pointCounts[0]*sizeof(double) );920}921922assert( perViewErrorsMat.type() == CV_64F);923assert( perViewErrorsMat.total() == static_cast<size_t>(imageCount) );924memcpy( perViewErrors, perViewErrorsMat.ptr(), imageCount*sizeof(double) );925926assert( cameraMatrix.type() == CV_64FC1 );927memcpy( _cameraMatrix, cameraMatrix.ptr(), 9*sizeof(double) );928929assert( cameraMatrix.type() == CV_64FC1 );930memcpy( _distortionCoeffs, distCoeffs.ptr(), 4*sizeof(double) );931932vector<Mat>::iterator rvecsIt = rvecs.begin();933vector<Mat>::iterator tvecsIt = tvecs.begin();934double *rm = rotationMatrices,935*tm = translationVectors;936assert( rvecsIt->type() == CV_64FC1 );937assert( tvecsIt->type() == CV_64FC1 );938for( int i = 0; i < imageCount; ++rvecsIt, ++tvecsIt, i++, rm+=9, tm+=3 )939{940Mat r9( 3, 3, CV_64FC1 );941cvtest::Rodrigues( *rvecsIt, r9 );942memcpy( rm, r9.ptr(), 9*sizeof(double) );943memcpy( tm, tvecsIt->ptr(), 3*sizeof(double) );944}945}946947void CV_CameraCalibrationTest_CPP::project( int pointCount, CvPoint3D64f* _objectPoints,948double* rotationMatrix, double* translationVector,949double* _cameraMatrix, double* distortion, CvPoint2D64f* _imagePoints )950{951Mat objectPoints( pointCount, 3, CV_64FC1, _objectPoints );952Mat rmat( 3, 3, CV_64FC1, rotationMatrix ),953rvec( 1, 3, CV_64FC1 ),954tvec( 1, 3, CV_64FC1, translationVector );955Mat cameraMatrix( 3, 3, CV_64FC1, _cameraMatrix );956Mat distCoeffs( 1, 4, CV_64FC1, distortion );957vector<Point2f> imagePoints;958cvtest::Rodrigues( rmat, rvec );959960objectPoints.convertTo( objectPoints, CV_32FC1 );961projectPoints( objectPoints, rvec, tvec,962cameraMatrix, distCoeffs, imagePoints );963vector<Point2f>::const_iterator it = imagePoints.begin();964for( int i = 0; it != imagePoints.end(); ++it, i++ )965{966_imagePoints[i] = cvPoint2D64f( it->x, it->y );967}968}969970971//----------------------------------------- CV_CalibrationMatrixValuesTest --------------------------------972973class CV_CalibrationMatrixValuesTest : public cvtest::BaseTest974{975public:976CV_CalibrationMatrixValuesTest() {}977protected:978void run(int);979virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,980double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,981Point2d& principalPoint, double& aspectRatio ) = 0;982};983984void CV_CalibrationMatrixValuesTest::run(int)985{986int code = cvtest::TS::OK;987const double fcMinVal = 1e-5;988const double fcMaxVal = 1000;989const double apertureMaxVal = 0.01;990991RNG rng = ts->get_rng();992993double fx, fy, cx, cy, nx, ny;994Mat cameraMatrix( 3, 3, CV_64FC1 );995cameraMatrix.setTo( Scalar(0) );996fx = cameraMatrix.at<double>(0,0) = rng.uniform( fcMinVal, fcMaxVal );997fy = cameraMatrix.at<double>(1,1) = rng.uniform( fcMinVal, fcMaxVal );998cx = cameraMatrix.at<double>(0,2) = rng.uniform( fcMinVal, fcMaxVal );999cy = cameraMatrix.at<double>(1,2) = rng.uniform( fcMinVal, fcMaxVal );1000cameraMatrix.at<double>(2,2) = 1;10011002Size imageSize( 600, 400 );10031004double apertureWidth = (double)rng * apertureMaxVal,1005apertureHeight = (double)rng * apertureMaxVal;10061007double fovx, fovy, focalLength, aspectRatio,1008goodFovx, goodFovy, goodFocalLength, goodAspectRatio;1009Point2d principalPoint, goodPrincipalPoint;101010111012calibMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,1013fovx, fovy, focalLength, principalPoint, aspectRatio );10141015// calculate calibration matrix values1016goodAspectRatio = fy / fx;10171018if( apertureWidth != 0.0 && apertureHeight != 0.0 )1019{1020nx = imageSize.width / apertureWidth;1021ny = imageSize.height / apertureHeight;1022}1023else1024{1025nx = 1.0;1026ny = goodAspectRatio;1027}10281029goodFovx = (atan2(cx, fx) + atan2(imageSize.width - cx, fx)) * 180.0 / CV_PI;1030goodFovy = (atan2(cy, fy) + atan2(imageSize.height - cy, fy)) * 180.0 / CV_PI;10311032goodFocalLength = fx / nx;10331034goodPrincipalPoint.x = cx / nx;1035goodPrincipalPoint.y = cy / ny;10361037// check results1038if( fabs(fovx - goodFovx) > FLT_EPSILON )1039{1040ts->printf( cvtest::TS::LOG, "bad fovx (real=%f, good = %f\n", fovx, goodFovx );1041code = cvtest::TS::FAIL_BAD_ACCURACY;1042goto _exit_;1043}1044if( fabs(fovy - goodFovy) > FLT_EPSILON )1045{1046ts->printf( cvtest::TS::LOG, "bad fovy (real=%f, good = %f\n", fovy, goodFovy );1047code = cvtest::TS::FAIL_BAD_ACCURACY;1048goto _exit_;1049}1050if( fabs(focalLength - goodFocalLength) > FLT_EPSILON )1051{1052ts->printf( cvtest::TS::LOG, "bad focalLength (real=%f, good = %f\n", focalLength, goodFocalLength );1053code = cvtest::TS::FAIL_BAD_ACCURACY;1054goto _exit_;1055}1056if( fabs(aspectRatio - goodAspectRatio) > FLT_EPSILON )1057{1058ts->printf( cvtest::TS::LOG, "bad aspectRatio (real=%f, good = %f\n", aspectRatio, goodAspectRatio );1059code = cvtest::TS::FAIL_BAD_ACCURACY;1060goto _exit_;1061}1062if( cv::norm(principalPoint - goodPrincipalPoint) > FLT_EPSILON ) // Point2d1063{1064ts->printf( cvtest::TS::LOG, "bad principalPoint\n" );1065code = cvtest::TS::FAIL_BAD_ACCURACY;1066goto _exit_;1067}10681069_exit_:1070RNG& _rng = ts->get_rng();1071_rng = rng;1072ts->set_failed_test_info( code );1073}10741075//----------------------------------------- CV_CalibrationMatrixValuesTest_C --------------------------------10761077class CV_CalibrationMatrixValuesTest_C : public CV_CalibrationMatrixValuesTest1078{1079public:1080CV_CalibrationMatrixValuesTest_C(){}1081protected:1082virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,1083double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,1084Point2d& principalPoint, double& aspectRatio );1085};10861087void CV_CalibrationMatrixValuesTest_C::calibMatrixValues( const Mat& _cameraMatrix, Size imageSize,1088double apertureWidth, double apertureHeight,1089double& fovx, double& fovy, double& focalLength,1090Point2d& principalPoint, double& aspectRatio )1091{1092CvMat cameraMatrix = cvMat(_cameraMatrix);1093CvPoint2D64f pp = {0, 0};1094cvCalibrationMatrixValues( &cameraMatrix, cvSize(imageSize), apertureWidth, apertureHeight,1095&fovx, &fovy, &focalLength, &pp, &aspectRatio );1096principalPoint.x = pp.x;1097principalPoint.y = pp.y;1098}109911001101//----------------------------------------- CV_CalibrationMatrixValuesTest_CPP --------------------------------11021103class CV_CalibrationMatrixValuesTest_CPP : public CV_CalibrationMatrixValuesTest1104{1105public:1106CV_CalibrationMatrixValuesTest_CPP() {}1107protected:1108virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,1109double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,1110Point2d& principalPoint, double& aspectRatio );1111};11121113void CV_CalibrationMatrixValuesTest_CPP::calibMatrixValues( const Mat& cameraMatrix, Size imageSize,1114double apertureWidth, double apertureHeight,1115double& fovx, double& fovy, double& focalLength,1116Point2d& principalPoint, double& aspectRatio )1117{1118calibrationMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,1119fovx, fovy, focalLength, principalPoint, aspectRatio );1120}112111221123//----------------------------------------- CV_ProjectPointsTest --------------------------------1124void calcdfdx( const vector<vector<Point2f> >& leftF, const vector<vector<Point2f> >& rightF, double eps, Mat& dfdx )1125{1126const int fdim = 2;1127CV_Assert( !leftF.empty() && !rightF.empty() && !leftF[0].empty() && !rightF[0].empty() );1128CV_Assert( leftF[0].size() == rightF[0].size() );1129CV_Assert( fabs(eps) > std::numeric_limits<double>::epsilon() );1130int fcount = (int)leftF[0].size(), xdim = (int)leftF.size();11311132dfdx.create( fcount*fdim, xdim, CV_64FC1 );11331134vector<vector<Point2f> >::const_iterator arrLeftIt = leftF.begin();1135vector<vector<Point2f> >::const_iterator arrRightIt = rightF.begin();1136for( int xi = 0; xi < xdim; xi++, ++arrLeftIt, ++arrRightIt )1137{1138CV_Assert( (int)arrLeftIt->size() == fcount );1139CV_Assert( (int)arrRightIt->size() == fcount );1140vector<Point2f>::const_iterator lIt = arrLeftIt->begin();1141vector<Point2f>::const_iterator rIt = arrRightIt->begin();1142for( int fi = 0; fi < dfdx.rows; fi+=fdim, ++lIt, ++rIt )1143{1144dfdx.at<double>(fi, xi ) = 0.5 * ((double)(rIt->x - lIt->x)) / eps;1145dfdx.at<double>(fi+1, xi ) = 0.5 * ((double)(rIt->y - lIt->y)) / eps;1146}1147}1148}11491150class CV_ProjectPointsTest : public cvtest::BaseTest1151{1152public:1153CV_ProjectPointsTest() {}1154protected:1155void run(int);1156virtual void project( const Mat& objectPoints,1157const Mat& rvec, const Mat& tvec,1158const Mat& cameraMatrix,1159const Mat& distCoeffs,1160vector<Point2f>& imagePoints,1161Mat& dpdrot, Mat& dpdt, Mat& dpdf,1162Mat& dpdc, Mat& dpddist,1163double aspectRatio=0 ) = 0;1164};11651166void CV_ProjectPointsTest::run(int)1167{1168//typedef float matType;11691170int code = cvtest::TS::OK;1171const int pointCount = 100;11721173const float zMinVal = 10.0f, zMaxVal = 100.0f,1174rMinVal = -0.3f, rMaxVal = 0.3f,1175tMinVal = -2.0f, tMaxVal = 2.0f;11761177const float imgPointErr = 1e-3f,1178dEps = 1e-3f;11791180double err;11811182Size imgSize( 600, 800 );1183Mat_<float> objPoints( pointCount, 3), rvec( 1, 3), rmat, tvec( 1, 3 ), cameraMatrix( 3, 3 ), distCoeffs( 1, 4 ),1184leftRvec, rightRvec, leftTvec, rightTvec, leftCameraMatrix, rightCameraMatrix, leftDistCoeffs, rightDistCoeffs;11851186RNG rng = ts->get_rng();11871188// generate data1189cameraMatrix << 300.f, 0.f, imgSize.width/2.f,11900.f, 300.f, imgSize.height/2.f,11910.f, 0.f, 1.f;1192distCoeffs << 0.1, 0.01, 0.001, 0.001;11931194rvec(0,0) = rng.uniform( rMinVal, rMaxVal );1195rvec(0,1) = rng.uniform( rMinVal, rMaxVal );1196rvec(0,2) = rng.uniform( rMinVal, rMaxVal );1197rmat = cv::Mat_<float>::zeros(3, 3);1198cvtest::Rodrigues( rvec, rmat );11991200tvec(0,0) = rng.uniform( tMinVal, tMaxVal );1201tvec(0,1) = rng.uniform( tMinVal, tMaxVal );1202tvec(0,2) = rng.uniform( tMinVal, tMaxVal );12031204for( int y = 0; y < objPoints.rows; y++ )1205{1206Mat point(1, 3, CV_32FC1, objPoints.ptr(y) );1207float z = rng.uniform( zMinVal, zMaxVal );1208point.at<float>(0,2) = z;1209point.at<float>(0,0) = (rng.uniform(2.f,(float)(imgSize.width-2)) - cameraMatrix(0,2)) / cameraMatrix(0,0) * z;1210point.at<float>(0,1) = (rng.uniform(2.f,(float)(imgSize.height-2)) - cameraMatrix(1,2)) / cameraMatrix(1,1) * z;1211point = (point - tvec) * rmat;1212}12131214vector<Point2f> imgPoints;1215vector<vector<Point2f> > leftImgPoints;1216vector<vector<Point2f> > rightImgPoints;1217Mat dpdrot, dpdt, dpdf, dpdc, dpddist,1218valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist;12191220project( objPoints, rvec, tvec, cameraMatrix, distCoeffs,1221imgPoints, dpdrot, dpdt, dpdf, dpdc, dpddist, 0 );12221223// calculate and check image points1224assert( (int)imgPoints.size() == pointCount );1225vector<Point2f>::const_iterator it = imgPoints.begin();1226for( int i = 0; i < pointCount; i++, ++it )1227{1228Point3d p( objPoints(i,0), objPoints(i,1), objPoints(i,2) );1229double z = p.x*rmat(2,0) + p.y*rmat(2,1) + p.z*rmat(2,2) + tvec(0,2),1230x = (p.x*rmat(0,0) + p.y*rmat(0,1) + p.z*rmat(0,2) + tvec(0,0)) / z,1231y = (p.x*rmat(1,0) + p.y*rmat(1,1) + p.z*rmat(1,2) + tvec(0,1)) / z,1232r2 = x*x + y*y,1233r4 = r2*r2;1234Point2f validImgPoint;1235double a1 = 2*x*y,1236a2 = r2 + 2*x*x,1237a3 = r2 + 2*y*y,1238cdist = 1+distCoeffs(0,0)*r2+distCoeffs(0,1)*r4;1239validImgPoint.x = static_cast<float>((double)cameraMatrix(0,0)*(x*cdist + (double)distCoeffs(0,2)*a1 + (double)distCoeffs(0,3)*a2)1240+ (double)cameraMatrix(0,2));1241validImgPoint.y = static_cast<float>((double)cameraMatrix(1,1)*(y*cdist + (double)distCoeffs(0,2)*a3 + distCoeffs(0,3)*a1)1242+ (double)cameraMatrix(1,2));12431244if( fabs(it->x - validImgPoint.x) > imgPointErr ||1245fabs(it->y - validImgPoint.y) > imgPointErr )1246{1247ts->printf( cvtest::TS::LOG, "bad image point\n" );1248code = cvtest::TS::FAIL_BAD_ACCURACY;1249goto _exit_;1250}1251}12521253// check derivatives1254// 1. rotation1255leftImgPoints.resize(3);1256rightImgPoints.resize(3);1257for( int i = 0; i < 3; i++ )1258{1259rvec.copyTo( leftRvec ); leftRvec(0,i) -= dEps;1260project( objPoints, leftRvec, tvec, cameraMatrix, distCoeffs,1261leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1262rvec.copyTo( rightRvec ); rightRvec(0,i) += dEps;1263project( objPoints, rightRvec, tvec, cameraMatrix, distCoeffs,1264rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1265}1266calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdrot );1267err = cvtest::norm( dpdrot, valDpdrot, NORM_INF );1268if( err > 3 )1269{1270ts->printf( cvtest::TS::LOG, "bad dpdrot: too big difference = %g\n", err );1271code = cvtest::TS::FAIL_BAD_ACCURACY;1272}12731274// 2. translation1275for( int i = 0; i < 3; i++ )1276{1277tvec.copyTo( leftTvec ); leftTvec(0,i) -= dEps;1278project( objPoints, rvec, leftTvec, cameraMatrix, distCoeffs,1279leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1280tvec.copyTo( rightTvec ); rightTvec(0,i) += dEps;1281project( objPoints, rvec, rightTvec, cameraMatrix, distCoeffs,1282rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1283}1284calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdt );1285if( cvtest::norm( dpdt, valDpdt, NORM_INF ) > 0.2 )1286{1287ts->printf( cvtest::TS::LOG, "bad dpdtvec\n" );1288code = cvtest::TS::FAIL_BAD_ACCURACY;1289}12901291// 3. camera matrix1292// 3.1. focus1293leftImgPoints.resize(2);1294rightImgPoints.resize(2);1295cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,0) -= dEps;1296project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,1297leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1298cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,1) -= dEps;1299project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,1300leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1301cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,0) += dEps;1302project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,1303rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1304cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,1) += dEps;1305project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,1306rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1307calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdf );1308if ( cvtest::norm( dpdf, valDpdf, NORM_L2 ) > 0.2 )1309{1310ts->printf( cvtest::TS::LOG, "bad dpdf\n" );1311code = cvtest::TS::FAIL_BAD_ACCURACY;1312}1313// 3.2. principal point1314leftImgPoints.resize(2);1315rightImgPoints.resize(2);1316cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,2) -= dEps;1317project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,1318leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1319cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,2) -= dEps;1320project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,1321leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1322cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,2) += dEps;1323project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,1324rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1325cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,2) += dEps;1326project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,1327rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1328calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdc );1329if ( cvtest::norm( dpdc, valDpdc, NORM_L2 ) > 0.2 )1330{1331ts->printf( cvtest::TS::LOG, "bad dpdc\n" );1332code = cvtest::TS::FAIL_BAD_ACCURACY;1333}13341335// 4. distortion1336leftImgPoints.resize(distCoeffs.cols);1337rightImgPoints.resize(distCoeffs.cols);1338for( int i = 0; i < distCoeffs.cols; i++ )1339{1340distCoeffs.copyTo( leftDistCoeffs ); leftDistCoeffs(0,i) -= dEps;1341project( objPoints, rvec, tvec, cameraMatrix, leftDistCoeffs,1342leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1343distCoeffs.copyTo( rightDistCoeffs ); rightDistCoeffs(0,i) += dEps;1344project( objPoints, rvec, tvec, cameraMatrix, rightDistCoeffs,1345rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );1346}1347calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpddist );1348if( cvtest::norm( dpddist, valDpddist, NORM_L2 ) > 0.3 )1349{1350ts->printf( cvtest::TS::LOG, "bad dpddist\n" );1351code = cvtest::TS::FAIL_BAD_ACCURACY;1352}13531354_exit_:1355RNG& _rng = ts->get_rng();1356_rng = rng;1357ts->set_failed_test_info( code );1358}13591360//----------------------------------------- CV_ProjectPointsTest_C --------------------------------1361class CV_ProjectPointsTest_C : public CV_ProjectPointsTest1362{1363public:1364CV_ProjectPointsTest_C() {}1365protected:1366virtual void project( const Mat& objectPoints,1367const Mat& rvec, const Mat& tvec,1368const Mat& cameraMatrix,1369const Mat& distCoeffs,1370vector<Point2f>& imagePoints,1371Mat& dpdrot, Mat& dpdt, Mat& dpdf,1372Mat& dpdc, Mat& dpddist,1373double aspectRatio=0 );1374};13751376void CV_ProjectPointsTest_C::project( const Mat& opoints, const Mat& rvec, const Mat& tvec,1377const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& ipoints,1378Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)1379{1380int npoints = opoints.cols*opoints.rows*opoints.channels()/3;1381ipoints.resize(npoints);1382dpdrot.create(npoints*2, 3, CV_64F);1383dpdt.create(npoints*2, 3, CV_64F);1384dpdf.create(npoints*2, 2, CV_64F);1385dpdc.create(npoints*2, 2, CV_64F);1386dpddist.create(npoints*2, distCoeffs.rows + distCoeffs.cols - 1, CV_64F);1387Mat imagePoints(ipoints);1388CvMat _objectPoints = cvMat(opoints), _imagePoints = cvMat(imagePoints);1389CvMat _rvec = cvMat(rvec), _tvec = cvMat(tvec), _cameraMatrix = cvMat(cameraMatrix), _distCoeffs = cvMat(distCoeffs);1390CvMat _dpdrot = cvMat(dpdrot), _dpdt = cvMat(dpdt), _dpdf = cvMat(dpdf), _dpdc = cvMat(dpdc), _dpddist = cvMat(dpddist);13911392cvProjectPoints2( &_objectPoints, &_rvec, &_tvec, &_cameraMatrix, &_distCoeffs,1393&_imagePoints, &_dpdrot, &_dpdt, &_dpdf, &_dpdc, &_dpddist, aspectRatio );1394}139513961397//----------------------------------------- CV_ProjectPointsTest_CPP --------------------------------1398class CV_ProjectPointsTest_CPP : public CV_ProjectPointsTest1399{1400public:1401CV_ProjectPointsTest_CPP() {}1402protected:1403virtual void project( const Mat& objectPoints,1404const Mat& rvec, const Mat& tvec,1405const Mat& cameraMatrix,1406const Mat& distCoeffs,1407vector<Point2f>& imagePoints,1408Mat& dpdrot, Mat& dpdt, Mat& dpdf,1409Mat& dpdc, Mat& dpddist,1410double aspectRatio=0 );1411};14121413void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec, const Mat& tvec,1414const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& imagePoints,1415Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)1416{1417Mat J;1418projectPoints( objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, J, aspectRatio);1419J.colRange(0, 3).copyTo(dpdrot);1420J.colRange(3, 6).copyTo(dpdt);1421J.colRange(6, 8).copyTo(dpdf);1422J.colRange(8, 10).copyTo(dpdc);1423J.colRange(10, J.cols).copyTo(dpddist);1424}14251426///////////////////////////////// Stereo Calibration /////////////////////////////////////14271428class CV_StereoCalibrationCornerTest : public cvtest::BaseTest1429{1430public:1431CV_StereoCalibrationCornerTest();1432~CV_StereoCalibrationCornerTest();1433void clear();1434protected:1435void run(int);1436};14371438CV_StereoCalibrationCornerTest::CV_StereoCalibrationCornerTest()1439{1440}144114421443CV_StereoCalibrationCornerTest::~CV_StereoCalibrationCornerTest()1444{1445clear();1446}14471448void CV_StereoCalibrationCornerTest::clear()1449{1450cvtest::BaseTest::clear();1451}14521453static bool resizeCameraMatrix(const Mat &in_cm, Mat &dst_cm, double scale)1454{1455if (in_cm.empty() || in_cm.cols != 3 || in_cm.rows != 3 || in_cm.type() != CV_64FC1)1456return false;1457dst_cm = in_cm * scale;1458dst_cm.at<double>(2, 2) = 1.0;1459return true;1460}14611462// see https://github.com/opencv/opencv/pull/6836 for details1463void CV_StereoCalibrationCornerTest::run(int)1464{1465const Matx33d M1(906.7857732303256, 0.0, 1026.456125870669,14660.0, 906.7857732303256, 540.0531577669913,14670.0, 0.0, 1.0);1468const Matx33d M2(906.782205162265, 0.0, 1014.619997352785,14690.0, 906.782205162265, 561.9990018887295,14700.0, 0.0, 1.0);1471const Matx<double, 5, 1> D1(0.0064836857220181504, 0.033880363848984636, 0.0, 0.0, -0.042996356352306114);1472const Matx<double, 5, 1> D2(0.023754068600491646, -0.02364619610835259, 0.0, 0.0, 0.0015014971456262652);14731474const Size imageSize(2048, 1088);1475const double scale = 0.25;14761477const Matx33d Rot(0.999788461750194, -0.015696495349844446, -0.013291041528534329,14780.015233019205877604, 0.999296086451901, -0.034282455101525826,14790.01381980018141639, 0.03407274036010432, 0.9993238021218641);1480const Matx31d T(-1.552005597952028, 0.0019508251875105093, -0.023335501616116062);14811482// generate camera matrices for resized image rectification.1483Mat srcM1(M1), srcM2(M2);1484Mat rszM1, rszM2;1485resizeCameraMatrix(srcM1, rszM1, scale);1486resizeCameraMatrix(srcM2, rszM2, scale);1487Size rszImageSize(cvRound(scale * imageSize.width), cvRound(scale * imageSize.height));1488Size srcImageSize = imageSize;1489// apply stereoRectify1490Mat srcR[2], srcP[2], srcQ;1491Mat rszR[2], rszP[2], rszQ;1492stereoRectify(srcM1, D1, srcM2, D2, srcImageSize, Rot, T,1493srcR[0], srcR[1], srcP[0], srcP[1], srcQ,1494CALIB_ZERO_DISPARITY, 0);1495stereoRectify(rszM1, D1, rszM2, D2, rszImageSize, Rot, T,1496rszR[0], rszR[1], rszP[0], rszP[1], rszQ,1497CALIB_ZERO_DISPARITY, 0);1498// generate remap maps1499Mat srcRmap[2], rszRmap[2];1500initUndistortRectifyMap(srcM1, D1, srcR[0], srcP[0], srcImageSize, CV_32FC2, srcRmap[0], srcRmap[1]);1501initUndistortRectifyMap(rszM1, D1, rszR[0], rszP[0], rszImageSize, CV_32FC2, rszRmap[0], rszRmap[1]);15021503// generate source image1504// it's an artificial pattern with white rect in the center1505Mat image(imageSize, CV_8UC3);1506image.setTo(0);1507image(cv::Rect(imageSize.width / 3, imageSize.height / 3, imageSize.width / 3, imageSize.height / 3)).setTo(255);15081509// perform remap-resize1510Mat src_result;1511remap(image, src_result, srcRmap[0], srcRmap[1], INTER_LINEAR);1512resize(src_result, src_result, Size(), scale, scale, INTER_LINEAR_EXACT);1513// perform resize-remap1514Mat rsz_result;1515resize(image, rsz_result, Size(), scale, scale, INTER_LINEAR_EXACT);1516remap(rsz_result, rsz_result, rszRmap[0], rszRmap[1], INTER_LINEAR);15171518// modifying the camera matrix with resizeCameraMatrix must yield the same1519// result as calibrating the downscaled images1520int cnz = countNonZero((cv::Mat(src_result - rsz_result) != 0)(1521cv::Rect(src_result.cols / 3, src_result.rows / 3,1522(int)(src_result.cols / 3.1), int(src_result.rows / 3.1))));1523if (cnz)1524{1525ts->printf( cvtest::TS::LOG, "The camera matrix is wrong for downscaled image\n");1526ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );1527}1528}15291530class CV_StereoCalibrationTest : public cvtest::BaseTest1531{1532public:1533CV_StereoCalibrationTest();1534~CV_StereoCalibrationTest();1535void clear();1536protected:1537bool checkPandROI( int test_case_idx,1538const Mat& M, const Mat& D, const Mat& R,1539const Mat& P, Size imgsize, Rect roi );15401541// covers of tested functions1542virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,1543const vector<vector<Point2f> >& imagePoints1,1544const vector<vector<Point2f> >& imagePoints2,1545Mat& cameraMatrix1, Mat& distCoeffs1,1546Mat& cameraMatrix2, Mat& distCoeffs2,1547Size imageSize, Mat& R, Mat& T,1548Mat& E, Mat& F, TermCriteria criteria, int flags ) = 0;1549virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,1550const Mat& cameraMatrix2, const Mat& distCoeffs2,1551Size imageSize, const Mat& R, const Mat& T,1552Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,1553double alpha, Size newImageSize,1554Rect* validPixROI1, Rect* validPixROI2, int flags ) = 0;1555virtual bool rectifyUncalibrated( const Mat& points1,1556const Mat& points2, const Mat& F, Size imgSize,1557Mat& H1, Mat& H2, double threshold=5 ) = 0;1558virtual void triangulate( const Mat& P1, const Mat& P2,1559const Mat &points1, const Mat &points2,1560Mat &points4D ) = 0;1561virtual void correct( const Mat& F,1562const Mat &points1, const Mat &points2,1563Mat &newPoints1, Mat &newPoints2 ) = 0;15641565void run(int);1566};156715681569CV_StereoCalibrationTest::CV_StereoCalibrationTest()1570{1571}157215731574CV_StereoCalibrationTest::~CV_StereoCalibrationTest()1575{1576clear();1577}15781579void CV_StereoCalibrationTest::clear()1580{1581cvtest::BaseTest::clear();1582}15831584bool CV_StereoCalibrationTest::checkPandROI( int test_case_idx, const Mat& M, const Mat& D, const Mat& R,1585const Mat& P, Size imgsize, Rect roi )1586{1587const double eps = 0.05;1588const int N = 21;1589int x, y, k;1590vector<Point2f> pts, upts;15911592// step 1. check that all the original points belong to the destination image1593for( y = 0; y < N; y++ )1594for( x = 0; x < N; x++ )1595pts.push_back(Point2f((float)x*imgsize.width/(N-1), (float)y*imgsize.height/(N-1)));15961597undistortPoints(Mat(pts), upts, M, D, R, P );1598for( k = 0; k < N*N; k++ )1599if( upts[k].x < -imgsize.width*eps || upts[k].x > imgsize.width*(1+eps) ||1600upts[k].y < -imgsize.height*eps || upts[k].y > imgsize.height*(1+eps) )1601{1602ts->printf(cvtest::TS::LOG, "Test #%d. The point (%g, %g) was mapped to (%g, %g) which is out of image\n",1603test_case_idx, pts[k].x, pts[k].y, upts[k].x, upts[k].y);1604return false;1605}16061607// step 2. check that all the points inside ROI belong to the original source image1608Mat temp(imgsize, CV_8U), utemp, map1, map2;1609temp = Scalar::all(1);1610initUndistortRectifyMap(M, D, R, P, imgsize, CV_16SC2, map1, map2);1611remap(temp, utemp, map1, map2, INTER_LINEAR);16121613if(roi.x < 0 || roi.y < 0 || roi.x + roi.width > imgsize.width || roi.y + roi.height > imgsize.height)1614{1615ts->printf(cvtest::TS::LOG, "Test #%d. The ROI=(%d, %d, %d, %d) is outside of the imge rectangle\n",1616test_case_idx, roi.x, roi.y, roi.width, roi.height);1617return false;1618}1619double s = sum(utemp(roi))[0];1620if( s > roi.area() || roi.area() - s > roi.area()*(1-eps) )1621{1622ts->printf(cvtest::TS::LOG, "Test #%d. The ratio of black pixels inside the valid ROI (~%g%%) is too large\n",1623test_case_idx, s*100./roi.area());1624return false;1625}16261627return true;1628}16291630void CV_StereoCalibrationTest::run( int )1631{1632const int ntests = 1;1633const double maxReprojErr = 2;1634const double maxScanlineDistErr_c = 3;1635const double maxScanlineDistErr_uc = 4;1636FILE* f = 0;16371638for(int testcase = 1; testcase <= ntests; testcase++)1639{1640cv::String filepath;1641char buf[1000];1642filepath = cv::format("%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase );1643f = fopen(filepath.c_str(), "rt");1644Size patternSize;1645vector<string> imglist;16461647if( !f || !fgets(buf, sizeof(buf)-3, f) || sscanf(buf, "%d%d", &patternSize.width, &patternSize.height) != 2 )1648{1649ts->printf( cvtest::TS::LOG, "The file %s can not be opened or has invalid content\n", filepath.c_str() );1650ts->set_failed_test_info( f ? cvtest::TS::FAIL_INVALID_TEST_DATA : cvtest::TS::FAIL_MISSING_TEST_DATA );1651if (f)1652fclose(f);1653return;1654}16551656for(;;)1657{1658if( !fgets( buf, sizeof(buf)-3, f ))1659break;1660size_t len = strlen(buf);1661while( len > 0 && isspace(buf[len-1]))1662buf[--len] = '\0';1663if( buf[0] == '#')1664continue;1665filepath = cv::format("%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf );1666imglist.push_back(string(filepath));1667}1668fclose(f);16691670if( imglist.size() == 0 || imglist.size() % 2 != 0 )1671{1672ts->printf( cvtest::TS::LOG, "The number of images is 0 or an odd number in the case #%d\n", testcase );1673ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );1674return;1675}16761677int nframes = (int)(imglist.size()/2);1678int npoints = patternSize.width*patternSize.height;1679vector<vector<Point3f> > objpt(nframes);1680vector<vector<Point2f> > imgpt1(nframes);1681vector<vector<Point2f> > imgpt2(nframes);1682Size imgsize;1683int total = 0;16841685for( int i = 0; i < nframes; i++ )1686{1687Mat left = imread(imglist[i*2]);1688Mat right = imread(imglist[i*2+1]);1689if(left.empty() || right.empty())1690{1691ts->printf( cvtest::TS::LOG, "Can not load images %s and %s, testcase %d\n",1692imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase );1693ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );1694return;1695}1696imgsize = left.size();1697bool found1 = findChessboardCorners(left, patternSize, imgpt1[i]);1698bool found2 = findChessboardCorners(right, patternSize, imgpt2[i]);1699if(!found1 || !found2)1700{1701ts->printf( cvtest::TS::LOG, "The function could not detect boards (%d x %d) on the images %s and %s, testcase %d\n",1702patternSize.width, patternSize.height,1703imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase );1704ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );1705return;1706}1707total += (int)imgpt1[i].size();1708for( int j = 0; j < npoints; j++ )1709objpt[i].push_back(Point3f((float)(j%patternSize.width), (float)(j/patternSize.width), 0.f));1710}17111712// rectify (calibrated)1713Mat 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;1714M1.at<double>(0,2) = M2.at<double>(0,2)=(imgsize.width-1)*0.5;1715M1.at<double>(1,2) = M2.at<double>(1,2)=(imgsize.height-1)*0.5;1716D1 = Scalar::all(0);1717D2 = Scalar::all(0);1718double err = calibrateStereoCamera(objpt, imgpt1, imgpt2, M1, D1, M2, D2, imgsize, R, T, E, F,1719TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 1e-6),1720CV_CALIB_SAME_FOCAL_LENGTH1721//+ CV_CALIB_FIX_ASPECT_RATIO1722+ CV_CALIB_FIX_PRINCIPAL_POINT1723+ CV_CALIB_ZERO_TANGENT_DIST1724+ CV_CALIB_FIX_K31725+ CV_CALIB_FIX_K4 + CV_CALIB_FIX_K5 //+ CV_CALIB_FIX_K61726);1727err /= nframes*npoints;1728if( err > maxReprojErr )1729{1730ts->printf( cvtest::TS::LOG, "The average reprojection error is too big (=%g), testcase %d\n", err, testcase);1731ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );1732return;1733}17341735Mat R1, R2, P1, P2, Q;1736Rect roi1, roi2;1737rectify(M1, D1, M2, D2, imgsize, R, T, R1, R2, P1, P2, Q, 1, imgsize, &roi1, &roi2, 0);1738Mat eye33 = Mat::eye(3,3,CV_64F);1739Mat R1t = R1.t(), R2t = R2.t();17401741if( cvtest::norm(R1t*R1 - eye33, NORM_L2) > 0.01 ||1742cvtest::norm(R2t*R2 - eye33, NORM_L2) > 0.01 ||1743abs(determinant(F)) > 0.01)1744{1745ts->printf( cvtest::TS::LOG, "The computed (by rectify) R1 and R2 are not orthogonal,"1746"or the computed (by calibrate) F is not singular, testcase %d\n", testcase);1747ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );1748return;1749}17501751if(!checkPandROI(testcase, M1, D1, R1, P1, imgsize, roi1))1752{1753ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );1754return;1755}17561757if(!checkPandROI(testcase, M2, D2, R2, P2, imgsize, roi2))1758{1759ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );1760return;1761}17621763//check that Tx after rectification is equal to distance between cameras1764double tx = fabs(P2.at<double>(0, 3) / P2.at<double>(0, 0));1765if (fabs(tx - cvtest::norm(T, NORM_L2)) > 1e-5)1766{1767ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );1768return;1769}17701771//check that Q reprojects points before the camera1772double testPoint[4] = {0.0, 0.0, 100.0, 1.0};1773Mat reprojectedTestPoint = Q * Mat_<double>(4, 1, testPoint);1774CV_Assert(reprojectedTestPoint.type() == CV_64FC1);1775if( reprojectedTestPoint.at<double>(2) / reprojectedTestPoint.at<double>(3) < 0 )1776{1777ts->printf( cvtest::TS::LOG, "A point after rectification is reprojected behind the camera, testcase %d\n", testcase);1778ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );1779}17801781//check that Q reprojects the same points as reconstructed by triangulation1782const float minCoord = -300.0f;1783const float maxCoord = 300.0f;1784const float minDisparity = 0.1f;1785const float maxDisparity = 60.0f;1786const int pointsCount = 500;1787const float requiredAccuracy = 1e-3f;1788const float allowToFail = 0.2f; // 20%1789RNG& rng = ts->get_rng();17901791Mat projectedPoints_1(2, pointsCount, CV_32FC1);1792Mat projectedPoints_2(2, pointsCount, CV_32FC1);1793Mat disparities(1, pointsCount, CV_32FC1);17941795rng.fill(projectedPoints_1, RNG::UNIFORM, minCoord, maxCoord);1796rng.fill(disparities, RNG::UNIFORM, minDisparity, maxDisparity);1797projectedPoints_2.row(0) = projectedPoints_1.row(0) - disparities;1798Mat ys_2 = projectedPoints_2.row(1);1799projectedPoints_1.row(1).copyTo(ys_2);18001801Mat points4d;1802triangulate(P1, P2, projectedPoints_1, projectedPoints_2, points4d);1803Mat homogeneousPoints4d = points4d.t();1804const int dimension = 4;1805homogeneousPoints4d = homogeneousPoints4d.reshape(dimension);1806Mat triangulatedPoints;1807convertPointsFromHomogeneous(homogeneousPoints4d, triangulatedPoints);18081809Mat sparsePoints;1810sparsePoints.push_back(projectedPoints_1);1811sparsePoints.push_back(disparities);1812sparsePoints = sparsePoints.t();1813sparsePoints = sparsePoints.reshape(3);1814Mat reprojectedPoints;1815perspectiveTransform(sparsePoints, reprojectedPoints, Q);18161817Mat diff;1818absdiff(triangulatedPoints, reprojectedPoints, diff);1819Mat mask = diff > requiredAccuracy;1820mask = mask.reshape(1);1821mask = mask.col(0) | mask.col(1) | mask.col(2);1822int numFailed = countNonZero(mask);1823#if 01824std::cout << "numFailed=" << numFailed << std::endl;1825for (int i = 0; i < triangulatedPoints.rows; i++)1826{1827if (mask.at<uchar>(i))1828{1829// failed points usually have 'w'~0 (points4d[3])1830std::cout << "i=" << i << " triangulatePoints=" << triangulatedPoints.row(i) << " reprojectedPoints=" << reprojectedPoints.row(i) << std::endl <<1831" points4d=" << points4d.col(i).t() << " projectedPoints_1=" << projectedPoints_1.col(i).t() << " disparities=" << disparities.col(i).t() << std::endl;1832}1833}1834#endif18351836if (numFailed >= allowToFail * pointsCount)1837{1838ts->printf( cvtest::TS::LOG, "Points reprojected with a matrix Q and points reconstructed by triangulation are different (tolerance=%g, failed=%d), testcase %d\n",1839requiredAccuracy, numFailed, testcase);1840ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );1841}18421843//check correctMatches1844const float constraintAccuracy = 1e-5f;1845Mat newPoints1, newPoints2;1846Mat points1 = projectedPoints_1.t();1847points1 = points1.reshape(2, 1);1848Mat points2 = projectedPoints_2.t();1849points2 = points2.reshape(2, 1);1850correctMatches(F, points1, points2, newPoints1, newPoints2);1851Mat newHomogeneousPoints1, newHomogeneousPoints2;1852convertPointsToHomogeneous(newPoints1, newHomogeneousPoints1);1853convertPointsToHomogeneous(newPoints2, newHomogeneousPoints2);1854newHomogeneousPoints1 = newHomogeneousPoints1.reshape(1);1855newHomogeneousPoints2 = newHomogeneousPoints2.reshape(1);1856Mat typedF;1857F.convertTo(typedF, newHomogeneousPoints1.type());1858for (int i = 0; i < newHomogeneousPoints1.rows; ++i)1859{1860Mat error = newHomogeneousPoints2.row(i) * typedF * newHomogeneousPoints1.row(i).t();1861CV_Assert(error.rows == 1 && error.cols == 1);1862if (cvtest::norm(error, NORM_L2) > constraintAccuracy)1863{1864ts->printf( cvtest::TS::LOG, "Epipolar constraint is violated after correctMatches, testcase %d\n", testcase);1865ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );1866}1867}18681869// rectifyUncalibrated1870CV_Assert( imgpt1.size() == imgpt2.size() );1871Mat _imgpt1( total, 1, CV_32FC2 ), _imgpt2( total, 1, CV_32FC2 );1872vector<vector<Point2f> >::const_iterator iit1 = imgpt1.begin();1873vector<vector<Point2f> >::const_iterator iit2 = imgpt2.begin();1874for( int pi = 0; iit1 != imgpt1.end(); ++iit1, ++iit2 )1875{1876vector<Point2f>::const_iterator pit1 = iit1->begin();1877vector<Point2f>::const_iterator pit2 = iit2->begin();1878CV_Assert( iit1->size() == iit2->size() );1879for( ; pit1 != iit1->end(); ++pit1, ++pit2, pi++ )1880{1881_imgpt1.at<Point2f>(pi,0) = Point2f( pit1->x, pit1->y );1882_imgpt2.at<Point2f>(pi,0) = Point2f( pit2->x, pit2->y );1883}1884}18851886Mat _M1, _M2, _D1, _D2;1887vector<Mat> _R1, _R2, _T1, _T2;1888calibrateCamera( objpt, imgpt1, imgsize, _M1, _D1, _R1, _T1, 0 );1889calibrateCamera( objpt, imgpt2, imgsize, _M2, _D2, _R2, _T2, 0 );1890undistortPoints( _imgpt1, _imgpt1, _M1, _D1, Mat(), _M1 );1891undistortPoints( _imgpt2, _imgpt2, _M2, _D2, Mat(), _M2 );18921893Mat matF, _H1, _H2;1894matF = findFundamentalMat( _imgpt1, _imgpt2 );1895rectifyUncalibrated( _imgpt1, _imgpt2, matF, imgsize, _H1, _H2 );18961897Mat rectifPoints1, rectifPoints2;1898perspectiveTransform( _imgpt1, rectifPoints1, _H1 );1899perspectiveTransform( _imgpt2, rectifPoints2, _H2 );19001901bool verticalStereo = abs(P2.at<double>(0,3)) < abs(P2.at<double>(1,3));1902double maxDiff_c = 0, maxDiff_uc = 0;1903for( int i = 0, k = 0; i < nframes; i++ )1904{1905vector<Point2f> temp[2];1906undistortPoints(Mat(imgpt1[i]), temp[0], M1, D1, R1, P1);1907undistortPoints(Mat(imgpt2[i]), temp[1], M2, D2, R2, P2);19081909for( int j = 0; j < npoints; j++, k++ )1910{1911double diff_c = verticalStereo ? abs(temp[0][j].x - temp[1][j].x) : abs(temp[0][j].y - temp[1][j].y);1912Point2f d = rectifPoints1.at<Point2f>(k,0) - rectifPoints2.at<Point2f>(k,0);1913double diff_uc = verticalStereo ? abs(d.x) : abs(d.y);1914maxDiff_c = max(maxDiff_c, diff_c);1915maxDiff_uc = max(maxDiff_uc, diff_uc);1916if( maxDiff_c > maxScanlineDistErr_c )1917{1918ts->printf( cvtest::TS::LOG, "The distance between %s coordinates is too big(=%g) (used calibrated stereo), testcase %d\n",1919verticalStereo ? "x" : "y", diff_c, testcase);1920ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );1921return;1922}1923if( maxDiff_uc > maxScanlineDistErr_uc )1924{1925ts->printf( cvtest::TS::LOG, "The distance between %s coordinates is too big(=%g) (used uncalibrated stereo), testcase %d\n",1926verticalStereo ? "x" : "y", diff_uc, testcase);1927ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );1928return;1929}1930}1931}19321933ts->printf( cvtest::TS::LOG, "Testcase %d. Max distance (calibrated) =%g\n"1934"Max distance (uncalibrated) =%g\n", testcase, maxDiff_c, maxDiff_uc );1935}1936}19371938//-------------------------------- CV_StereoCalibrationTest_C ------------------------------19391940class CV_StereoCalibrationTest_C : public CV_StereoCalibrationTest1941{1942public:1943CV_StereoCalibrationTest_C() {}1944protected:1945virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,1946const vector<vector<Point2f> >& imagePoints1,1947const vector<vector<Point2f> >& imagePoints2,1948Mat& cameraMatrix1, Mat& distCoeffs1,1949Mat& cameraMatrix2, Mat& distCoeffs2,1950Size imageSize, Mat& R, Mat& T,1951Mat& E, Mat& F, TermCriteria criteria, int flags );1952virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,1953const Mat& cameraMatrix2, const Mat& distCoeffs2,1954Size imageSize, const Mat& R, const Mat& T,1955Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,1956double alpha, Size newImageSize,1957Rect* validPixROI1, Rect* validPixROI2, int flags );1958virtual bool rectifyUncalibrated( const Mat& points1,1959const Mat& points2, const Mat& F, Size imgSize,1960Mat& H1, Mat& H2, double threshold=5 );1961virtual void triangulate( const Mat& P1, const Mat& P2,1962const Mat &points1, const Mat &points2,1963Mat &points4D );1964virtual void correct( const Mat& F,1965const Mat &points1, const Mat &points2,1966Mat &newPoints1, Mat &newPoints2 );1967};19681969double CV_StereoCalibrationTest_C::calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,1970const vector<vector<Point2f> >& imagePoints1,1971const vector<vector<Point2f> >& imagePoints2,1972Mat& cameraMatrix1, Mat& distCoeffs1,1973Mat& cameraMatrix2, Mat& distCoeffs2,1974Size imageSize, Mat& R, Mat& T,1975Mat& E, Mat& F, TermCriteria criteria, int flags )1976{1977cameraMatrix1.create( 3, 3, CV_64F );1978cameraMatrix2.create( 3, 3, CV_64F);1979distCoeffs1.create( 1, 5, CV_64F);1980distCoeffs2.create( 1, 5, CV_64F);1981R.create(3, 3, CV_64F);1982T.create(3, 1, CV_64F);1983E.create(3, 3, CV_64F);1984F.create(3, 3, CV_64F);19851986int nimages = (int)objectPoints.size(), total = 0;1987for( int i = 0; i < nimages; i++ )1988{1989total += (int)objectPoints[i].size();1990}19911992Mat npoints( 1, nimages, CV_32S ),1993objPt( 1, total, traits::Type<Point3f>::value ),1994imgPt( 1, total, traits::Type<Point2f>::value ),1995imgPt2( 1, total, traits::Type<Point2f>::value );19961997Point2f* imgPtData2 = imgPt2.ptr<Point2f>();1998Point3f* objPtData = objPt.ptr<Point3f>();1999Point2f* imgPtData = imgPt.ptr<Point2f>();2000for( int i = 0, ni = 0, j = 0; i < nimages; i++, j += ni )2001{2002ni = (int)objectPoints[i].size();2003npoints.ptr<int>()[i] = ni;2004std::copy(objectPoints[i].begin(), objectPoints[i].end(), objPtData + j);2005std::copy(imagePoints1[i].begin(), imagePoints1[i].end(), imgPtData + j);2006std::copy(imagePoints2[i].begin(), imagePoints2[i].end(), imgPtData2 + j);2007}2008CvMat _objPt = cvMat(objPt), _imgPt = cvMat(imgPt), _imgPt2 = cvMat(imgPt2), _npoints = cvMat(npoints);2009CvMat _cameraMatrix1 = cvMat(cameraMatrix1), _distCoeffs1 = cvMat(distCoeffs1);2010CvMat _cameraMatrix2 = cvMat(cameraMatrix2), _distCoeffs2 = cvMat(distCoeffs2);2011CvMat matR = cvMat(R), matT = cvMat(T), matE = cvMat(E), matF = cvMat(F);20122013return cvStereoCalibrate(&_objPt, &_imgPt, &_imgPt2, &_npoints, &_cameraMatrix1,2014&_distCoeffs1, &_cameraMatrix2, &_distCoeffs2, cvSize(imageSize),2015&matR, &matT, &matE, &matF, flags, cvTermCriteria(criteria));2016}20172018void CV_StereoCalibrationTest_C::rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,2019const Mat& cameraMatrix2, const Mat& distCoeffs2,2020Size imageSize, const Mat& R, const Mat& T,2021Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,2022double alpha, Size newImageSize,2023Rect* validPixROI1, Rect* validPixROI2, int flags )2024{2025int rtype = CV_64F;2026R1.create(3, 3, rtype);2027R2.create(3, 3, rtype);2028P1.create(3, 4, rtype);2029P2.create(3, 4, rtype);2030Q.create(4, 4, rtype);2031CvMat _cameraMatrix1 = cvMat(cameraMatrix1), _distCoeffs1 = cvMat(distCoeffs1);2032CvMat _cameraMatrix2 = cvMat(cameraMatrix2), _distCoeffs2 = cvMat(distCoeffs2);2033CvMat matR = cvMat(R), matT = cvMat(T), _R1 = cvMat(R1), _R2 = cvMat(R2), _P1 = cvMat(P1), _P2 = cvMat(P2), matQ = cvMat(Q);2034cvStereoRectify( &_cameraMatrix1, &_cameraMatrix2, &_distCoeffs1, &_distCoeffs2,2035cvSize(imageSize), &matR, &matT, &_R1, &_R2, &_P1, &_P2, &matQ, flags,2036alpha, cvSize(newImageSize), (CvRect*)validPixROI1, (CvRect*)validPixROI2);2037}20382039bool CV_StereoCalibrationTest_C::rectifyUncalibrated( const Mat& points1,2040const Mat& points2, const Mat& F, Size imgSize, Mat& H1, Mat& H2, double threshold )2041{2042H1.create(3, 3, CV_64F);2043H2.create(3, 3, CV_64F);2044CvMat _pt1 = cvMat(points1), _pt2 = cvMat(points2), matF, *pF=0, _H1 = cvMat(H1), _H2 = cvMat(H2);2045if( F.size() == Size(3, 3) )2046pF = &(matF = cvMat(F));2047return cvStereoRectifyUncalibrated(&_pt1, &_pt2, pF, cvSize(imgSize), &_H1, &_H2, threshold) > 0;2048}20492050void CV_StereoCalibrationTest_C::triangulate( const Mat& P1, const Mat& P2,2051const Mat &points1, const Mat &points2,2052Mat &points4D )2053{2054CvMat _P1 = cvMat(P1), _P2 = cvMat(P2), _points1 = cvMat(points1), _points2 = cvMat(points2);2055points4D.create(4, points1.cols, points1.type());2056CvMat _points4D = cvMat(points4D);2057cvTriangulatePoints(&_P1, &_P2, &_points1, &_points2, &_points4D);2058}20592060void CV_StereoCalibrationTest_C::correct( const Mat& F,2061const Mat &points1, const Mat &points2,2062Mat &newPoints1, Mat &newPoints2 )2063{2064CvMat _F = cvMat(F), _points1 = cvMat(points1), _points2 = cvMat(points2);2065newPoints1.create(1, points1.cols, points1.type());2066newPoints2.create(1, points2.cols, points2.type());2067CvMat _newPoints1 = cvMat(newPoints1), _newPoints2 = cvMat(newPoints2);2068cvCorrectMatches(&_F, &_points1, &_points2, &_newPoints1, &_newPoints2);2069}20702071//-------------------------------- CV_StereoCalibrationTest_CPP ------------------------------20722073class CV_StereoCalibrationTest_CPP : public CV_StereoCalibrationTest2074{2075public:2076CV_StereoCalibrationTest_CPP() {}2077protected:2078virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,2079const vector<vector<Point2f> >& imagePoints1,2080const vector<vector<Point2f> >& imagePoints2,2081Mat& cameraMatrix1, Mat& distCoeffs1,2082Mat& cameraMatrix2, Mat& distCoeffs2,2083Size imageSize, Mat& R, Mat& T,2084Mat& E, Mat& F, TermCriteria criteria, int flags );2085virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,2086const Mat& cameraMatrix2, const Mat& distCoeffs2,2087Size imageSize, const Mat& R, const Mat& T,2088Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,2089double alpha, Size newImageSize,2090Rect* validPixROI1, Rect* validPixROI2, int flags );2091virtual bool rectifyUncalibrated( const Mat& points1,2092const Mat& points2, const Mat& F, Size imgSize,2093Mat& H1, Mat& H2, double threshold=5 );2094virtual void triangulate( const Mat& P1, const Mat& P2,2095const Mat &points1, const Mat &points2,2096Mat &points4D );2097virtual void correct( const Mat& F,2098const Mat &points1, const Mat &points2,2099Mat &newPoints1, Mat &newPoints2 );2100};21012102double CV_StereoCalibrationTest_CPP::calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,2103const vector<vector<Point2f> >& imagePoints1,2104const vector<vector<Point2f> >& imagePoints2,2105Mat& cameraMatrix1, Mat& distCoeffs1,2106Mat& cameraMatrix2, Mat& distCoeffs2,2107Size imageSize, Mat& R, Mat& T,2108Mat& E, Mat& F, TermCriteria criteria, int flags )2109{2110return stereoCalibrate( objectPoints, imagePoints1, imagePoints2,2111cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,2112imageSize, R, T, E, F, flags, criteria );2113}21142115void CV_StereoCalibrationTest_CPP::rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,2116const Mat& cameraMatrix2, const Mat& distCoeffs2,2117Size imageSize, const Mat& R, const Mat& T,2118Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,2119double alpha, Size newImageSize,2120Rect* validPixROI1, Rect* validPixROI2, int flags )2121{2122stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,2123imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize,validPixROI1, validPixROI2 );2124}21252126bool CV_StereoCalibrationTest_CPP::rectifyUncalibrated( const Mat& points1,2127const Mat& points2, const Mat& F, Size imgSize, Mat& H1, Mat& H2, double threshold )2128{2129return stereoRectifyUncalibrated( points1, points2, F, imgSize, H1, H2, threshold );2130}21312132void CV_StereoCalibrationTest_CPP::triangulate( const Mat& P1, const Mat& P2,2133const Mat &points1, const Mat &points2,2134Mat &points4D )2135{2136triangulatePoints(P1, P2, points1, points2, points4D);2137}21382139void CV_StereoCalibrationTest_CPP::correct( const Mat& F,2140const Mat &points1, const Mat &points2,2141Mat &newPoints1, Mat &newPoints2 )2142{2143correctMatches(F, points1, points2, newPoints1, newPoints2);2144}21452146///////////////////////////////////////////////////////////////////////////////////////////////////21472148TEST(Calib3d_CalibrateCamera_C, regression) { CV_CameraCalibrationTest_C test; test.safe_run(); }2149TEST(Calib3d_CalibrateCamera_CPP, regression) { CV_CameraCalibrationTest_CPP test; test.safe_run(); }2150TEST(Calib3d_CalibrationMatrixValues_C, accuracy) { CV_CalibrationMatrixValuesTest_C test; test.safe_run(); }2151TEST(Calib3d_CalibrationMatrixValues_CPP, accuracy) { CV_CalibrationMatrixValuesTest_CPP test; test.safe_run(); }2152TEST(Calib3d_ProjectPoints_C, accuracy) { CV_ProjectPointsTest_C test; test.safe_run(); }2153TEST(Calib3d_ProjectPoints_CPP, regression) { CV_ProjectPointsTest_CPP test; test.safe_run(); }2154TEST(Calib3d_StereoCalibrate_C, regression) { CV_StereoCalibrationTest_C test; test.safe_run(); }2155TEST(Calib3d_StereoCalibrate_CPP, regression) { CV_StereoCalibrationTest_CPP test; test.safe_run(); }2156TEST(Calib3d_StereoCalibrateCorner, regression) { CV_StereoCalibrationCornerTest test; test.safe_run(); }21572158TEST(Calib3d_StereoCalibrate_CPP, extended)2159{2160cvtest::TS* ts = cvtest::TS::ptr();2161String filepath = cv::format("%scv/stereo/case%d/", ts->get_data_path().c_str(), 1 );21622163Mat left = imread(filepath+"left01.png");2164Mat right = imread(filepath+"right01.png");2165if(left.empty() || right.empty())2166{2167ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );2168return;2169}21702171vector<vector<Point2f> > imgpt1(1), imgpt2(1);2172vector<vector<Point3f> > objpt(1);2173Size patternSize(9, 6), imageSize(640, 480);2174bool found1 = findChessboardCorners(left, patternSize, imgpt1[0]);2175bool found2 = findChessboardCorners(right, patternSize, imgpt2[0]);21762177if(!found1 || !found2)2178{2179ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );2180return;2181}21822183for( int j = 0; j < patternSize.width*patternSize.height; j++ )2184objpt[0].push_back(Point3f((float)(j%patternSize.width), (float)(j/patternSize.width), 0.f));21852186Mat K1, K2, c1, c2, R, T, E, F, err;2187int flags = 0;2188double res0 = stereoCalibrate( objpt, imgpt1, imgpt2,2189K1, c1, K2, c2,2190imageSize, R, T, E, F, err, flags);21912192flags = CALIB_USE_EXTRINSIC_GUESS;2193double res1 = stereoCalibrate( objpt, imgpt1, imgpt2,2194K1, c1, K2, c2,2195imageSize, R, T, E, F, err, flags);2196EXPECT_LE(res1, res0);2197EXPECT_TRUE(err.total() == 2);2198}21992200TEST(Calib3d_StereoCalibrate, regression_10791)2201{2202const Matx33d M1(2203853.1387981631528, 0, 704.154907802121,22040, 853.6445089162528, 520.3600712930319,22050, 0, 12206);2207const Matx33d M2(2208848.6090216909176, 0, 701.6162856852185,22090, 849.7040162357157, 509.1864036137,22100, 0, 12211);2212const Matx<double, 14, 1> D1(-6.463598629567206, 79.00104930508179, -0.0001006144444464403, -0.0005437499822299972,221312.56900616588467, -6.056719942752855, 76.3842481414836, 45.57460250612659,22140, 0, 0, 0, 0, 0);2215const Matx<double, 14, 1> D2(0.6123436439798265, -0.4671756923224087, -0.0001261947899033442, -0.000597334584036978,2216-0.05660119809538371, 1.037075740629769, -0.3076042835831711, -0.2502169324283623,22170, 0, 0, 0, 0, 0);22182219const Matx33d R(22200.9999926627018476, -0.0001095586963765905, 0.003829169539302921,22210.0001021735876758584, 0.9999981346680941, 0.0019287874145156,2222-0.003829373712065528, -0.001928382022437616, 0.99999080857763332223);2224const Matx31d T(-58.9161771697128, -0.01581306249996402, -0.8492960216760961);22252226const Size imageSize(1280, 960);22272228Mat R1, R2, P1, P2, Q;2229Rect roi1, roi2;2230stereoRectify(M1, D1, M2, D2, imageSize, R, T,2231R1, R2, P1, P2, Q,2232CALIB_ZERO_DISPARITY, 1, imageSize, &roi1, &roi2);22332234EXPECT_GE(roi1.area(), 400*300) << roi1;2235EXPECT_GE(roi2.area(), 400*300) << roi2;2236}22372238TEST(Calib3d_Triangulate, accuracy)2239{2240// the testcase from http://code.opencv.org/issues/43342241{2242double P1data[] = { 250, 0, 200, 0, 0, 250, 150, 0, 0, 0, 1, 0 };2243double P2data[] = { 250, 0, 200, -250, 0, 250, 150, 0, 0, 0, 1, 0 };2244Mat P1(3, 4, CV_64F, P1data), P2(3, 4, CV_64F, P2data);22452246float x1data[] = { 200.f, 0.f };2247float x2data[] = { 170.f, 1.f };2248float Xdata[] = { 0.f, -5.f, 25/3.f };2249Mat x1(2, 1, CV_32F, x1data);2250Mat x2(2, 1, CV_32F, x2data);2251Mat res0(1, 3, CV_32F, Xdata);2252Mat res_, res;22532254triangulatePoints(P1, P2, x1, x2, res_);2255cv::transpose(res_, res_); // TODO cvtest (transpose doesn't support inplace)2256convertPointsFromHomogeneous(res_, res);2257res = res.reshape(1, 1);22582259cout << "[1]:" << endl;2260cout << "\tres0: " << res0 << endl;2261cout << "\tres: " << res << endl;22622263ASSERT_LE(cvtest::norm(res, res0, NORM_INF), 1e-1);2264}22652266// another testcase http://code.opencv.org/issues/34612267{2268Matx33d K1(6137.147949, 0.000000, 644.974609,22690.000000, 6137.147949, 573.442749,22700.000000, 0.000000, 1.000000);2271Matx33d K2(6137.147949, 0.000000, 644.674438,22720.000000, 6137.147949, 573.079834,22730.000000, 0.000000, 1.000000);22742275Matx34d RT1(1, 0, 0, 0,22760, 1, 0, 0,22770, 0, 1, 0);22782279Matx34d RT2(0.998297, 0.0064108, -0.0579766, 143.614334,2280-0.0065818, 0.999975, -0.00275888, -5.160085,22810.0579574, 0.00313577, 0.998314, 96.066109);22822283Matx34d P1 = K1*RT1;2284Matx34d P2 = K2*RT2;22852286float x1data[] = { 438.f, 19.f };2287float x2data[] = { 452.363600f, 16.452225f };2288float Xdata[] = { -81.049530f, -215.702804f, 2401.645449f };2289Mat x1(2, 1, CV_32F, x1data);2290Mat x2(2, 1, CV_32F, x2data);2291Mat res0(1, 3, CV_32F, Xdata);2292Mat res_, res;22932294triangulatePoints(P1, P2, x1, x2, res_);2295cv::transpose(res_, res_); // TODO cvtest (transpose doesn't support inplace)2296convertPointsFromHomogeneous(res_, res);2297res = res.reshape(1, 1);22982299cout << "[2]:" << endl;2300cout << "\tres0: " << res0 << endl;2301cout << "\tres: " << res << endl;23022303ASSERT_LE(cvtest::norm(res, res0, NORM_INF), 2);2304}2305}23062307}} // namespace230823092310