test_cameracalibration.cpp 87 KB

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