test_cameracalibration.cpp 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410
  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // Intel License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000, Intel Corporation, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of Intel Corporation may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. #include "test_precomp.hpp"
  42. namespace opencv_test { namespace {
  43. #if 0
  44. class CV_ProjectPointsTest : public cvtest::ArrayTest
  45. {
  46. public:
  47. CV_ProjectPointsTest();
  48. protected:
  49. int read_params( const cv::FileStorage& fs );
  50. void fill_array( int test_case_idx, int i, int j, Mat& arr );
  51. int prepare_test_case( int test_case_idx );
  52. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  53. double get_success_error_level( int test_case_idx, int i, int j );
  54. void run_func();
  55. void prepare_to_validation( int );
  56. bool calc_jacobians;
  57. };
  58. CV_ProjectPointsTest::CV_ProjectPointsTest()
  59. : cvtest::ArrayTest( "3d-ProjectPoints", "cvProjectPoints2", "" )
  60. {
  61. test_array[INPUT].push_back(NULL); // rotation vector
  62. test_array[OUTPUT].push_back(NULL); // rotation matrix
  63. test_array[OUTPUT].push_back(NULL); // jacobian (J)
  64. test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)
  65. test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)
  66. test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)
  67. test_array[REF_OUTPUT].push_back(NULL);
  68. test_array[REF_OUTPUT].push_back(NULL);
  69. test_array[REF_OUTPUT].push_back(NULL);
  70. test_array[REF_OUTPUT].push_back(NULL);
  71. test_array[REF_OUTPUT].push_back(NULL);
  72. element_wise_relative_error = false;
  73. calc_jacobians = false;
  74. }
  75. int CV_ProjectPointsTest::read_params( const cv::FileStorage& fs )
  76. {
  77. int code = cvtest::ArrayTest::read_params( fs );
  78. return code;
  79. }
  80. void CV_ProjectPointsTest::get_test_array_types_and_sizes(
  81. int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  82. {
  83. RNG& rng = ts->get_rng();
  84. int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
  85. int i, code;
  86. code = cvtest::randInt(rng) % 3;
  87. types[INPUT][0] = CV_MAKETYPE(depth, 1);
  88. if( code == 0 )
  89. {
  90. sizes[INPUT][0] = cvSize(1,1);
  91. types[INPUT][0] = CV_MAKETYPE(depth, 3);
  92. }
  93. else if( code == 1 )
  94. sizes[INPUT][0] = cvSize(3,1);
  95. else
  96. sizes[INPUT][0] = cvSize(1,3);
  97. sizes[OUTPUT][0] = cvSize(3, 3);
  98. types[OUTPUT][0] = CV_MAKETYPE(depth, 1);
  99. types[OUTPUT][1] = CV_MAKETYPE(depth, 1);
  100. if( cvtest::randInt(rng) % 2 )
  101. sizes[OUTPUT][1] = cvSize(3,9);
  102. else
  103. sizes[OUTPUT][1] = cvSize(9,3);
  104. types[OUTPUT][2] = types[INPUT][0];
  105. sizes[OUTPUT][2] = sizes[INPUT][0];
  106. types[OUTPUT][3] = types[OUTPUT][1];
  107. sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);
  108. types[OUTPUT][4] = types[OUTPUT][1];
  109. sizes[OUTPUT][4] = cvSize(3,3);
  110. calc_jacobians = 1;//cvtest::randInt(rng) % 3 != 0;
  111. if( !calc_jacobians )
  112. sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);
  113. for( i = 0; i < 5; i++ )
  114. {
  115. types[REF_OUTPUT][i] = types[OUTPUT][i];
  116. sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
  117. }
  118. }
  119. double CV_ProjectPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )
  120. {
  121. return j == 4 ? 1e-2 : 1e-2;
  122. }
  123. void CV_ProjectPointsTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, CvMat* arr )
  124. {
  125. double r[3], theta0, theta1, f;
  126. CvMat _r = cvMat( arr->rows, arr->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(arr->type)), r );
  127. RNG& rng = ts->get_rng();
  128. r[0] = cvtest::randReal(rng)*CV_PI*2;
  129. r[1] = cvtest::randReal(rng)*CV_PI*2;
  130. r[2] = cvtest::randReal(rng)*CV_PI*2;
  131. theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
  132. theta1 = fmod(theta0, CV_PI*2);
  133. if( theta1 > CV_PI )
  134. theta1 = -(CV_PI*2 - theta1);
  135. f = theta1/(theta0 ? theta0 : 1);
  136. r[0] *= f;
  137. r[1] *= f;
  138. r[2] *= f;
  139. cvTsConvert( &_r, arr );
  140. }
  141. int CV_ProjectPointsTest::prepare_test_case( int test_case_idx )
  142. {
  143. int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
  144. return code;
  145. }
  146. void CV_ProjectPointsTest::run_func()
  147. {
  148. CvMat *v2m_jac = 0, *m2v_jac = 0;
  149. if( calc_jacobians )
  150. {
  151. v2m_jac = &test_mat[OUTPUT][1];
  152. m2v_jac = &test_mat[OUTPUT][3];
  153. }
  154. cvProjectPoints2( &test_mat[INPUT][0], &test_mat[OUTPUT][0], v2m_jac );
  155. cvProjectPoints2( &test_mat[OUTPUT][0], &test_mat[OUTPUT][2], m2v_jac );
  156. }
  157. void CV_ProjectPointsTest::prepare_to_validation( int /*test_case_idx*/ )
  158. {
  159. const CvMat* vec = &test_mat[INPUT][0];
  160. CvMat* m = &test_mat[REF_OUTPUT][0];
  161. CvMat* vec2 = &test_mat[REF_OUTPUT][2];
  162. CvMat* v2m_jac = 0, *m2v_jac = 0;
  163. double theta0, theta1;
  164. if( calc_jacobians )
  165. {
  166. v2m_jac = &test_mat[REF_OUTPUT][1];
  167. m2v_jac = &test_mat[REF_OUTPUT][3];
  168. }
  169. cvTsProjectPoints( vec, m, v2m_jac );
  170. cvTsProjectPoints( m, vec2, m2v_jac );
  171. cvTsCopy( vec, vec2 );
  172. theta0 = cvtest::norm( cvarrtomat(vec2), 0, CV_L2 );
  173. theta1 = fmod( theta0, CV_PI*2 );
  174. if( theta1 > CV_PI )
  175. theta1 = -(CV_PI*2 - theta1);
  176. cvScale( vec2, vec2, theta1/(theta0 ? theta0 : 1) );
  177. if( calc_jacobians )
  178. {
  179. //cvInvert( v2m_jac, m2v_jac, CV_SVD );
  180. if( cvtest::norm(cvarrtomat(&test_mat[OUTPUT][3]), 0, CV_C) < 1000 )
  181. {
  182. cvTsGEMM( &test_mat[OUTPUT][1], &test_mat[OUTPUT][3],
  183. 1, 0, 0, &test_mat[OUTPUT][4],
  184. v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );
  185. }
  186. else
  187. {
  188. cvTsSetIdentity( &test_mat[OUTPUT][4], cvScalarAll(1.) );
  189. cvTsCopy( &test_mat[REF_OUTPUT][2], &test_mat[OUTPUT][2] );
  190. }
  191. cvTsSetIdentity( &test_mat[REF_OUTPUT][4], cvScalarAll(1.) );
  192. }
  193. }
  194. CV_ProjectPointsTest ProjectPoints_test;
  195. #endif
  196. // --------------------------------- CV_CameraCalibrationTest --------------------------------------------
  197. typedef Matx33d RotMat;
  198. class CV_CameraCalibrationTest : public cvtest::BaseTest
  199. {
  200. public:
  201. CV_CameraCalibrationTest();
  202. ~CV_CameraCalibrationTest();
  203. void clear();
  204. protected:
  205. int compare(double* val, double* refVal, int len,
  206. double eps, const char* paramName);
  207. virtual void calibrate(Size imageSize,
  208. const std::vector<std::vector<Point2d> >& imagePoints,
  209. const std::vector<std::vector<Point3d> >& objectPoints,
  210. int iFixedPoint, Mat& distortionCoeffs, Mat& cameraMatrix, std::vector<Vec3d>& translationVectors,
  211. std::vector<RotMat>& rotationMatrices, std::vector<Point3d>& newObjPoints,
  212. std::vector<double>& stdDevs, std::vector<double>& perViewErrors,
  213. int flags ) = 0;
  214. virtual void project( const std::vector<Point3d>& objectPoints,
  215. const RotMat& rotationMatrix, const Vec3d& translationVector,
  216. const Mat& cameraMatrix, const Mat& distortion,
  217. std::vector<Point2d>& imagePoints ) = 0;
  218. void run(int);
  219. };
  220. CV_CameraCalibrationTest::CV_CameraCalibrationTest()
  221. {
  222. }
  223. CV_CameraCalibrationTest::~CV_CameraCalibrationTest()
  224. {
  225. clear();
  226. }
  227. void CV_CameraCalibrationTest::clear()
  228. {
  229. cvtest::BaseTest::clear();
  230. }
  231. int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len,
  232. double eps, const char* param_name )
  233. {
  234. return cvtest::cmpEps2_64f( ts, val, ref_val, len, eps, param_name );
  235. }
  236. void CV_CameraCalibrationTest::run( int start_from )
  237. {
  238. int code = cvtest::TS::OK;
  239. cv::String filepath;
  240. cv::String filename;
  241. std::vector<std::vector<Point2d> > imagePoints;
  242. std::vector<std::vector<Point3d> > objectPoints;
  243. std::vector<std::vector<Point2d> > reprojectPoints;
  244. std::vector<Vec3d> transVects;
  245. std::vector<RotMat> rotMatrs;
  246. std::vector<Point3d> newObjPoints;
  247. std::vector<double> stdDevs;
  248. std::vector<double> perViewErrors;
  249. std::vector<Vec3d> goodTransVects;
  250. std::vector<RotMat> goodRotMatrs;
  251. std::vector<Point3d> goodObjPoints;
  252. std::vector<double> goodPerViewErrors;
  253. std::vector<double> goodStdDevs;
  254. Mat cameraMatrix;
  255. Mat distortion = Mat::zeros(1, 5, CV_64F);
  256. Mat goodDistortion = Mat::zeros(1, 5, CV_64F);
  257. FILE* file = 0;
  258. FILE* datafile = 0;
  259. int i,j;
  260. int currImage;
  261. int currPoint;
  262. char i_dat_file[100];
  263. int progress = 0;
  264. int values_read = -1;
  265. filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() );
  266. filename = cv::format("%sdatafiles.txt", filepath.c_str() );
  267. datafile = fopen( filename.c_str(), "r" );
  268. if( datafile == 0 )
  269. {
  270. ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename.c_str() );
  271. code = cvtest::TS::FAIL_MISSING_TEST_DATA;
  272. ts->set_failed_test_info( code );
  273. return;
  274. }
  275. int numTests = 0;
  276. values_read = fscanf(datafile,"%d",&numTests);
  277. CV_Assert(values_read == 1);
  278. for( int currTest = start_from; currTest < numTests; currTest++ )
  279. {
  280. values_read = fscanf(datafile,"%s",i_dat_file);
  281. CV_Assert(values_read == 1);
  282. filename = cv::format("%s%s", filepath.c_str(), i_dat_file);
  283. file = fopen(filename.c_str(),"r");
  284. ts->update_context( this, currTest, true );
  285. if( file == 0 )
  286. {
  287. ts->printf( cvtest::TS::LOG,
  288. "Can't open current test file: %s\n",filename.c_str());
  289. if( numTests == 1 )
  290. {
  291. code = cvtest::TS::FAIL_MISSING_TEST_DATA;
  292. break;
  293. }
  294. continue; // if there is more than one test, just skip the test
  295. }
  296. Size imageSize;
  297. values_read = fscanf(file,"%d %d\n",&(imageSize.width),&(imageSize.height));
  298. CV_Assert(values_read == 2);
  299. if( imageSize.width <= 0 || imageSize.height <= 0 )
  300. {
  301. ts->printf( cvtest::TS::LOG, "Image size in test file is incorrect\n" );
  302. code = cvtest::TS::FAIL_INVALID_TEST_DATA;
  303. break;
  304. }
  305. /* Read etalon size */
  306. Size etalonSize;
  307. values_read = fscanf(file,"%d %d\n",&(etalonSize.width),&(etalonSize.height));
  308. CV_Assert(values_read == 2);
  309. if( etalonSize.width <= 0 || etalonSize.height <= 0 )
  310. {
  311. ts->printf( cvtest::TS::LOG, "Pattern size in test file is incorrect\n" );
  312. code = cvtest::TS::FAIL_INVALID_TEST_DATA;
  313. break;
  314. }
  315. int numPoints = etalonSize.width * etalonSize.height;
  316. /* Read number of images */
  317. int numImages = 0;
  318. values_read = fscanf(file,"%d\n",&numImages);
  319. CV_Assert(values_read == 1);
  320. if( numImages <=0 )
  321. {
  322. ts->printf( cvtest::TS::LOG, "Number of images in test file is incorrect\n");
  323. code = cvtest::TS::FAIL_INVALID_TEST_DATA;
  324. break;
  325. }
  326. /* Read calibration flags */
  327. int calibFlags = 0;
  328. values_read = fscanf(file,"%d\n",&calibFlags);
  329. CV_Assert(values_read == 1);
  330. /* Read index of the fixed point */
  331. int iFixedPoint;
  332. values_read = fscanf(file,"%d\n",&iFixedPoint);
  333. CV_Assert(values_read == 1);
  334. /* Need to allocate memory */
  335. imagePoints.resize(numImages);
  336. objectPoints.resize(numImages);
  337. reprojectPoints.resize(numImages);
  338. for( currImage = 0; currImage < numImages; currImage++ )
  339. {
  340. imagePoints[currImage].resize(numPoints);
  341. objectPoints[currImage].resize(numPoints);
  342. reprojectPoints[currImage].resize(numPoints);
  343. }
  344. transVects.resize(numImages);
  345. rotMatrs.resize(numImages);
  346. newObjPoints.resize(numPoints);
  347. stdDevs.resize(CALIB_NINTRINSIC + 6*numImages + 3*numPoints);
  348. perViewErrors.resize(numImages);
  349. goodTransVects.resize(numImages);
  350. goodRotMatrs.resize(numImages);
  351. goodObjPoints.resize(numPoints);
  352. goodPerViewErrors.resize(numImages);
  353. int nstddev = CALIB_NINTRINSIC + 6*numImages + 3*numPoints;
  354. goodStdDevs.resize(nstddev);
  355. for( currImage = 0; currImage < numImages; currImage++ )
  356. {
  357. for( currPoint = 0; currPoint < numPoints; currPoint++ )
  358. {
  359. double x,y,z;
  360. values_read = fscanf(file,"%lf %lf %lf\n",&x,&y,&z);
  361. CV_Assert(values_read == 3);
  362. objectPoints[currImage][currPoint].x = x;
  363. objectPoints[currImage][currPoint].y = y;
  364. objectPoints[currImage][currPoint].z = z;
  365. }
  366. }
  367. /* Read image points */
  368. for( currImage = 0; currImage < numImages; currImage++ )
  369. {
  370. for( currPoint = 0; currPoint < numPoints; currPoint++ )
  371. {
  372. double x,y;
  373. values_read = fscanf(file,"%lf %lf\n",&x,&y);
  374. CV_Assert(values_read == 2);
  375. imagePoints[currImage][currPoint].x = x;
  376. imagePoints[currImage][currPoint].y = y;
  377. }
  378. }
  379. /* Read good data computed before */
  380. /* Focal lengths */
  381. double goodFcx,goodFcy;
  382. values_read = fscanf(file,"%lf %lf",&goodFcx,&goodFcy);
  383. CV_Assert(values_read == 2);
  384. /* Principal points */
  385. double goodCx,goodCy;
  386. values_read = fscanf(file,"%lf %lf",&goodCx,&goodCy);
  387. CV_Assert(values_read == 2);
  388. /* Read distortion */
  389. for( i = 0; i < 4; i++ )
  390. {
  391. values_read = fscanf(file,"%lf",&goodDistortion.at<double>(i)); CV_Assert(values_read == 1);
  392. }
  393. /* Read good Rot matrices */
  394. for( currImage = 0; currImage < numImages; currImage++ )
  395. {
  396. for( i = 0; i < 3; i++ )
  397. for( j = 0; j < 3; j++ )
  398. {
  399. // Yes, load with transpose
  400. values_read = fscanf(file, "%lf", &goodRotMatrs[currImage].val[j*3+i]);
  401. CV_Assert(values_read == 1);
  402. }
  403. }
  404. /* Read good Trans vectors */
  405. for( currImage = 0; currImage < numImages; currImage++ )
  406. {
  407. for( i = 0; i < 3; i++ )
  408. {
  409. values_read = fscanf(file, "%lf", &goodTransVects[currImage].val[i]);
  410. CV_Assert(values_read == 1);
  411. }
  412. }
  413. bool releaseObject = iFixedPoint > 0 && iFixedPoint < numPoints - 1;
  414. /* Read good refined 3D object points */
  415. if( releaseObject )
  416. {
  417. for( i = 0; i < numPoints; i++ )
  418. {
  419. for( j = 0; j < 3; j++ )
  420. {
  421. values_read = fscanf(file, "%lf", &goodObjPoints[i].x + j);
  422. CV_Assert(values_read == 1);
  423. }
  424. }
  425. }
  426. /* Read good stdDeviations */
  427. for (i = 0; i < CALIB_NINTRINSIC + numImages*6; i++)
  428. {
  429. values_read = fscanf(file, "%lf", &goodStdDevs[i]);
  430. CV_Assert(values_read == 1);
  431. }
  432. for( ; i < nstddev; i++ )
  433. {
  434. if( releaseObject )
  435. {
  436. values_read = fscanf(file, "%lf", &goodStdDevs[i]);
  437. CV_Assert(values_read == 1);
  438. }
  439. else
  440. goodStdDevs[i] = 0.0;
  441. }
  442. cameraMatrix = Mat::zeros(3, 3, CV_64F);
  443. cameraMatrix.at<double>(0, 0) = cameraMatrix.at<double>(1, 1) = 807.;
  444. cameraMatrix.at<double>(0, 2) = (imageSize.width - 1)*0.5;
  445. cameraMatrix.at<double>(1, 2) = (imageSize.height - 1)*0.5;
  446. cameraMatrix.at<double>(2, 2) = 1.;
  447. /* Now we can calibrate camera */
  448. calibrate( imageSize,
  449. imagePoints,
  450. objectPoints,
  451. iFixedPoint,
  452. distortion,
  453. cameraMatrix,
  454. transVects,
  455. rotMatrs,
  456. newObjPoints,
  457. stdDevs,
  458. perViewErrors,
  459. calibFlags );
  460. /* ---- Reproject points to the image ---- */
  461. for( currImage = 0; currImage < numImages; currImage++ )
  462. {
  463. if( releaseObject )
  464. {
  465. objectPoints[currImage] = newObjPoints;
  466. }
  467. project( objectPoints[currImage],
  468. rotMatrs[currImage],
  469. transVects[currImage],
  470. cameraMatrix,
  471. distortion,
  472. reprojectPoints[currImage]);
  473. }
  474. /* ----- Compute reprojection error ----- */
  475. double dx,dy;
  476. double rx,ry;
  477. for( currImage = 0; currImage < numImages; currImage++ )
  478. {
  479. double imageMeanDx = 0;
  480. double imageMeanDy = 0;
  481. for( currPoint = 0; currPoint < etalonSize.width * etalonSize.height; currPoint++ )
  482. {
  483. rx = reprojectPoints[currImage][currPoint].x;
  484. ry = reprojectPoints[currImage][currPoint].y;
  485. dx = rx - imagePoints[currImage][currPoint].x;
  486. dy = ry - imagePoints[currImage][currPoint].y;
  487. imageMeanDx += dx*dx;
  488. imageMeanDy += dy*dy;
  489. }
  490. goodPerViewErrors[currImage] = sqrt( (imageMeanDx + imageMeanDy) /
  491. (etalonSize.width * etalonSize.height));
  492. //only for c-version of test (it does not provides evaluation of perViewErrors
  493. //and returns zeros)
  494. if(perViewErrors[currImage] == 0.0)
  495. perViewErrors[currImage] = goodPerViewErrors[currImage];
  496. }
  497. /* ========= Compare parameters ========= */
  498. CV_Assert(cameraMatrix.type() == CV_64F && cameraMatrix.size() == Size(3, 3));
  499. CV_Assert(distortion.type() == CV_64F);
  500. Size dsz = distortion.size();
  501. CV_Assert(dsz == Size(4, 1) || dsz == Size(1, 4) || dsz == Size(5, 1) || dsz == Size(1, 5));
  502. /*std::cout << "cameraMatrix: " << cameraMatrix << "\n";
  503. std::cout << "curr distCoeffs: " << distortion << "\n";
  504. std::cout << "good distCoeffs: " << goodDistortion << "\n";*/
  505. /* ----- Compare focal lengths ----- */
  506. code = compare(&cameraMatrix.at<double>(0, 0), &goodFcx, 1, 0.1, "fx");
  507. if( code < 0 )
  508. break;
  509. code = compare(&cameraMatrix.at<double>(1, 1),&goodFcy, 1, 0.1, "fy");
  510. if( code < 0 )
  511. break;
  512. /* ----- Compare principal points ----- */
  513. code = compare(&cameraMatrix.at<double>(0,2), &goodCx, 1, 0.1, "cx");
  514. if( code < 0 )
  515. break;
  516. code = compare(&cameraMatrix.at<double>(1,2), &goodCy, 1, 0.1, "cy");
  517. if( code < 0 )
  518. break;
  519. /* ----- Compare distortion ----- */
  520. code = compare(&distortion.at<double>(0), &goodDistortion.at<double>(0), 4, 0.1, "[k1,k2,p1,p2]");
  521. if( code < 0 )
  522. break;
  523. /* ----- Compare rot matrixs ----- */
  524. CV_Assert(rotMatrs.size() == (size_t)numImages);
  525. CV_Assert(transVects.size() == (size_t)numImages);
  526. //code = compare(rotMatrs[0].val, goodRotMatrs[0].val, 9*numImages, 0.05, "rotation matrices");
  527. for( i = 0; i < numImages; i++ )
  528. {
  529. if( cv::norm(rotMatrs[i], goodRotMatrs[i], NORM_INF) > 0.05 )
  530. {
  531. printf("rot mats for frame #%d are very different\n", i);
  532. std::cout << "curr:\n" << rotMatrs[i] << std::endl;
  533. std::cout << "good:\n" << goodRotMatrs[i] << std::endl;
  534. code = TS::FAIL_BAD_ACCURACY;
  535. break;
  536. }
  537. }
  538. if( code < 0 )
  539. break;
  540. /* ----- Compare rot matrixs ----- */
  541. code = compare(transVects[0].val, goodTransVects[0].val, 3*numImages, 0.1, "translation vectors");
  542. if( code < 0 )
  543. break;
  544. /* ----- Compare refined 3D object points ----- */
  545. if( releaseObject )
  546. {
  547. code = compare(&newObjPoints[0].x, &goodObjPoints[0].x, 3*numPoints, 0.1, "refined 3D object points");
  548. if( code < 0 )
  549. break;
  550. }
  551. /* ----- Compare per view re-projection errors ----- */
  552. CV_Assert(perViewErrors.size() == (size_t)numImages);
  553. code = compare(&perViewErrors[0], &goodPerViewErrors[0], numImages, 0.1, "per view errors vector");
  554. if( code < 0 )
  555. break;
  556. /* ----- Compare standard deviations of parameters ----- */
  557. if( stdDevs.size() < (size_t)nstddev )
  558. stdDevs.resize(nstddev);
  559. for ( i = 0; i < nstddev; i++)
  560. {
  561. if(stdDevs[i] == 0.0)
  562. stdDevs[i] = goodStdDevs[i];
  563. }
  564. code = compare(&stdDevs[0], &goodStdDevs[0], nstddev, .5,
  565. "stdDevs vector");
  566. if( code < 0 )
  567. break;
  568. /*if( maxDx > 1.0 )
  569. {
  570. ts->printf( cvtest::TS::LOG,
  571. "Error in reprojection maxDx=%f > 1.0\n",maxDx);
  572. code = cvtest::TS::FAIL_BAD_ACCURACY; break;
  573. }
  574. if( maxDy > 1.0 )
  575. {
  576. ts->printf( cvtest::TS::LOG,
  577. "Error in reprojection maxDy=%f > 1.0\n",maxDy);
  578. code = cvtest::TS::FAIL_BAD_ACCURACY; break;
  579. }*/
  580. progress = update_progress( progress, currTest, numTests, 0 );
  581. fclose(file);
  582. file = 0;
  583. }
  584. if( file )
  585. fclose(file);
  586. if( datafile )
  587. fclose(datafile);
  588. if( code < 0 )
  589. ts->set_failed_test_info( code );
  590. }
  591. // --------------------------------- CV_CameraCalibrationTest_CPP --------------------------------------------
  592. class CV_CameraCalibrationTest_CPP : public CV_CameraCalibrationTest
  593. {
  594. public:
  595. CV_CameraCalibrationTest_CPP(){}
  596. protected:
  597. virtual void calibrate(Size imageSize,
  598. const std::vector<std::vector<Point2d> >& imagePoints,
  599. const std::vector<std::vector<Point3d> >& objectPoints,
  600. int iFixedPoint, Mat& distortionCoeffs, Mat& cameraMatrix, std::vector<Vec3d>& translationVectors,
  601. std::vector<RotMat>& rotationMatrices, std::vector<Point3d>& newObjPoints,
  602. std::vector<double>& stdDevs, std::vector<double>& perViewErrors,
  603. int flags );
  604. virtual void project( const std::vector<Point3d>& objectPoints,
  605. const RotMat& rotationMatrix, const Vec3d& translationVector,
  606. const Mat& cameraMatrix, const Mat& distortion,
  607. std::vector<Point2d>& imagePoints );
  608. };
  609. void CV_CameraCalibrationTest_CPP::calibrate(Size imageSize,
  610. const std::vector<std::vector<Point2d> >& _imagePoints,
  611. const std::vector<std::vector<Point3d> >& _objectPoints,
  612. int iFixedPoint, Mat& _distCoeffs, Mat& _cameraMatrix, std::vector<Vec3d>& translationVectors,
  613. std::vector<RotMat>& rotationMatrices, std::vector<Point3d>& newObjPoints,
  614. std::vector<double>& stdDevs, std::vector<double>& perViewErrors,
  615. int flags )
  616. {
  617. int pointCount = (int)_imagePoints[0].size();
  618. size_t i, imageCount = _imagePoints.size();
  619. vector<vector<Point3f> > objectPoints( imageCount );
  620. vector<vector<Point2f> > imagePoints( imageCount );
  621. Mat cameraMatrix, distCoeffs(1,4,CV_64F,Scalar::all(0));
  622. vector<Mat> rvecs, tvecs;
  623. Mat newObjMat;
  624. Mat stdDevsMatInt, stdDevsMatExt;
  625. Mat stdDevsMatObj;
  626. Mat perViewErrorsMat;
  627. for( i = 0; i < imageCount; i++ )
  628. {
  629. Mat(_imagePoints[i]).convertTo(imagePoints[i], CV_32F);
  630. Mat(_objectPoints[i]).convertTo(objectPoints[i], CV_32F);
  631. }
  632. size_t nstddev0 = CALIB_NINTRINSIC + imageCount*6, nstddev1 = nstddev0 + _imagePoints[0].size()*3;
  633. for( i = nstddev0; i < nstddev1; i++ )
  634. {
  635. stdDevs[i] = 0.0;
  636. }
  637. calibrateCameraRO( objectPoints,
  638. imagePoints,
  639. imageSize,
  640. iFixedPoint,
  641. cameraMatrix,
  642. distCoeffs,
  643. rvecs,
  644. tvecs,
  645. newObjMat,
  646. stdDevsMatInt,
  647. stdDevsMatExt,
  648. stdDevsMatObj,
  649. perViewErrorsMat,
  650. flags );
  651. bool releaseObject = iFixedPoint > 0 && iFixedPoint < pointCount - 1;
  652. if( releaseObject )
  653. {
  654. newObjMat.convertTo( newObjPoints, CV_64F );
  655. }
  656. Mat stdDevMats[] = {stdDevsMatInt, stdDevsMatExt, stdDevsMatObj}, stdDevsMat;
  657. vconcat(stdDevMats, releaseObject ? 3 : 2, stdDevsMat);
  658. stdDevsMat.convertTo(stdDevs, CV_64F);
  659. perViewErrorsMat.convertTo(perViewErrors, CV_64F);
  660. cameraMatrix.convertTo(_cameraMatrix, CV_64F);
  661. distCoeffs.convertTo(_distCoeffs, CV_64F);
  662. for( i = 0; i < imageCount; i++ )
  663. {
  664. Mat r9;
  665. cvtest::Rodrigues( rvecs[i], r9 );
  666. r9.convertTo(rotationMatrices[i], CV_64F);
  667. tvecs[i].convertTo(translationVectors[i], CV_64F);
  668. }
  669. }
  670. void CV_CameraCalibrationTest_CPP::project( const std::vector<Point3d>& objectPoints,
  671. const RotMat& rotationMatrix, const Vec3d& translationVector,
  672. const Mat& cameraMatrix, const Mat& distortion,
  673. std::vector<Point2d>& imagePoints )
  674. {
  675. projectPoints(objectPoints, rotationMatrix, translationVector, cameraMatrix, distortion, imagePoints );
  676. /*Mat objectPoints( pointCount, 3, CV_64FC1, _objectPoints );
  677. Mat rmat( 3, 3, CV_64FC1, rotationMatrix ),
  678. rvec( 1, 3, CV_64FC1 ),
  679. tvec( 1, 3, CV_64FC1, translationVector );
  680. Mat cameraMatrix( 3, 3, CV_64FC1, _cameraMatrix );
  681. Mat distCoeffs( 1, 4, CV_64FC1, distortion );
  682. vector<Point2f> imagePoints;
  683. cvtest::Rodrigues( rmat, rvec );
  684. objectPoints.convertTo( objectPoints, CV_32FC1 );
  685. projectPoints( objectPoints, rvec, tvec,
  686. cameraMatrix, distCoeffs, imagePoints );
  687. vector<Point2f>::const_iterator it = imagePoints.begin();
  688. for( int i = 0; it != imagePoints.end(); ++it, i++ )
  689. {
  690. _imagePoints[i] = cvPoint2D64f( it->x, it->y );
  691. }*/
  692. }
  693. //----------------------------------------- CV_CalibrationMatrixValuesTest --------------------------------
  694. class CV_CalibrationMatrixValuesTest : public cvtest::BaseTest
  695. {
  696. public:
  697. CV_CalibrationMatrixValuesTest() {}
  698. protected:
  699. void run(int);
  700. virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  701. double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
  702. Point2d& principalPoint, double& aspectRatio ) = 0;
  703. };
  704. void CV_CalibrationMatrixValuesTest::run(int)
  705. {
  706. int code = cvtest::TS::OK;
  707. const double fcMinVal = 1e-5;
  708. const double fcMaxVal = 1000;
  709. const double apertureMaxVal = 0.01;
  710. RNG rng = ts->get_rng();
  711. double fx, fy, cx, cy, nx, ny;
  712. Mat cameraMatrix( 3, 3, CV_64FC1 );
  713. cameraMatrix.setTo( Scalar(0) );
  714. fx = cameraMatrix.at<double>(0,0) = rng.uniform( fcMinVal, fcMaxVal );
  715. fy = cameraMatrix.at<double>(1,1) = rng.uniform( fcMinVal, fcMaxVal );
  716. cx = cameraMatrix.at<double>(0,2) = rng.uniform( fcMinVal, fcMaxVal );
  717. cy = cameraMatrix.at<double>(1,2) = rng.uniform( fcMinVal, fcMaxVal );
  718. cameraMatrix.at<double>(2,2) = 1;
  719. Size imageSize( 600, 400 );
  720. double apertureWidth = (double)rng * apertureMaxVal,
  721. apertureHeight = (double)rng * apertureMaxVal;
  722. double fovx, fovy, focalLength, aspectRatio,
  723. goodFovx, goodFovy, goodFocalLength, goodAspectRatio;
  724. Point2d principalPoint, goodPrincipalPoint;
  725. calibMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,
  726. fovx, fovy, focalLength, principalPoint, aspectRatio );
  727. // calculate calibration matrix values
  728. goodAspectRatio = fy / fx;
  729. if( apertureWidth != 0.0 && apertureHeight != 0.0 )
  730. {
  731. nx = imageSize.width / apertureWidth;
  732. ny = imageSize.height / apertureHeight;
  733. }
  734. else
  735. {
  736. nx = 1.0;
  737. ny = goodAspectRatio;
  738. }
  739. goodFovx = (atan2(cx, fx) + atan2(imageSize.width - cx, fx)) * 180.0 / CV_PI;
  740. goodFovy = (atan2(cy, fy) + atan2(imageSize.height - cy, fy)) * 180.0 / CV_PI;
  741. goodFocalLength = fx / nx;
  742. goodPrincipalPoint.x = cx / nx;
  743. goodPrincipalPoint.y = cy / ny;
  744. // check results
  745. if( fabs(fovx - goodFovx) > FLT_EPSILON )
  746. {
  747. ts->printf( cvtest::TS::LOG, "bad fovx (real=%f, good = %f\n", fovx, goodFovx );
  748. code = cvtest::TS::FAIL_BAD_ACCURACY;
  749. goto _exit_;
  750. }
  751. if( fabs(fovy - goodFovy) > FLT_EPSILON )
  752. {
  753. ts->printf( cvtest::TS::LOG, "bad fovy (real=%f, good = %f\n", fovy, goodFovy );
  754. code = cvtest::TS::FAIL_BAD_ACCURACY;
  755. goto _exit_;
  756. }
  757. if( fabs(focalLength - goodFocalLength) > FLT_EPSILON )
  758. {
  759. ts->printf( cvtest::TS::LOG, "bad focalLength (real=%f, good = %f\n", focalLength, goodFocalLength );
  760. code = cvtest::TS::FAIL_BAD_ACCURACY;
  761. goto _exit_;
  762. }
  763. if( fabs(aspectRatio - goodAspectRatio) > FLT_EPSILON )
  764. {
  765. ts->printf( cvtest::TS::LOG, "bad aspectRatio (real=%f, good = %f\n", aspectRatio, goodAspectRatio );
  766. code = cvtest::TS::FAIL_BAD_ACCURACY;
  767. goto _exit_;
  768. }
  769. if( cv::norm(principalPoint - goodPrincipalPoint) > FLT_EPSILON ) // Point2d
  770. {
  771. ts->printf( cvtest::TS::LOG, "bad principalPoint\n" );
  772. code = cvtest::TS::FAIL_BAD_ACCURACY;
  773. goto _exit_;
  774. }
  775. _exit_:
  776. RNG& _rng = ts->get_rng();
  777. _rng = rng;
  778. ts->set_failed_test_info( code );
  779. }
  780. //----------------------------------------- CV_CalibrationMatrixValuesTest_CPP --------------------------------
  781. class CV_CalibrationMatrixValuesTest_CPP : public CV_CalibrationMatrixValuesTest
  782. {
  783. public:
  784. CV_CalibrationMatrixValuesTest_CPP() {}
  785. protected:
  786. virtual void calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  787. double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength,
  788. Point2d& principalPoint, double& aspectRatio );
  789. };
  790. void CV_CalibrationMatrixValuesTest_CPP::calibMatrixValues( const Mat& cameraMatrix, Size imageSize,
  791. double apertureWidth, double apertureHeight,
  792. double& fovx, double& fovy, double& focalLength,
  793. Point2d& principalPoint, double& aspectRatio )
  794. {
  795. calibrationMatrixValues( cameraMatrix, imageSize, apertureWidth, apertureHeight,
  796. fovx, fovy, focalLength, principalPoint, aspectRatio );
  797. }
  798. //----------------------------------------- CV_ProjectPointsTest --------------------------------
  799. void calcdfdx( const vector<vector<Point2f> >& leftF, const vector<vector<Point2f> >& rightF, double eps, Mat& dfdx )
  800. {
  801. const int fdim = 2;
  802. CV_Assert( !leftF.empty() && !rightF.empty() && !leftF[0].empty() && !rightF[0].empty() );
  803. CV_Assert( leftF[0].size() == rightF[0].size() );
  804. CV_Assert( fabs(eps) > std::numeric_limits<double>::epsilon() );
  805. int fcount = (int)leftF[0].size(), xdim = (int)leftF.size();
  806. dfdx.create( fcount*fdim, xdim, CV_64FC1 );
  807. vector<vector<Point2f> >::const_iterator arrLeftIt = leftF.begin();
  808. vector<vector<Point2f> >::const_iterator arrRightIt = rightF.begin();
  809. for( int xi = 0; xi < xdim; xi++, ++arrLeftIt, ++arrRightIt )
  810. {
  811. CV_Assert( (int)arrLeftIt->size() == fcount );
  812. CV_Assert( (int)arrRightIt->size() == fcount );
  813. vector<Point2f>::const_iterator lIt = arrLeftIt->begin();
  814. vector<Point2f>::const_iterator rIt = arrRightIt->begin();
  815. for( int fi = 0; fi < dfdx.rows; fi+=fdim, ++lIt, ++rIt )
  816. {
  817. dfdx.at<double>(fi, xi ) = 0.5 * ((double)(rIt->x - lIt->x)) / eps;
  818. dfdx.at<double>(fi+1, xi ) = 0.5 * ((double)(rIt->y - lIt->y)) / eps;
  819. }
  820. }
  821. }
  822. class CV_ProjectPointsTest : public cvtest::BaseTest
  823. {
  824. public:
  825. CV_ProjectPointsTest() {}
  826. protected:
  827. void run(int);
  828. virtual void project( const Mat& objectPoints,
  829. const Mat& rvec, const Mat& tvec,
  830. const Mat& cameraMatrix,
  831. const Mat& distCoeffs,
  832. vector<Point2f>& imagePoints,
  833. Mat& dpdrot, Mat& dpdt, Mat& dpdf,
  834. Mat& dpdc, Mat& dpddist,
  835. double aspectRatio=0 ) = 0;
  836. };
  837. void CV_ProjectPointsTest::run(int)
  838. {
  839. //typedef float matType;
  840. int code = cvtest::TS::OK;
  841. const int pointCount = 100;
  842. const float zMinVal = 10.0f, zMaxVal = 100.0f,
  843. rMinVal = -0.3f, rMaxVal = 0.3f,
  844. tMinVal = -2.0f, tMaxVal = 2.0f;
  845. const float imgPointErr = 1e-3f,
  846. dEps = 1e-3f;
  847. double err;
  848. Size imgSize( 600, 800 );
  849. Mat_<float> objPoints( pointCount, 3), rvec( 1, 3), rmat, tvec( 1, 3 ), cameraMatrix( 3, 3 ), distCoeffs( 1, 4 ),
  850. leftRvec, rightRvec, leftTvec, rightTvec, leftCameraMatrix, rightCameraMatrix, leftDistCoeffs, rightDistCoeffs;
  851. RNG rng = ts->get_rng();
  852. // generate data
  853. cameraMatrix << 300.f, 0.f, imgSize.width/2.f,
  854. 0.f, 300.f, imgSize.height/2.f,
  855. 0.f, 0.f, 1.f;
  856. distCoeffs << 0.1, 0.01, 0.001, 0.001;
  857. rvec(0,0) = rng.uniform( rMinVal, rMaxVal );
  858. rvec(0,1) = rng.uniform( rMinVal, rMaxVal );
  859. rvec(0,2) = rng.uniform( rMinVal, rMaxVal );
  860. rmat = cv::Mat_<float>::zeros(3, 3);
  861. cvtest::Rodrigues( rvec, rmat );
  862. tvec(0,0) = rng.uniform( tMinVal, tMaxVal );
  863. tvec(0,1) = rng.uniform( tMinVal, tMaxVal );
  864. tvec(0,2) = rng.uniform( tMinVal, tMaxVal );
  865. for( int y = 0; y < objPoints.rows; y++ )
  866. {
  867. Mat point(1, 3, CV_32FC1, objPoints.ptr(y) );
  868. float z = rng.uniform( zMinVal, zMaxVal );
  869. point.at<float>(0,2) = z;
  870. point.at<float>(0,0) = (rng.uniform(2.f,(float)(imgSize.width-2)) - cameraMatrix(0,2)) / cameraMatrix(0,0) * z;
  871. point.at<float>(0,1) = (rng.uniform(2.f,(float)(imgSize.height-2)) - cameraMatrix(1,2)) / cameraMatrix(1,1) * z;
  872. point = (point - tvec) * rmat;
  873. }
  874. vector<Point2f> imgPoints;
  875. vector<vector<Point2f> > leftImgPoints;
  876. vector<vector<Point2f> > rightImgPoints;
  877. Mat dpdrot, dpdt, dpdf, dpdc, dpddist,
  878. valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist;
  879. project( objPoints, rvec, tvec, cameraMatrix, distCoeffs,
  880. imgPoints, dpdrot, dpdt, dpdf, dpdc, dpddist, 0 );
  881. // calculate and check image points
  882. CV_Assert( (int)imgPoints.size() == pointCount );
  883. vector<Point2f>::const_iterator it = imgPoints.begin();
  884. for( int i = 0; i < pointCount; i++, ++it )
  885. {
  886. Point3d p( objPoints(i,0), objPoints(i,1), objPoints(i,2) );
  887. double z = p.x*rmat(2,0) + p.y*rmat(2,1) + p.z*rmat(2,2) + tvec(0,2),
  888. x = (p.x*rmat(0,0) + p.y*rmat(0,1) + p.z*rmat(0,2) + tvec(0,0)) / z,
  889. y = (p.x*rmat(1,0) + p.y*rmat(1,1) + p.z*rmat(1,2) + tvec(0,1)) / z,
  890. r2 = x*x + y*y,
  891. r4 = r2*r2;
  892. Point2f validImgPoint;
  893. double a1 = 2*x*y,
  894. a2 = r2 + 2*x*x,
  895. a3 = r2 + 2*y*y,
  896. cdist = 1+distCoeffs(0,0)*r2+distCoeffs(0,1)*r4;
  897. validImgPoint.x = static_cast<float>((double)cameraMatrix(0,0)*(x*cdist + (double)distCoeffs(0,2)*a1 + (double)distCoeffs(0,3)*a2)
  898. + (double)cameraMatrix(0,2));
  899. validImgPoint.y = static_cast<float>((double)cameraMatrix(1,1)*(y*cdist + (double)distCoeffs(0,2)*a3 + distCoeffs(0,3)*a1)
  900. + (double)cameraMatrix(1,2));
  901. if( fabs(it->x - validImgPoint.x) > imgPointErr ||
  902. fabs(it->y - validImgPoint.y) > imgPointErr )
  903. {
  904. ts->printf( cvtest::TS::LOG, "bad image point\n" );
  905. code = cvtest::TS::FAIL_BAD_ACCURACY;
  906. goto _exit_;
  907. }
  908. }
  909. // check derivatives
  910. // 1. rotation
  911. leftImgPoints.resize(3);
  912. rightImgPoints.resize(3);
  913. for( int i = 0; i < 3; i++ )
  914. {
  915. rvec.copyTo( leftRvec ); leftRvec(0,i) -= dEps;
  916. project( objPoints, leftRvec, tvec, cameraMatrix, distCoeffs,
  917. leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  918. rvec.copyTo( rightRvec ); rightRvec(0,i) += dEps;
  919. project( objPoints, rightRvec, tvec, cameraMatrix, distCoeffs,
  920. rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  921. }
  922. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdrot );
  923. err = cvtest::norm( dpdrot, valDpdrot, NORM_INF );
  924. if( err > 3 )
  925. {
  926. ts->printf( cvtest::TS::LOG, "bad dpdrot: too big difference = %g\n", err );
  927. code = cvtest::TS::FAIL_BAD_ACCURACY;
  928. }
  929. // 2. translation
  930. for( int i = 0; i < 3; i++ )
  931. {
  932. tvec.copyTo( leftTvec ); leftTvec(0,i) -= dEps;
  933. project( objPoints, rvec, leftTvec, cameraMatrix, distCoeffs,
  934. leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  935. tvec.copyTo( rightTvec ); rightTvec(0,i) += dEps;
  936. project( objPoints, rvec, rightTvec, cameraMatrix, distCoeffs,
  937. rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  938. }
  939. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdt );
  940. if( cvtest::norm( dpdt, valDpdt, NORM_INF ) > 0.2 )
  941. {
  942. ts->printf( cvtest::TS::LOG, "bad dpdtvec\n" );
  943. code = cvtest::TS::FAIL_BAD_ACCURACY;
  944. }
  945. // 3. camera matrix
  946. // 3.1. focus
  947. leftImgPoints.resize(2);
  948. rightImgPoints.resize(2);
  949. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,0) -= dEps;
  950. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  951. leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  952. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,1) -= dEps;
  953. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  954. leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  955. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,0) += dEps;
  956. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  957. rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  958. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,1) += dEps;
  959. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  960. rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  961. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdf );
  962. if ( cvtest::norm( dpdf, valDpdf, NORM_L2 ) > 0.2 )
  963. {
  964. ts->printf( cvtest::TS::LOG, "bad dpdf\n" );
  965. code = cvtest::TS::FAIL_BAD_ACCURACY;
  966. }
  967. // 3.2. principal point
  968. leftImgPoints.resize(2);
  969. rightImgPoints.resize(2);
  970. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(0,2) -= dEps;
  971. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  972. leftImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  973. cameraMatrix.copyTo( leftCameraMatrix ); leftCameraMatrix(1,2) -= dEps;
  974. project( objPoints, rvec, tvec, leftCameraMatrix, distCoeffs,
  975. leftImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  976. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(0,2) += dEps;
  977. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  978. rightImgPoints[0], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  979. cameraMatrix.copyTo( rightCameraMatrix ); rightCameraMatrix(1,2) += dEps;
  980. project( objPoints, rvec, tvec, rightCameraMatrix, distCoeffs,
  981. rightImgPoints[1], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  982. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpdc );
  983. if ( cvtest::norm( dpdc, valDpdc, NORM_L2 ) > 0.2 )
  984. {
  985. ts->printf( cvtest::TS::LOG, "bad dpdc\n" );
  986. code = cvtest::TS::FAIL_BAD_ACCURACY;
  987. }
  988. // 4. distortion
  989. leftImgPoints.resize(distCoeffs.cols);
  990. rightImgPoints.resize(distCoeffs.cols);
  991. for( int i = 0; i < distCoeffs.cols; i++ )
  992. {
  993. distCoeffs.copyTo( leftDistCoeffs ); leftDistCoeffs(0,i) -= dEps;
  994. project( objPoints, rvec, tvec, cameraMatrix, leftDistCoeffs,
  995. leftImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  996. distCoeffs.copyTo( rightDistCoeffs ); rightDistCoeffs(0,i) += dEps;
  997. project( objPoints, rvec, tvec, cameraMatrix, rightDistCoeffs,
  998. rightImgPoints[i], valDpdrot, valDpdt, valDpdf, valDpdc, valDpddist, 0 );
  999. }
  1000. calcdfdx( leftImgPoints, rightImgPoints, dEps, valDpddist );
  1001. if( cvtest::norm( dpddist, valDpddist, NORM_L2 ) > 0.3 )
  1002. {
  1003. ts->printf( cvtest::TS::LOG, "bad dpddist\n" );
  1004. code = cvtest::TS::FAIL_BAD_ACCURACY;
  1005. }
  1006. _exit_:
  1007. RNG& _rng = ts->get_rng();
  1008. _rng = rng;
  1009. ts->set_failed_test_info( code );
  1010. }
  1011. //----------------------------------------- CV_ProjectPointsTest_CPP --------------------------------
  1012. class CV_ProjectPointsTest_CPP : public CV_ProjectPointsTest
  1013. {
  1014. public:
  1015. CV_ProjectPointsTest_CPP() {}
  1016. protected:
  1017. virtual void project( const Mat& objectPoints,
  1018. const Mat& rvec, const Mat& tvec,
  1019. const Mat& cameraMatrix,
  1020. const Mat& distCoeffs,
  1021. vector<Point2f>& imagePoints,
  1022. Mat& dpdrot, Mat& dpdt, Mat& dpdf,
  1023. Mat& dpdc, Mat& dpddist,
  1024. double aspectRatio=0 );
  1025. };
  1026. void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec, const Mat& tvec,
  1027. const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& imagePoints,
  1028. Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio)
  1029. {
  1030. Mat J;
  1031. projectPoints( objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, J, aspectRatio);
  1032. J.colRange(0, 3).copyTo(dpdrot);
  1033. J.colRange(3, 6).copyTo(dpdt);
  1034. J.colRange(6, 8).copyTo(dpdf);
  1035. J.colRange(8, 10).copyTo(dpdc);
  1036. J.colRange(10, J.cols).copyTo(dpddist);
  1037. }
  1038. ///////////////////////////////// Stereo Calibration /////////////////////////////////////
  1039. class CV_StereoCalibrationTest : public cvtest::BaseTest
  1040. {
  1041. public:
  1042. CV_StereoCalibrationTest();
  1043. ~CV_StereoCalibrationTest();
  1044. void clear();
  1045. protected:
  1046. bool checkPandROI( int test_case_idx,
  1047. const Mat& M, const Mat& D, const Mat& R,
  1048. const Mat& P, Size imgsize, Rect roi );
  1049. // covers of tested functions
  1050. virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
  1051. const vector<vector<Point2f> >& imagePoints1,
  1052. const vector<vector<Point2f> >& imagePoints2,
  1053. Mat& cameraMatrix1, Mat& distCoeffs1,
  1054. Mat& cameraMatrix2, Mat& distCoeffs2,
  1055. Size imageSize, Mat& R, Mat& T,
  1056. Mat& E, Mat& F,
  1057. std::vector<RotMat>& rotationMatrices, std::vector<Vec3d>& translationVectors,
  1058. vector<double>& perViewErrors1, vector<double>& perViewErrors2,
  1059. TermCriteria criteria, int flags ) = 0;
  1060. virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
  1061. const Mat& cameraMatrix2, const Mat& distCoeffs2,
  1062. Size imageSize, const Mat& R, const Mat& T,
  1063. Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
  1064. double alpha, Size newImageSize,
  1065. Rect* validPixROI1, Rect* validPixROI2, int flags ) = 0;
  1066. virtual bool rectifyUncalibrated( const Mat& points1,
  1067. const Mat& points2, const Mat& F, Size imgSize,
  1068. Mat& H1, Mat& H2, double threshold=5 ) = 0;
  1069. virtual void triangulate( const Mat& P1, const Mat& P2,
  1070. const Mat &points1, const Mat &points2,
  1071. Mat &points4D ) = 0;
  1072. virtual void correct( const Mat& F,
  1073. const Mat &points1, const Mat &points2,
  1074. Mat &newPoints1, Mat &newPoints2 ) = 0;
  1075. int compare(double* val, double* refVal, int len,
  1076. double eps, const char* paramName);
  1077. void run(int);
  1078. };
  1079. CV_StereoCalibrationTest::CV_StereoCalibrationTest()
  1080. {
  1081. }
  1082. CV_StereoCalibrationTest::~CV_StereoCalibrationTest()
  1083. {
  1084. clear();
  1085. }
  1086. void CV_StereoCalibrationTest::clear()
  1087. {
  1088. cvtest::BaseTest::clear();
  1089. }
  1090. bool CV_StereoCalibrationTest::checkPandROI( int test_case_idx, const Mat& M, const Mat& D, const Mat& R,
  1091. const Mat& P, Size imgsize, Rect roi )
  1092. {
  1093. const double eps = 0.05;
  1094. const int N = 21;
  1095. int x, y, k;
  1096. vector<Point2f> pts, upts;
  1097. // step 1. check that all the original points belong to the destination image
  1098. for( y = 0; y < N; y++ )
  1099. for( x = 0; x < N; x++ )
  1100. pts.push_back(Point2f((float)x*imgsize.width/(N-1), (float)y*imgsize.height/(N-1)));
  1101. undistortPoints(pts, upts, M, D, R, P );
  1102. for( k = 0; k < N*N; k++ )
  1103. if( upts[k].x < -imgsize.width*eps || upts[k].x > imgsize.width*(1+eps) ||
  1104. upts[k].y < -imgsize.height*eps || upts[k].y > imgsize.height*(1+eps) )
  1105. {
  1106. ts->printf(cvtest::TS::LOG, "Test #%d. The point (%g, %g) was mapped to (%g, %g) which is out of image\n",
  1107. test_case_idx, pts[k].x, pts[k].y, upts[k].x, upts[k].y);
  1108. return false;
  1109. }
  1110. // step 2. check that all the points inside ROI belong to the original source image
  1111. Mat temp(imgsize, CV_8U), utemp, map1, map2;
  1112. temp = Scalar::all(1);
  1113. initUndistortRectifyMap(M, D, R, P, imgsize, CV_16SC2, map1, map2);
  1114. remap(temp, utemp, map1, map2, INTER_LINEAR);
  1115. if(roi.x < 0 || roi.y < 0 || roi.x + roi.width > imgsize.width || roi.y + roi.height > imgsize.height)
  1116. {
  1117. ts->printf(cvtest::TS::LOG, "Test #%d. The ROI=(%d, %d, %d, %d) is outside of the imge rectangle\n",
  1118. test_case_idx, roi.x, roi.y, roi.width, roi.height);
  1119. return false;
  1120. }
  1121. double s = sum(utemp(roi))[0];
  1122. if( s > roi.area() || roi.area() - s > roi.area()*(1-eps) )
  1123. {
  1124. ts->printf(cvtest::TS::LOG, "Test #%d. The ratio of black pixels inside the valid ROI (~%g%%) is too large\n",
  1125. test_case_idx, s*100./roi.area());
  1126. return false;
  1127. }
  1128. return true;
  1129. }
  1130. int CV_StereoCalibrationTest::compare(double* val, double* ref_val, int len,
  1131. double eps, const char* param_name )
  1132. {
  1133. return cvtest::cmpEps2_64f( ts, val, ref_val, len, eps, param_name );
  1134. }
  1135. void CV_StereoCalibrationTest::run( int )
  1136. {
  1137. const int ntests = 1;
  1138. const double maxReprojErr = 2;
  1139. const double maxScanlineDistErr_c = 3;
  1140. const double maxScanlineDistErr_uc = 4;
  1141. const double maxDiffBtwRmsErrors = 1e-4;
  1142. FILE* f = 0;
  1143. for(int testcase = 1; testcase <= ntests; testcase++)
  1144. {
  1145. cv::String filepath;
  1146. char buf[1000];
  1147. filepath = cv::format("%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase );
  1148. f = fopen(filepath.c_str(), "rt");
  1149. Size patternSize;
  1150. vector<string> imglist;
  1151. if( !f || !fgets(buf, sizeof(buf)-3, f) || sscanf(buf, "%d%d", &patternSize.width, &patternSize.height) != 2 )
  1152. {
  1153. ts->printf( cvtest::TS::LOG, "The file %s can not be opened or has invalid content\n", filepath.c_str() );
  1154. ts->set_failed_test_info( f ? cvtest::TS::FAIL_INVALID_TEST_DATA : cvtest::TS::FAIL_MISSING_TEST_DATA );
  1155. if (f)
  1156. fclose(f);
  1157. return;
  1158. }
  1159. for(;;)
  1160. {
  1161. if( !fgets( buf, sizeof(buf)-3, f ))
  1162. break;
  1163. size_t len = strlen(buf);
  1164. while( len > 0 && isspace(buf[len-1]))
  1165. buf[--len] = '\0';
  1166. if( buf[0] == '#')
  1167. continue;
  1168. filepath = cv::format("%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf );
  1169. imglist.push_back(string(filepath));
  1170. }
  1171. fclose(f);
  1172. if( imglist.size() == 0 || imglist.size() % 2 != 0 )
  1173. {
  1174. ts->printf( cvtest::TS::LOG, "The number of images is 0 or an odd number in the case #%d\n", testcase );
  1175. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
  1176. return;
  1177. }
  1178. int nframes = (int)(imglist.size()/2);
  1179. int npoints = patternSize.width*patternSize.height;
  1180. vector<vector<Point3f> > objpt(nframes);
  1181. vector<vector<Point2f> > imgpt1(nframes);
  1182. vector<vector<Point2f> > imgpt2(nframes);
  1183. Size imgsize;
  1184. int total = 0;
  1185. for( int i = 0; i < nframes; i++ )
  1186. {
  1187. Mat left = imread(imglist[i*2], IMREAD_GRAYSCALE);
  1188. Mat right = imread(imglist[i*2+1], IMREAD_GRAYSCALE);
  1189. if(left.empty() || right.empty())
  1190. {
  1191. ts->printf( cvtest::TS::LOG, "Can not load images %s and %s, testcase %d\n",
  1192. imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase );
  1193. ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
  1194. return;
  1195. }
  1196. imgsize = left.size();
  1197. bool found1 = findChessboardCorners(left, patternSize, imgpt1[i]);
  1198. bool found2 = findChessboardCorners(right, patternSize, imgpt2[i]);
  1199. cornerSubPix(left, imgpt1[i], Size(5, 5), Size(-1, -1), TermCriteria(TermCriteria::EPS | TermCriteria::MAX_ITER, 30, 0.1));
  1200. cornerSubPix(right, imgpt2[i], Size(5, 5), Size(-1, -1), TermCriteria(TermCriteria::EPS | TermCriteria::MAX_ITER, 30, 0.1));
  1201. if(!found1 || !found2)
  1202. {
  1203. ts->printf( cvtest::TS::LOG, "The function could not detect boards (%d x %d) on the images %s and %s, testcase %d\n",
  1204. patternSize.width, patternSize.height,
  1205. imglist[i*2].c_str(), imglist[i*2+1].c_str(), testcase );
  1206. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  1207. return;
  1208. }
  1209. total += (int)imgpt1[i].size();
  1210. for( int j = 0; j < npoints; j++ )
  1211. objpt[i].push_back(Point3f((float)(j%patternSize.width), (float)(j/patternSize.width), 0.f));
  1212. }
  1213. vector<RotMat> rotMats1(nframes);
  1214. vector<Vec3d> transVecs1(nframes);
  1215. vector<RotMat> rotMats2(nframes);
  1216. vector<Vec3d> transVecs2(nframes);
  1217. vector<double> rmsErrorPerView1(nframes);
  1218. vector<double> rmsErrorPerView2(nframes);
  1219. vector<double> rmsErrorPerViewFromReprojectedImgPts1(nframes);
  1220. vector<double> rmsErrorPerViewFromReprojectedImgPts2(nframes);
  1221. // rectify (calibrated)
  1222. 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;
  1223. M1.at<double>(0,2) = M2.at<double>(0,2)=(imgsize.width-1)*0.5;
  1224. M1.at<double>(1,2) = M2.at<double>(1,2)=(imgsize.height-1)*0.5;
  1225. D1 = Scalar::all(0);
  1226. D2 = Scalar::all(0);
  1227. double rmsErrorFromStereoCalib = calibrateStereoCamera(objpt, imgpt1, imgpt2, M1, D1, M2, D2, imgsize, R, T, E, F,
  1228. rotMats1, transVecs1, rmsErrorPerView1, rmsErrorPerView2,
  1229. TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 1e-6),
  1230. CALIB_SAME_FOCAL_LENGTH
  1231. //+ CALIB_FIX_ASPECT_RATIO
  1232. + CALIB_FIX_PRINCIPAL_POINT
  1233. + CALIB_ZERO_TANGENT_DIST
  1234. + CALIB_FIX_K3
  1235. + CALIB_FIX_K4 + CALIB_FIX_K5 //+ CALIB_FIX_K6
  1236. );
  1237. /* rmsErrorFromStereoCalib /= nframes*npoints; */
  1238. if (rmsErrorFromStereoCalib > maxReprojErr)
  1239. {
  1240. ts->printf(cvtest::TS::LOG, "The average reprojection error is too big (=%g), testcase %d\n",
  1241. rmsErrorFromStereoCalib, testcase);
  1242. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  1243. return;
  1244. }
  1245. double rmsErrorFromReprojectedImgPts = 0.0f;
  1246. if (rotMats1.empty() || transVecs1.empty())
  1247. {
  1248. rmsErrorPerViewFromReprojectedImgPts1 = rmsErrorPerView1;
  1249. rmsErrorPerViewFromReprojectedImgPts2 = rmsErrorPerView2;
  1250. rmsErrorFromReprojectedImgPts = rmsErrorFromStereoCalib;
  1251. }
  1252. else
  1253. {
  1254. vector<Point2f > reprojectedImgPts[2] = {vector<Point2f>(nframes), vector<Point2f>(nframes)};
  1255. size_t totalPoints = 0;
  1256. double totalErr[2] = { 0, 0 }, viewErr[2];
  1257. for (size_t i = 0; i < objpt.size(); ++i) {
  1258. RotMat r1 = rotMats1[i];
  1259. Vec3d t1 = transVecs1[i];
  1260. RotMat r2 = Mat(R * r1);
  1261. Mat T2t = R * t1;
  1262. Vec3d t2 = Mat(T2t + T);
  1263. projectPoints(objpt[i], r1, t1, M1, D1, reprojectedImgPts[0]);
  1264. projectPoints(objpt[i], r2, t2, M2, D2, reprojectedImgPts[1]);
  1265. viewErr[0] = cv::norm(imgpt1[i], reprojectedImgPts[0], cv::NORM_L2SQR);
  1266. viewErr[1] = cv::norm(imgpt2[i], reprojectedImgPts[1], cv::NORM_L2SQR);
  1267. size_t n = objpt[i].size();
  1268. totalErr[0] += viewErr[0];
  1269. totalErr[1] += viewErr[1];
  1270. totalPoints += n;
  1271. rmsErrorPerViewFromReprojectedImgPts1[i] = sqrt(viewErr[0] / n);
  1272. rmsErrorPerViewFromReprojectedImgPts2[i] = sqrt(viewErr[1] / n);
  1273. }
  1274. rmsErrorFromReprojectedImgPts = std::sqrt((totalErr[0] + totalErr[1]) / (2 * totalPoints));
  1275. }
  1276. if (abs(rmsErrorFromStereoCalib - rmsErrorFromReprojectedImgPts) > maxDiffBtwRmsErrors)
  1277. {
  1278. ts->printf(cvtest::TS::LOG,
  1279. "The difference of the average reprojection error from the calibration function and from the "
  1280. "reprojected image points is too big (|%g - %g| = %g), testcase %d\n",
  1281. rmsErrorFromStereoCalib, rmsErrorFromReprojectedImgPts,
  1282. (rmsErrorFromStereoCalib - rmsErrorFromReprojectedImgPts), testcase);
  1283. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  1284. return;
  1285. }
  1286. /* ----- Compare per view rms re-projection errors ----- */
  1287. CV_Assert(rmsErrorPerView1.size() == (size_t)nframes);
  1288. CV_Assert(rmsErrorPerViewFromReprojectedImgPts1.size() == (size_t)nframes);
  1289. CV_Assert(rmsErrorPerView2.size() == (size_t)nframes);
  1290. CV_Assert(rmsErrorPerViewFromReprojectedImgPts2.size() == (size_t)nframes);
  1291. int code1 = compare(&rmsErrorPerView1[0], &rmsErrorPerViewFromReprojectedImgPts1[0], nframes,
  1292. maxDiffBtwRmsErrors, "per view errors vector");
  1293. int code2 = compare(&rmsErrorPerView2[0], &rmsErrorPerViewFromReprojectedImgPts2[0], nframes,
  1294. maxDiffBtwRmsErrors, "per view errors vector");
  1295. if (code1 < 0)
  1296. {
  1297. ts->printf(cvtest::TS::LOG,
  1298. "Some of the per view rms reprojection errors differ between calibration function and reprojected "
  1299. "points, for the first camera, testcase %d\n",
  1300. testcase);
  1301. ts->set_failed_test_info(code1);
  1302. return;
  1303. }
  1304. if (code2 < 0)
  1305. {
  1306. ts->printf(cvtest::TS::LOG,
  1307. "Some of the per view rms reprojection errors differ between calibration function and reprojected "
  1308. "points, for the second camera, testcase %d\n",
  1309. testcase);
  1310. ts->set_failed_test_info(code2);
  1311. return;
  1312. }
  1313. Mat R1, R2, P1, P2, Q;
  1314. Rect roi1, roi2;
  1315. rectify(M1, D1, M2, D2, imgsize, R, T, R1, R2, P1, P2, Q, 1, imgsize, &roi1, &roi2, 0);
  1316. Mat eye33 = Mat::eye(3,3,CV_64F);
  1317. Mat R1t = R1.t(), R2t = R2.t();
  1318. if( cvtest::norm(R1t*R1 - eye33, NORM_L2) > 0.01 ||
  1319. cvtest::norm(R2t*R2 - eye33, NORM_L2) > 0.01 ||
  1320. abs(determinant(F)) > 0.01)
  1321. {
  1322. ts->printf( cvtest::TS::LOG, "The computed (by rectify) R1 and R2 are not orthogonal,"
  1323. "or the computed (by calibrate) F is not singular, testcase %d\n", testcase);
  1324. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  1325. return;
  1326. }
  1327. if(!checkPandROI(testcase, M1, D1, R1, P1, imgsize, roi1))
  1328. {
  1329. ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
  1330. return;
  1331. }
  1332. if(!checkPandROI(testcase, M2, D2, R2, P2, imgsize, roi2))
  1333. {
  1334. ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
  1335. return;
  1336. }
  1337. //check that Tx after rectification is equal to distance between cameras
  1338. double tx = fabs(P2.at<double>(0, 3) / P2.at<double>(0, 0));
  1339. if (fabs(tx - cvtest::norm(T, NORM_L2)) > 1e-5)
  1340. {
  1341. ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
  1342. return;
  1343. }
  1344. //check that Q reprojects points before the camera
  1345. double testPoint[4] = {0.0, 0.0, 100.0, 1.0};
  1346. Mat reprojectedTestPoint = Q * Mat_<double>(4, 1, testPoint);
  1347. CV_Assert(reprojectedTestPoint.type() == CV_64FC1);
  1348. if( reprojectedTestPoint.at<double>(2) / reprojectedTestPoint.at<double>(3) < 0 )
  1349. {
  1350. ts->printf( cvtest::TS::LOG, "A point after rectification is reprojected behind the camera, testcase %d\n", testcase);
  1351. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  1352. }
  1353. //check that Q reprojects the same points as reconstructed by triangulation
  1354. const float minCoord = -300.0f;
  1355. const float maxCoord = 300.0f;
  1356. const float minDisparity = 0.1f;
  1357. const float maxDisparity = 60.0f;
  1358. const int pointsCount = 500;
  1359. const float requiredAccuracy = 1e-3f;
  1360. const float allowToFail = 0.2f; // 20%
  1361. RNG& rng = ts->get_rng();
  1362. Mat projectedPoints_1(2, pointsCount, CV_32FC1);
  1363. Mat projectedPoints_2(2, pointsCount, CV_32FC1);
  1364. Mat disparities(1, pointsCount, CV_32FC1);
  1365. rng.fill(projectedPoints_1, RNG::UNIFORM, minCoord, maxCoord);
  1366. rng.fill(disparities, RNG::UNIFORM, minDisparity, maxDisparity);
  1367. projectedPoints_2.row(0) = projectedPoints_1.row(0) - disparities;
  1368. Mat ys_2 = projectedPoints_2.row(1);
  1369. projectedPoints_1.row(1).copyTo(ys_2);
  1370. Mat points4d;
  1371. triangulate(P1, P2, projectedPoints_1, projectedPoints_2, points4d);
  1372. Mat homogeneousPoints4d = points4d.t();
  1373. const int dimension = 4;
  1374. homogeneousPoints4d = homogeneousPoints4d.reshape(dimension);
  1375. Mat triangulatedPoints;
  1376. convertPointsFromHomogeneous(homogeneousPoints4d, triangulatedPoints);
  1377. Mat sparsePoints;
  1378. sparsePoints.push_back(projectedPoints_1);
  1379. sparsePoints.push_back(disparities);
  1380. sparsePoints = sparsePoints.t();
  1381. sparsePoints = sparsePoints.reshape(3);
  1382. Mat reprojectedPoints;
  1383. perspectiveTransform(sparsePoints, reprojectedPoints, Q);
  1384. Mat diff;
  1385. absdiff(triangulatedPoints, reprojectedPoints, diff);
  1386. Mat mask = diff > requiredAccuracy;
  1387. mask = mask.reshape(1);
  1388. mask = mask.col(0) | mask.col(1) | mask.col(2);
  1389. int numFailed = countNonZero(mask);
  1390. #if 0
  1391. std::cout << "numFailed=" << numFailed << std::endl;
  1392. for (int i = 0; i < triangulatedPoints.rows; i++)
  1393. {
  1394. if (mask.at<uchar>(i))
  1395. {
  1396. // failed points usually have 'w'~0 (points4d[3])
  1397. std::cout << "i=" << i << " triangulatePoints=" << triangulatedPoints.row(i) << " reprojectedPoints=" << reprojectedPoints.row(i) << std::endl <<
  1398. " points4d=" << points4d.col(i).t() << " projectedPoints_1=" << projectedPoints_1.col(i).t() << " disparities=" << disparities.col(i).t() << std::endl;
  1399. }
  1400. }
  1401. #endif
  1402. if (numFailed >= allowToFail * pointsCount)
  1403. {
  1404. ts->printf( cvtest::TS::LOG, "Points reprojected with a matrix Q and points reconstructed by triangulation are different (tolerance=%g, failed=%d), testcase %d\n",
  1405. requiredAccuracy, numFailed, testcase);
  1406. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  1407. }
  1408. //check correctMatches
  1409. const float constraintAccuracy = 1e-5f;
  1410. Mat newPoints1, newPoints2;
  1411. Mat points1 = projectedPoints_1.t();
  1412. points1 = points1.reshape(2, 1);
  1413. Mat points2 = projectedPoints_2.t();
  1414. points2 = points2.reshape(2, 1);
  1415. correctMatches(F, points1, points2, newPoints1, newPoints2);
  1416. Mat newHomogeneousPoints1, newHomogeneousPoints2;
  1417. convertPointsToHomogeneous(newPoints1, newHomogeneousPoints1);
  1418. convertPointsToHomogeneous(newPoints2, newHomogeneousPoints2);
  1419. newHomogeneousPoints1 = newHomogeneousPoints1.reshape(1);
  1420. newHomogeneousPoints2 = newHomogeneousPoints2.reshape(1);
  1421. Mat typedF;
  1422. F.convertTo(typedF, newHomogeneousPoints1.type());
  1423. for (int i = 0; i < newHomogeneousPoints1.rows; ++i)
  1424. {
  1425. Mat error = newHomogeneousPoints2.row(i) * typedF * newHomogeneousPoints1.row(i).t();
  1426. CV_Assert(error.rows == 1 && error.cols == 1);
  1427. if (cvtest::norm(error, NORM_L2) > constraintAccuracy)
  1428. {
  1429. ts->printf( cvtest::TS::LOG, "Epipolar constraint is violated after correctMatches, testcase %d\n", testcase);
  1430. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  1431. }
  1432. }
  1433. // rectifyUncalibrated
  1434. CV_Assert( imgpt1.size() == imgpt2.size() );
  1435. Mat _imgpt1( total, 1, CV_32FC2 ), _imgpt2( total, 1, CV_32FC2 );
  1436. vector<vector<Point2f> >::const_iterator iit1 = imgpt1.begin();
  1437. vector<vector<Point2f> >::const_iterator iit2 = imgpt2.begin();
  1438. for( int pi = 0; iit1 != imgpt1.end(); ++iit1, ++iit2 )
  1439. {
  1440. vector<Point2f>::const_iterator pit1 = iit1->begin();
  1441. vector<Point2f>::const_iterator pit2 = iit2->begin();
  1442. CV_Assert( iit1->size() == iit2->size() );
  1443. for( ; pit1 != iit1->end(); ++pit1, ++pit2, pi++ )
  1444. {
  1445. _imgpt1.at<Point2f>(pi,0) = Point2f( pit1->x, pit1->y );
  1446. _imgpt2.at<Point2f>(pi,0) = Point2f( pit2->x, pit2->y );
  1447. }
  1448. }
  1449. Mat _M1, _M2, _D1, _D2;
  1450. vector<Mat> _R1, _R2, _T1, _T2;
  1451. calibrateCamera( objpt, imgpt1, imgsize, _M1, _D1, _R1, _T1, 0 );
  1452. calibrateCamera( objpt, imgpt2, imgsize, _M2, _D2, _R2, _T2, 0 );
  1453. undistortPoints( _imgpt1, _imgpt1, _M1, _D1, Mat(), _M1 );
  1454. undistortPoints( _imgpt2, _imgpt2, _M2, _D2, Mat(), _M2 );
  1455. Mat matF, _H1, _H2;
  1456. matF = findFundamentalMat( _imgpt1, _imgpt2 );
  1457. rectifyUncalibrated( _imgpt1, _imgpt2, matF, imgsize, _H1, _H2 );
  1458. Mat rectifPoints1, rectifPoints2;
  1459. perspectiveTransform( _imgpt1, rectifPoints1, _H1 );
  1460. perspectiveTransform( _imgpt2, rectifPoints2, _H2 );
  1461. bool verticalStereo = abs(P2.at<double>(0,3)) < abs(P2.at<double>(1,3));
  1462. double maxDiff_c = 0, maxDiff_uc = 0;
  1463. for( int i = 0, k = 0; i < nframes; i++ )
  1464. {
  1465. vector<Point2f> temp[2];
  1466. undistortPoints(imgpt1[i], temp[0], M1, D1, R1, P1);
  1467. undistortPoints(imgpt2[i], temp[1], M2, D2, R2, P2);
  1468. for( int j = 0; j < npoints; j++, k++ )
  1469. {
  1470. double diff_c = verticalStereo ? abs(temp[0][j].x - temp[1][j].x) : abs(temp[0][j].y - temp[1][j].y);
  1471. Point2f d = rectifPoints1.at<Point2f>(k,0) - rectifPoints2.at<Point2f>(k,0);
  1472. double diff_uc = verticalStereo ? abs(d.x) : abs(d.y);
  1473. maxDiff_c = max(maxDiff_c, diff_c);
  1474. maxDiff_uc = max(maxDiff_uc, diff_uc);
  1475. if( maxDiff_c > maxScanlineDistErr_c )
  1476. {
  1477. ts->printf( cvtest::TS::LOG, "The distance between %s coordinates is too big(=%g) (used calibrated stereo), testcase %d\n",
  1478. verticalStereo ? "x" : "y", diff_c, testcase);
  1479. ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
  1480. return;
  1481. }
  1482. if( maxDiff_uc > maxScanlineDistErr_uc )
  1483. {
  1484. ts->printf( cvtest::TS::LOG, "The distance between %s coordinates is too big(=%g) (used uncalibrated stereo), testcase %d\n",
  1485. verticalStereo ? "x" : "y", diff_uc, testcase);
  1486. ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
  1487. return;
  1488. }
  1489. }
  1490. }
  1491. ts->printf( cvtest::TS::LOG, "Testcase %d. Max distance (calibrated) =%g\n"
  1492. "Max distance (uncalibrated) =%g\n", testcase, maxDiff_c, maxDiff_uc );
  1493. }
  1494. }
  1495. //-------------------------------- CV_StereoCalibrationTest_CPP ------------------------------
  1496. class CV_StereoCalibrationTest_CPP : public CV_StereoCalibrationTest
  1497. {
  1498. public:
  1499. CV_StereoCalibrationTest_CPP() {}
  1500. protected:
  1501. virtual double calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
  1502. const vector<vector<Point2f> >& imagePoints1,
  1503. const vector<vector<Point2f> >& imagePoints2,
  1504. Mat& cameraMatrix1, Mat& distCoeffs1,
  1505. Mat& cameraMatrix2, Mat& distCoeffs2,
  1506. Size imageSize, Mat& R, Mat& T,
  1507. Mat& E, Mat& F,
  1508. std::vector<RotMat>& rotationMatrices, std::vector<Vec3d>& translationVectors,
  1509. vector<double>& perViewErrors1, vector<double>& perViewErrors2,
  1510. TermCriteria criteria, int flags );
  1511. virtual void rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
  1512. const Mat& cameraMatrix2, const Mat& distCoeffs2,
  1513. Size imageSize, const Mat& R, const Mat& T,
  1514. Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
  1515. double alpha, Size newImageSize,
  1516. Rect* validPixROI1, Rect* validPixROI2, int flags );
  1517. virtual bool rectifyUncalibrated( const Mat& points1,
  1518. const Mat& points2, const Mat& F, Size imgSize,
  1519. Mat& H1, Mat& H2, double threshold=5 );
  1520. virtual void triangulate( const Mat& P1, const Mat& P2,
  1521. const Mat &points1, const Mat &points2,
  1522. Mat &points4D );
  1523. virtual void correct( const Mat& F,
  1524. const Mat &points1, const Mat &points2,
  1525. Mat &newPoints1, Mat &newPoints2 );
  1526. };
  1527. double CV_StereoCalibrationTest_CPP::calibrateStereoCamera( const vector<vector<Point3f> >& objectPoints,
  1528. const vector<vector<Point2f> >& imagePoints1,
  1529. const vector<vector<Point2f> >& imagePoints2,
  1530. Mat& cameraMatrix1, Mat& distCoeffs1,
  1531. Mat& cameraMatrix2, Mat& distCoeffs2,
  1532. Size imageSize, Mat& R, Mat& T,
  1533. Mat& E, Mat& F,
  1534. std::vector<RotMat>& rotationMatrices, std::vector<Vec3d>& translationVectors,
  1535. vector<double>& perViewErrors1, vector<double>& perViewErrors2,
  1536. TermCriteria criteria, int flags )
  1537. {
  1538. vector<Mat> rvecs, tvecs;
  1539. Mat perViewErrorsMat;
  1540. double avgErr = stereoCalibrate( objectPoints, imagePoints1, imagePoints2,
  1541. cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,
  1542. imageSize, R, T, E, F,
  1543. rvecs, tvecs, perViewErrorsMat,
  1544. flags, criteria );
  1545. size_t numImgs = imagePoints1.size();
  1546. if (perViewErrors1.size() != numImgs)
  1547. {
  1548. perViewErrors1.resize(numImgs);
  1549. }
  1550. if (perViewErrors2.size() != numImgs)
  1551. {
  1552. perViewErrors2.resize(numImgs);
  1553. }
  1554. for (size_t i = 0; i < numImgs; i++)
  1555. {
  1556. perViewErrors1[i] = perViewErrorsMat.at<double>((int)i, 0);
  1557. perViewErrors2[i] = perViewErrorsMat.at<double>((int)i, 1);
  1558. }
  1559. if (rotationMatrices.size() != numImgs)
  1560. {
  1561. rotationMatrices.resize(numImgs);
  1562. }
  1563. if (translationVectors.size() != numImgs)
  1564. {
  1565. translationVectors.resize(numImgs);
  1566. }
  1567. for (size_t i = 0; i < numImgs; i++)
  1568. {
  1569. Mat r9;
  1570. cv::Rodrigues( rvecs[i], r9 );
  1571. r9.convertTo(rotationMatrices[i], CV_64F);
  1572. tvecs[i].convertTo(translationVectors[i], CV_64F);
  1573. }
  1574. return avgErr;
  1575. }
  1576. void CV_StereoCalibrationTest_CPP::rectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
  1577. const Mat& cameraMatrix2, const Mat& distCoeffs2,
  1578. Size imageSize, const Mat& R, const Mat& T,
  1579. Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
  1580. double alpha, Size newImageSize,
  1581. Rect* validPixROI1, Rect* validPixROI2, int flags )
  1582. {
  1583. stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,
  1584. imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize,validPixROI1, validPixROI2 );
  1585. }
  1586. bool CV_StereoCalibrationTest_CPP::rectifyUncalibrated( const Mat& points1,
  1587. const Mat& points2, const Mat& F, Size imgSize, Mat& H1, Mat& H2, double threshold )
  1588. {
  1589. return stereoRectifyUncalibrated( points1, points2, F, imgSize, H1, H2, threshold );
  1590. }
  1591. void CV_StereoCalibrationTest_CPP::triangulate( const Mat& P1, const Mat& P2,
  1592. const Mat &points1, const Mat &points2,
  1593. Mat &points4D )
  1594. {
  1595. triangulatePoints(P1, P2, points1, points2, points4D);
  1596. }
  1597. void CV_StereoCalibrationTest_CPP::correct( const Mat& F,
  1598. const Mat &points1, const Mat &points2,
  1599. Mat &newPoints1, Mat &newPoints2 )
  1600. {
  1601. correctMatches(F, points1, points2, newPoints1, newPoints2);
  1602. }
  1603. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1604. TEST(Calib3d_CalibrateCamera_CPP, regression) { CV_CameraCalibrationTest_CPP test; test.safe_run(); }
  1605. TEST(Calib3d_CalibrationMatrixValues_CPP, accuracy) { CV_CalibrationMatrixValuesTest_CPP test; test.safe_run(); }
  1606. TEST(Calib3d_ProjectPoints_CPP, regression) { CV_ProjectPointsTest_CPP test; test.safe_run(); }
  1607. TEST(Calib3d_ProjectPoints_CPP, inputShape)
  1608. {
  1609. Matx31d rvec = Matx31d::zeros();
  1610. Matx31d tvec(0, 0, 1);
  1611. Matx33d cameraMatrix = Matx33d::eye();
  1612. const float L = 0.1f;
  1613. {
  1614. //3xN 1-channel
  1615. Mat objectPoints = (Mat_<float>(3, 2) << -L, L,
  1616. L, L,
  1617. 0, 0);
  1618. vector<Point2f> imagePoints;
  1619. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1620. EXPECT_EQ(objectPoints.cols, static_cast<int>(imagePoints.size()));
  1621. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<float>::epsilon());
  1622. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<float>::epsilon());
  1623. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<float>::epsilon());
  1624. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<float>::epsilon());
  1625. }
  1626. {
  1627. //Nx2 1-channel
  1628. Mat objectPoints = (Mat_<float>(2, 3) << -L, L, 0,
  1629. L, L, 0);
  1630. vector<Point2f> imagePoints;
  1631. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1632. EXPECT_EQ(objectPoints.rows, static_cast<int>(imagePoints.size()));
  1633. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<float>::epsilon());
  1634. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<float>::epsilon());
  1635. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<float>::epsilon());
  1636. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<float>::epsilon());
  1637. }
  1638. {
  1639. //1xN 3-channel
  1640. Mat objectPoints(1, 2, CV_32FC3);
  1641. objectPoints.at<Vec3f>(0,0) = Vec3f(-L, L, 0);
  1642. objectPoints.at<Vec3f>(0,1) = Vec3f(L, L, 0);
  1643. vector<Point2f> imagePoints;
  1644. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1645. EXPECT_EQ(objectPoints.cols, static_cast<int>(imagePoints.size()));
  1646. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<float>::epsilon());
  1647. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<float>::epsilon());
  1648. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<float>::epsilon());
  1649. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<float>::epsilon());
  1650. }
  1651. {
  1652. //Nx1 3-channel
  1653. Mat objectPoints(2, 1, CV_32FC3);
  1654. objectPoints.at<Vec3f>(0,0) = Vec3f(-L, L, 0);
  1655. objectPoints.at<Vec3f>(1,0) = Vec3f(L, L, 0);
  1656. vector<Point2f> imagePoints;
  1657. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1658. EXPECT_EQ(objectPoints.rows, static_cast<int>(imagePoints.size()));
  1659. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<float>::epsilon());
  1660. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<float>::epsilon());
  1661. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<float>::epsilon());
  1662. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<float>::epsilon());
  1663. }
  1664. {
  1665. //vector<Point3f>
  1666. vector<Point3f> objectPoints;
  1667. objectPoints.push_back(Point3f(-L, L, 0));
  1668. objectPoints.push_back(Point3f(L, L, 0));
  1669. vector<Point2f> imagePoints;
  1670. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1671. EXPECT_EQ(objectPoints.size(), imagePoints.size());
  1672. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<float>::epsilon());
  1673. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<float>::epsilon());
  1674. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<float>::epsilon());
  1675. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<float>::epsilon());
  1676. }
  1677. {
  1678. //vector<Point3d>
  1679. vector<Point3d> objectPoints;
  1680. objectPoints.push_back(Point3d(-L, L, 0));
  1681. objectPoints.push_back(Point3d(L, L, 0));
  1682. vector<Point2d> imagePoints;
  1683. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1684. EXPECT_EQ(objectPoints.size(), imagePoints.size());
  1685. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<double>::epsilon());
  1686. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<double>::epsilon());
  1687. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<double>::epsilon());
  1688. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<double>::epsilon());
  1689. }
  1690. }
  1691. TEST(Calib3d_ProjectPoints_CPP, outputShape)
  1692. {
  1693. Matx31d rvec = Matx31d::zeros();
  1694. Matx31d tvec(0, 0, 1);
  1695. Matx33d cameraMatrix = Matx33d::eye();
  1696. const float L = 0.1f;
  1697. {
  1698. vector<Point3f> objectPoints;
  1699. objectPoints.push_back(Point3f(-L, L, 0));
  1700. objectPoints.push_back(Point3f( L, L, 0));
  1701. objectPoints.push_back(Point3f( L, -L, 0));
  1702. //Mat --> will be Nx1 2-channel
  1703. Mat imagePoints;
  1704. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1705. EXPECT_EQ(static_cast<int>(objectPoints.size()), imagePoints.rows);
  1706. EXPECT_NEAR(imagePoints.at<Vec2f>(0,0)(0), -L, std::numeric_limits<float>::epsilon());
  1707. EXPECT_NEAR(imagePoints.at<Vec2f>(0,0)(1), L, std::numeric_limits<float>::epsilon());
  1708. EXPECT_NEAR(imagePoints.at<Vec2f>(1,0)(0), L, std::numeric_limits<float>::epsilon());
  1709. EXPECT_NEAR(imagePoints.at<Vec2f>(1,0)(1), L, std::numeric_limits<float>::epsilon());
  1710. EXPECT_NEAR(imagePoints.at<Vec2f>(2,0)(0), L, std::numeric_limits<float>::epsilon());
  1711. EXPECT_NEAR(imagePoints.at<Vec2f>(2,0)(1), -L, std::numeric_limits<float>::epsilon());
  1712. }
  1713. {
  1714. vector<Point3f> objectPoints;
  1715. objectPoints.push_back(Point3f(-L, L, 0));
  1716. objectPoints.push_back(Point3f( L, L, 0));
  1717. objectPoints.push_back(Point3f( L, -L, 0));
  1718. //Nx1 2-channel
  1719. Mat imagePoints(3,1,CV_32FC2);
  1720. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1721. EXPECT_EQ(static_cast<int>(objectPoints.size()), imagePoints.rows);
  1722. EXPECT_NEAR(imagePoints.at<Vec2f>(0,0)(0), -L, std::numeric_limits<float>::epsilon());
  1723. EXPECT_NEAR(imagePoints.at<Vec2f>(0,0)(1), L, std::numeric_limits<float>::epsilon());
  1724. EXPECT_NEAR(imagePoints.at<Vec2f>(1,0)(0), L, std::numeric_limits<float>::epsilon());
  1725. EXPECT_NEAR(imagePoints.at<Vec2f>(1,0)(1), L, std::numeric_limits<float>::epsilon());
  1726. EXPECT_NEAR(imagePoints.at<Vec2f>(2,0)(0), L, std::numeric_limits<float>::epsilon());
  1727. EXPECT_NEAR(imagePoints.at<Vec2f>(2,0)(1), -L, std::numeric_limits<float>::epsilon());
  1728. }
  1729. {
  1730. vector<Point3f> objectPoints;
  1731. objectPoints.push_back(Point3f(-L, L, 0));
  1732. objectPoints.push_back(Point3f( L, L, 0));
  1733. objectPoints.push_back(Point3f( L, -L, 0));
  1734. //1xN 2-channel
  1735. Mat imagePoints(1,3,CV_32FC2);
  1736. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1737. EXPECT_EQ(static_cast<int>(objectPoints.size()), imagePoints.cols);
  1738. EXPECT_NEAR(imagePoints.at<Vec2f>(0,0)(0), -L, std::numeric_limits<float>::epsilon());
  1739. EXPECT_NEAR(imagePoints.at<Vec2f>(0,0)(1), L, std::numeric_limits<float>::epsilon());
  1740. EXPECT_NEAR(imagePoints.at<Vec2f>(0,1)(0), L, std::numeric_limits<float>::epsilon());
  1741. EXPECT_NEAR(imagePoints.at<Vec2f>(0,1)(1), L, std::numeric_limits<float>::epsilon());
  1742. EXPECT_NEAR(imagePoints.at<Vec2f>(0,2)(0), L, std::numeric_limits<float>::epsilon());
  1743. EXPECT_NEAR(imagePoints.at<Vec2f>(0,2)(1), -L, std::numeric_limits<float>::epsilon());
  1744. }
  1745. {
  1746. vector<Point3f> objectPoints;
  1747. objectPoints.push_back(Point3f(-L, L, 0));
  1748. objectPoints.push_back(Point3f(L, L, 0));
  1749. //vector<Point2f>
  1750. vector<Point2f> imagePoints;
  1751. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1752. EXPECT_EQ(objectPoints.size(), imagePoints.size());
  1753. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<float>::epsilon());
  1754. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<float>::epsilon());
  1755. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<float>::epsilon());
  1756. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<float>::epsilon());
  1757. }
  1758. {
  1759. vector<Point3d> objectPoints;
  1760. objectPoints.push_back(Point3d(-L, L, 0));
  1761. objectPoints.push_back(Point3d(L, L, 0));
  1762. //vector<Point2d>
  1763. vector<Point2d> imagePoints;
  1764. projectPoints(objectPoints, rvec, tvec, cameraMatrix, noArray(), imagePoints);
  1765. EXPECT_EQ(objectPoints.size(), imagePoints.size());
  1766. EXPECT_NEAR(imagePoints[0].x, -L, std::numeric_limits<double>::epsilon());
  1767. EXPECT_NEAR(imagePoints[0].y, L, std::numeric_limits<double>::epsilon());
  1768. EXPECT_NEAR(imagePoints[1].x, L, std::numeric_limits<double>::epsilon());
  1769. EXPECT_NEAR(imagePoints[1].y, L, std::numeric_limits<double>::epsilon());
  1770. }
  1771. }
  1772. TEST(Calib3d_StereoCalibrate_CPP, regression) { CV_StereoCalibrationTest_CPP test; test.safe_run(); }
  1773. TEST(Calib3d_StereoCalibrate_CPP, extended)
  1774. {
  1775. cvtest::TS* ts = cvtest::TS::ptr();
  1776. String filepath = cv::format("%scv/stereo/case%d/", ts->get_data_path().c_str(), 1 );
  1777. Mat left = imread(filepath+"left01.png");
  1778. Mat right = imread(filepath+"right01.png");
  1779. if(left.empty() || right.empty())
  1780. {
  1781. ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
  1782. return;
  1783. }
  1784. vector<vector<Point2f> > imgpt1(1), imgpt2(1);
  1785. vector<vector<Point3f> > objpt(1);
  1786. Size patternSize(9, 6), imageSize(640, 480);
  1787. bool found1 = findChessboardCorners(left, patternSize, imgpt1[0]);
  1788. bool found2 = findChessboardCorners(right, patternSize, imgpt2[0]);
  1789. if(!found1 || !found2)
  1790. {
  1791. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  1792. return;
  1793. }
  1794. for( int j = 0; j < patternSize.width*patternSize.height; j++ )
  1795. objpt[0].push_back(Point3f((float)(j%patternSize.width), (float)(j/patternSize.width), 0.f));
  1796. Mat K1, K2, c1, c2, R, T, E, F, err;
  1797. int flags = 0;
  1798. double res0 = stereoCalibrate( objpt, imgpt1, imgpt2,
  1799. K1, c1, K2, c2,
  1800. imageSize, R, T, E, F, err, flags);
  1801. flags = CALIB_USE_EXTRINSIC_GUESS;
  1802. double res1 = stereoCalibrate( objpt, imgpt1, imgpt2,
  1803. K1, c1, K2, c2,
  1804. imageSize, R, T, E, F, err, flags);
  1805. EXPECT_LE(res1, res0);
  1806. EXPECT_TRUE(err.total() == 2);
  1807. }
  1808. TEST(Calib3d_StereoCalibrate, regression_10791)
  1809. {
  1810. const Matx33d M1(
  1811. 853.1387981631528, 0, 704.154907802121,
  1812. 0, 853.6445089162528, 520.3600712930319,
  1813. 0, 0, 1
  1814. );
  1815. const Matx33d M2(
  1816. 848.6090216909176, 0, 701.6162856852185,
  1817. 0, 849.7040162357157, 509.1864036137,
  1818. 0, 0, 1
  1819. );
  1820. const Matx<double, 14, 1> D1(-6.463598629567206, 79.00104930508179, -0.0001006144444464403, -0.0005437499822299972,
  1821. 12.56900616588467, -6.056719942752855, 76.3842481414836, 45.57460250612659,
  1822. 0, 0, 0, 0, 0, 0);
  1823. const Matx<double, 14, 1> D2(0.6123436439798265, -0.4671756923224087, -0.0001261947899033442, -0.000597334584036978,
  1824. -0.05660119809538371, 1.037075740629769, -0.3076042835831711, -0.2502169324283623,
  1825. 0, 0, 0, 0, 0, 0);
  1826. const Matx33d R(
  1827. 0.9999926627018476, -0.0001095586963765905, 0.003829169539302921,
  1828. 0.0001021735876758584, 0.9999981346680941, 0.0019287874145156,
  1829. -0.003829373712065528, -0.001928382022437616, 0.9999908085776333
  1830. );
  1831. const Matx31d T(-58.9161771697128, -0.01581306249996402, -0.8492960216760961);
  1832. const Size imageSize(1280, 960);
  1833. Mat R1, R2, P1, P2, Q;
  1834. Rect roi1, roi2;
  1835. stereoRectify(M1, D1, M2, D2, imageSize, R, T,
  1836. R1, R2, P1, P2, Q,
  1837. CALIB_ZERO_DISPARITY, 1, imageSize, &roi1, &roi2);
  1838. EXPECT_GE(roi1.area(), 400*300) << roi1;
  1839. EXPECT_GE(roi2.area(), 400*300) << roi2;
  1840. }
  1841. TEST(Calib3d_StereoCalibrate, regression_11131)
  1842. {
  1843. const Matx33d M1(
  1844. 1457.572438721727, 0, 1212.945694211622,
  1845. 0, 1457.522226502963, 1007.32058848921,
  1846. 0, 0, 1
  1847. );
  1848. const Matx33d M2(
  1849. 1460.868570835972, 0, 1215.024068023046,
  1850. 0, 1460.791367088, 1011.107202932225,
  1851. 0, 0, 1
  1852. );
  1853. const Matx<double, 5, 1> D1(0, 0, 0, 0, 0);
  1854. const Matx<double, 5, 1> D2(0, 0, 0, 0, 0);
  1855. const Matx33d R(
  1856. 0.9985404059825475, 0.02963547172078553, -0.04515303352041626,
  1857. -0.03103795276460111, 0.9990471552537432, -0.03068268351343364,
  1858. 0.04420071389006859, 0.03203935697372317, 0.9985087763742083
  1859. );
  1860. const Matx31d T(0.9995500167379527, 0.0116311595111068, 0.02764923448462666);
  1861. const Size imageSize(2456, 2058);
  1862. Mat R1, R2, P1, P2, Q;
  1863. Rect roi1, roi2;
  1864. stereoRectify(M1, D1, M2, D2, imageSize, R, T,
  1865. R1, R2, P1, P2, Q,
  1866. CALIB_ZERO_DISPARITY, 1, imageSize, &roi1, &roi2);
  1867. EXPECT_GT(P1.at<double>(0, 0), 0);
  1868. EXPECT_GT(P2.at<double>(0, 0), 0);
  1869. EXPECT_GT(R1.at<double>(0, 0), 0);
  1870. EXPECT_GT(R2.at<double>(0, 0), 0);
  1871. EXPECT_GE(roi1.area(), 400*300) << roi1;
  1872. EXPECT_GE(roi2.area(), 400*300) << roi2;
  1873. }
  1874. TEST(Calib3d_StereoCalibrate, regression_23305)
  1875. {
  1876. const Matx33d M1(
  1877. 850, 0, 640,
  1878. 0, 850, 640,
  1879. 0, 0, 1
  1880. );
  1881. const Matx34d P1_gold(
  1882. 850, 0, 640, 0,
  1883. 0, 850, 640, 0,
  1884. 0, 0, 1, 0
  1885. );
  1886. const Matx33d M2(
  1887. 850, 0, 640,
  1888. 0, 850, 640,
  1889. 0, 0, 1
  1890. );
  1891. const Matx34d P2_gold(
  1892. 850, 0, 640, -2*850, // correcponds to T(-2., 0., 0.)
  1893. 0, 850, 640, 0,
  1894. 0, 0, 1, 0
  1895. );
  1896. const Matx<double, 5, 1> D1(0, 0, 0, 0, 0);
  1897. const Matx<double, 5, 1> D2(0, 0, 0, 0, 0);
  1898. const Matx33d R(
  1899. 1., 0., 0.,
  1900. 0., 1., 0.,
  1901. 0., 0., 1.
  1902. );
  1903. const Matx31d T(-2., 0., 0.);
  1904. const Size imageSize(1280, 1280);
  1905. Mat R1, R2, P1, P2, Q;
  1906. Rect roi1, roi2;
  1907. stereoRectify(M1, D1, M2, D2, imageSize, R, T,
  1908. R1, R2, P1, P2, Q,
  1909. CALIB_ZERO_DISPARITY, 0, imageSize, &roi1, &roi2);
  1910. EXPECT_EQ(cv::norm(P1, P1_gold), 0.);
  1911. EXPECT_EQ(cv::norm(P2, P2_gold), 0.);
  1912. }
  1913. TEST(Calib3d_Triangulate, accuracy)
  1914. {
  1915. // the testcase from http://code.opencv.org/issues/4334
  1916. {
  1917. double P1data[] = { 250, 0, 200, 0, 0, 250, 150, 0, 0, 0, 1, 0 };
  1918. double P2data[] = { 250, 0, 200, -250, 0, 250, 150, 0, 0, 0, 1, 0 };
  1919. Mat P1(3, 4, CV_64F, P1data), P2(3, 4, CV_64F, P2data);
  1920. float x1data[] = { 200.f, 0.f };
  1921. float x2data[] = { 170.f, 1.f };
  1922. float Xdata[] = { 0.f, -5.f, 25/3.f };
  1923. Mat x1(2, 1, CV_32F, x1data);
  1924. Mat x2(2, 1, CV_32F, x2data);
  1925. Mat res0(1, 3, CV_32F, Xdata);
  1926. Mat res_, res;
  1927. triangulatePoints(P1, P2, x1, x2, res_);
  1928. cv::transpose(res_, res_); // TODO cvtest (transpose doesn't support inplace)
  1929. convertPointsFromHomogeneous(res_, res);
  1930. res = res.reshape(1, 1);
  1931. cout << "[1]:" << endl;
  1932. cout << "\tres0: " << res0 << endl;
  1933. cout << "\tres: " << res << endl;
  1934. ASSERT_LE(cvtest::norm(res, res0, NORM_INF), 1e-1);
  1935. }
  1936. // another testcase http://code.opencv.org/issues/3461
  1937. {
  1938. Matx33d K1(6137.147949, 0.000000, 644.974609,
  1939. 0.000000, 6137.147949, 573.442749,
  1940. 0.000000, 0.000000, 1.000000);
  1941. Matx33d K2(6137.147949, 0.000000, 644.674438,
  1942. 0.000000, 6137.147949, 573.079834,
  1943. 0.000000, 0.000000, 1.000000);
  1944. Matx34d RT1(1, 0, 0, 0,
  1945. 0, 1, 0, 0,
  1946. 0, 0, 1, 0);
  1947. Matx34d RT2(0.998297, 0.0064108, -0.0579766, 143.614334,
  1948. -0.0065818, 0.999975, -0.00275888, -5.160085,
  1949. 0.0579574, 0.00313577, 0.998314, 96.066109);
  1950. Matx34d P1 = K1*RT1;
  1951. Matx34d P2 = K2*RT2;
  1952. float x1data[] = { 438.f, 19.f };
  1953. float x2data[] = { 452.363600f, 16.452225f };
  1954. float Xdata[] = { -81.049530f, -215.702804f, 2401.645449f };
  1955. Mat x1(2, 1, CV_32F, x1data);
  1956. Mat x2(2, 1, CV_32F, x2data);
  1957. Mat res0(1, 3, CV_32F, Xdata);
  1958. Mat res_, res;
  1959. triangulatePoints(P1, P2, x1, x2, res_);
  1960. cv::transpose(res_, res_); // TODO cvtest (transpose doesn't support inplace)
  1961. convertPointsFromHomogeneous(res_, res);
  1962. res = res.reshape(1, 1);
  1963. cout << "[2]:" << endl;
  1964. cout << "\tres0: " << res0 << endl;
  1965. cout << "\tres: " << res << endl;
  1966. ASSERT_LE(cvtest::norm(res, res0, NORM_INF), 2);
  1967. }
  1968. }
  1969. ///////////////////////////////////////////////////////////////////////////////////////////////////
  1970. TEST(CV_RecoverPoseTest, regression_15341)
  1971. {
  1972. // initialize test data
  1973. const int invalid_point_count = 2;
  1974. const float _points1_[] = {
  1975. 1537.7f, 166.8f,
  1976. 1599.1f, 179.6f,
  1977. 1288.0f, 207.5f,
  1978. 1507.1f, 193.2f,
  1979. 1742.7f, 210.0f,
  1980. 1041.6f, 271.7f,
  1981. 1591.8f, 247.2f,
  1982. 1524.0f, 261.3f,
  1983. 1330.3f, 285.0f,
  1984. 1403.1f, 284.0f,
  1985. 1506.6f, 342.9f,
  1986. 1502.8f, 347.3f,
  1987. 1344.9f, 364.9f,
  1988. 0.0f, 0.0f // last point is initial invalid
  1989. };
  1990. const float _points2_[] = {
  1991. 1533.4f, 532.9f,
  1992. 1596.6f, 552.4f,
  1993. 1277.0f, 556.4f,
  1994. 1502.1f, 557.6f,
  1995. 1744.4f, 601.3f,
  1996. 1023.0f, 612.6f,
  1997. 1589.2f, 621.6f,
  1998. 1519.4f, 629.0f,
  1999. 1320.3f, 637.3f,
  2000. 1395.2f, 642.2f,
  2001. 1501.5f, 710.3f,
  2002. 1497.6f, 714.2f,
  2003. 1335.1f, 719.61f,
  2004. 1000.0f, 1000.0f // last point is initial invalid
  2005. };
  2006. vector<Point2f> _points1; Mat(14, 1, CV_32FC2, (void*)_points1_).copyTo(_points1);
  2007. vector<Point2f> _points2; Mat(14, 1, CV_32FC2, (void*)_points2_).copyTo(_points2);
  2008. const int point_count = (int) _points1.size();
  2009. CV_Assert(point_count == (int) _points2.size());
  2010. // camera matrix with both focal lengths = 1, and principal point = (0, 0)
  2011. const Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
  2012. // camera matrix with focal lengths 0.5 and 0.6 respectively and principal point = (100, 200)
  2013. double cameraMatrix2Data[] = { 0.5, 0, 100,
  2014. 0, 0.6, 200,
  2015. 0, 0, 1 };
  2016. const Mat cameraMatrix2( 3, 3, CV_64F, cameraMatrix2Data );
  2017. // zero and nonzero distortion coefficients
  2018. double nonZeroDistCoeffsData[] = { 0.01, 0.0001, 0, 0, 1e-04, 0.2, 0.02, 0.0002 }; // k1, k2, p1, p2, k3, k4, k5, k6
  2019. vector<Mat> distCoeffsList = {Mat::zeros(1, 5, CV_64F), Mat{1, 8, CV_64F, nonZeroDistCoeffsData}};
  2020. const auto &zeroDistCoeffs = distCoeffsList[0];
  2021. int Inliers = 0;
  2022. const int ntests = 3;
  2023. for (int testcase = 1; testcase <= ntests; ++testcase)
  2024. {
  2025. if (testcase == 1) // testcase with vector input data
  2026. {
  2027. // init temporary test data
  2028. vector<unsigned char> mask(point_count);
  2029. vector<Point2f> points1(_points1);
  2030. vector<Point2f> points2(_points2);
  2031. // Estimation of fundamental matrix using the RANSAC algorithm
  2032. Mat E, E2, R, t;
  2033. // Check pose when camera matrices are different.
  2034. for (const auto &distCoeffs: distCoeffsList)
  2035. {
  2036. E = findEssentialMat(points1, points2, cameraMatrix, distCoeffs, cameraMatrix2, distCoeffs, RANSAC, 0.999, 1.0, mask);
  2037. recoverPose(points1, points2, cameraMatrix, distCoeffs, cameraMatrix2, distCoeffs, E2, R, t, RANSAC, 0.999, 1.0, mask);
  2038. EXPECT_LT(cv::norm(E, E2, NORM_INF), 1e-4) <<
  2039. "Two big difference between the same essential matrices computed using different functions with different cameras, testcase " << testcase;
  2040. EXPECT_EQ(0, (int)mask[13]) << "Detecting outliers in function failed with different cameras, testcase " << testcase;
  2041. }
  2042. // Check pose when camera matrices are the same.
  2043. E = findEssentialMat(points1, points2, cameraMatrix, RANSAC, 0.999, 1.0, mask);
  2044. E2 = findEssentialMat(points1, points2, cameraMatrix, zeroDistCoeffs, cameraMatrix, zeroDistCoeffs, RANSAC, 0.999, 1.0, mask);
  2045. EXPECT_LT(cv::norm(E, E2, NORM_INF), 1e-4) <<
  2046. "Two big difference between the same essential matrices computed using different functions with same cameras, testcase " << testcase;
  2047. EXPECT_EQ(0, (int)mask[13]) << "Detecting outliers in function findEssentialMat failed with same cameras, testcase " << testcase;
  2048. points2[12] = Point2f(0.0f, 0.0f); // provoke another outlier detection for recover Pose
  2049. Inliers = recoverPose(E, points1, points2, cameraMatrix, R, t, mask);
  2050. EXPECT_EQ(0, (int)mask[12]) << "Detecting outliers in function failed with same cameras, testcase " << testcase;
  2051. }
  2052. else // testcase with mat input data
  2053. {
  2054. Mat points1(_points1, true);
  2055. Mat points2(_points2, true);
  2056. Mat mask;
  2057. if (testcase == 2)
  2058. {
  2059. // init temporary testdata
  2060. mask = Mat::zeros(point_count, 1, CV_8UC1);
  2061. }
  2062. else // testcase == 3 - with transposed mask
  2063. {
  2064. mask = Mat::zeros(1, point_count, CV_8UC1);
  2065. }
  2066. // Estimation of fundamental matrix using the RANSAC algorithm
  2067. Mat E, E2, R, t;
  2068. // Check pose when camera matrices are different.
  2069. for (const auto &distCoeffs: distCoeffsList)
  2070. {
  2071. E = findEssentialMat(points1, points2, cameraMatrix, distCoeffs, cameraMatrix2, distCoeffs, RANSAC, 0.999, 1.0, mask);
  2072. recoverPose(points1, points2, cameraMatrix, distCoeffs, cameraMatrix2, distCoeffs, E2, R, t, RANSAC, 0.999, 1.0, mask);
  2073. EXPECT_LT(cv::norm(E, E2, NORM_INF), 1e-4) <<
  2074. "Two big difference between the same essential matrices computed using different functions with different cameras, testcase " << testcase;
  2075. EXPECT_EQ(0, (int)mask.at<unsigned char>(13)) << "Detecting outliers in function failed with different cameras, testcase " << testcase;
  2076. }
  2077. // Check pose when camera matrices are the same.
  2078. E = findEssentialMat(points1, points2, cameraMatrix, RANSAC, 0.999, 1.0, mask);
  2079. E2 = findEssentialMat(points1, points2, cameraMatrix, zeroDistCoeffs, cameraMatrix, zeroDistCoeffs, RANSAC, 0.999, 1.0, mask);
  2080. EXPECT_LT(cv::norm(E, E2, NORM_INF), 1e-4) <<
  2081. "Two big difference between the same essential matrices computed using different functions with same cameras, testcase " << testcase;
  2082. EXPECT_EQ(0, (int)mask.at<unsigned char>(13)) << "Detecting outliers in function findEssentialMat failed with same cameras, testcase " << testcase;
  2083. points2.at<Point2f>(12) = Point2f(0.0f, 0.0f); // provoke an outlier detection
  2084. Inliers = recoverPose(E, points1, points2, cameraMatrix, R, t, mask);
  2085. EXPECT_EQ(0, (int)mask.at<unsigned char>(12)) << "Detecting outliers in function failed with same cameras, testcase " << testcase;
  2086. }
  2087. EXPECT_EQ(Inliers, point_count - invalid_point_count) <<
  2088. "Number of inliers differs from expected number of inliers, testcase " << testcase;
  2089. }
  2090. }
  2091. }} // namespace