@@ -153,7 +153,7 @@ class CV_solvePnPRansac_Test : public cvtest::BaseTest
153
153
return isTestSuccess;
154
154
}
155
155
156
- void run (int )
156
+ virtual void run (int )
157
157
{
158
158
ts->set_failed_test_info (cvtest::TS::OK);
159
159
@@ -253,6 +253,100 @@ class CV_solvePnP_Test : public CV_solvePnPRansac_Test
253
253
}
254
254
};
255
255
256
+ class CV_solveP3P_Test : public CV_solvePnPRansac_Test
257
+ {
258
+ public:
259
+ CV_solveP3P_Test ()
260
+ {
261
+ eps[SOLVEPNP_P3P] = 1.0e-4 ;
262
+ eps[SOLVEPNP_AP3P] = 1.0e-4 ;
263
+ totalTestsCount = 1000 ;
264
+ }
265
+
266
+ ~CV_solveP3P_Test () {}
267
+ protected:
268
+ virtual bool runTest (RNG& rng, int mode, int method, const vector<Point3f>& points, const double * epsilon, double & maxError)
269
+ {
270
+ std::vector<Mat> rvecs, tvecs;
271
+ Mat trueRvec, trueTvec;
272
+ Mat intrinsics, distCoeffs;
273
+ generateCameraMatrix (intrinsics, rng);
274
+ if (mode == 0 )
275
+ distCoeffs = Mat::zeros (4 , 1 , CV_64FC1);
276
+ else
277
+ generateDistCoeffs (distCoeffs, rng);
278
+ generatePose (trueRvec, trueTvec, rng);
279
+
280
+ std::vector<Point3f> opoints;
281
+ opoints = std::vector<Point3f>(points.begin (), points.begin ()+3 );
282
+
283
+ vector<Point2f> projectedPoints;
284
+ projectedPoints.resize (opoints.size ());
285
+ projectPoints (Mat (opoints), trueRvec, trueTvec, intrinsics, distCoeffs, projectedPoints);
286
+
287
+ int num_of_solutions = solveP3P (opoints, projectedPoints, intrinsics, distCoeffs, rvecs, tvecs, method);
288
+ if (num_of_solutions != (int ) rvecs.size () || num_of_solutions != (int ) tvecs.size () || num_of_solutions == 0 )
289
+ return false ;
290
+
291
+ double min_rvecDiff = DBL_MAX, min_tvecDiff = DBL_MAX;
292
+ for (unsigned int i = 0 ; i < rvecs.size (); ++i) {
293
+ double rvecDiff = norm (rvecs[i]-trueRvec);
294
+ min_rvecDiff = std::min (rvecDiff, min_rvecDiff);
295
+ }
296
+ for (unsigned int i = 0 ; i < tvecs.size (); ++i) {
297
+ double tvecDiff = norm (tvecs[i]-trueTvec);
298
+ min_tvecDiff = std::min (tvecDiff, min_tvecDiff);
299
+ }
300
+ bool isTestSuccess = min_rvecDiff < epsilon[method] && min_tvecDiff < epsilon[method];
301
+
302
+ double error = std::max (min_rvecDiff, min_tvecDiff);
303
+ if (error > maxError)
304
+ maxError = error;
305
+
306
+ return isTestSuccess;
307
+ }
308
+
309
+ virtual void run (int )
310
+ {
311
+ ts->set_failed_test_info (cvtest::TS::OK);
312
+
313
+ vector<Point3f> points, points_dls;
314
+ const int pointsCount = 500 ;
315
+ points.resize (pointsCount);
316
+ generate3DPointCloud (points);
317
+
318
+ const int methodsCount = 2 ;
319
+ int methods[methodsCount] = {SOLVEPNP_P3P, SOLVEPNP_AP3P};
320
+ RNG rng = ts->get_rng ();
321
+
322
+ for (int mode = 0 ; mode < 2 ; mode++)
323
+ {
324
+ for (int method = 0 ; method < methodsCount; method++)
325
+ {
326
+ double maxError = 0 ;
327
+ int successfulTestsCount = 0 ;
328
+ for (int testIndex = 0 ; testIndex < totalTestsCount; testIndex++)
329
+ {
330
+ if (runTest (rng, mode, methods[method], points, eps, maxError))
331
+ successfulTestsCount++;
332
+ }
333
+ // cout << maxError << " " << successfulTestsCount << endl;
334
+ if (successfulTestsCount < 0.7 *totalTestsCount)
335
+ {
336
+ ts->printf ( cvtest::TS::LOG, " Invalid accuracy for method %d, failed %d tests from %d, maximum error equals %f, distortion mode equals %d\n " ,
337
+ method, totalTestsCount - successfulTestsCount, totalTestsCount, maxError, mode);
338
+ ts->set_failed_test_info (cvtest::TS::FAIL_BAD_ACCURACY);
339
+ }
340
+ cout << " mode: " << mode << " , method: " << method << " -> "
341
+ << ((double )successfulTestsCount / totalTestsCount) * 100 << " %"
342
+ << " (err < " << maxError << " )" << endl;
343
+ }
344
+ }
345
+ }
346
+ };
347
+
348
+
349
+ TEST (Calib3d_SolveP3P, accuracy) { CV_solveP3P_Test test; test.safe_run ();}
256
350
TEST (Calib3d_SolvePnPRansac, accuracy) { CV_solvePnPRansac_Test test; test.safe_run (); }
257
351
TEST (Calib3d_SolvePnP, accuracy) { CV_solvePnP_Test test; test.safe_run (); }
258
352
0 commit comments