From 3cfe7375816b5a22191033f75fa06cfb42a4e41c Mon Sep 17 00:00:00 2001 From: Sergei Shutov Date: Thu, 15 Dec 2022 14:00:48 +0200 Subject: [PATCH] Fix hardcoded maxIters --- modules/calib3d/src/five-point.cpp | 4 +- modules/calib3d/src/usac.hpp | 3 +- modules/calib3d/src/usac/ransac_solvers.cpp | 4 +- modules/calib3d/test/test_usac.cpp | 69 ++++++++++++++++----- 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/modules/calib3d/src/five-point.cpp b/modules/calib3d/src/five-point.cpp index 735f8e6b85..9b82dcb11c 100644 --- a/modules/calib3d/src/five-point.cpp +++ b/modules/calib3d/src/five-point.cpp @@ -433,9 +433,9 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArr { CV_INSTRUMENT_REGION(); - if (method >= 32 && method <= 38) + if (method >= USAC_DEFAULT && method <= USAC_MAGSAC) return usac::findEssentialMat(_points1, _points2, _cameraMatrix, - method, prob, threshold, _mask); + method, prob, threshold, _mask, maxIters); Mat points1, points2, cameraMatrix; _points1.getMat().convertTo(points1, CV_64F); diff --git a/modules/calib3d/src/usac.hpp b/modules/calib3d/src/usac.hpp index 8daf4f52a9..2a3e0eb7fc 100644 --- a/modules/calib3d/src/usac.hpp +++ b/modules/calib3d/src/usac.hpp @@ -801,7 +801,8 @@ bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints, Mat findEssentialMat( InputArray points1, InputArray points2, InputArray cameraMatrix1, int method, double prob, - double threshold, OutputArray mask); + double threshold, OutputArray mask, + int maxIters); Mat estimateAffine2D(InputArray from, InputArray to, OutputArray inliers, int method, double ransacReprojThreshold, int maxIters, diff --git a/modules/calib3d/src/usac/ransac_solvers.cpp b/modules/calib3d/src/usac/ransac_solvers.cpp index fe64907ec0..cca13405bc 100644 --- a/modules/calib3d/src/usac/ransac_solvers.cpp +++ b/modules/calib3d/src/usac/ransac_solvers.cpp @@ -520,9 +520,9 @@ Mat findFundamentalMat( InputArray points1, InputArray points2, int method, doub } Mat findEssentialMat (InputArray points1, InputArray points2, InputArray cameraMatrix1, - int method, double prob, double thr, OutputArray mask) { + int method, double prob, double thr, OutputArray mask, int maxIters) { Ptr params; - setParameters(method, params, EstimationMethod::Essential, thr, 1000, prob, mask.needed()); + setParameters(method, params, EstimationMethod::Essential, thr, maxIters, prob, mask.needed()); Ptr ransac_output; if (run(params, points1, points2, params->getRandomGeneratorState(), ransac_output, cameraMatrix1, cameraMatrix1, noArray(), noArray())) { diff --git a/modules/calib3d/test/test_usac.cpp b/modules/calib3d/test/test_usac.cpp index 8297ab1de8..fc36e8c945 100644 --- a/modules/calib3d/test/test_usac.cpp +++ b/modules/calib3d/test/test_usac.cpp @@ -299,8 +299,11 @@ TEST(usac_Fundamental, regression_19639) EXPECT_TRUE(m.empty()); } +CV_ENUM(UsacMethod, USAC_DEFAULT, USAC_ACCURATE, USAC_PROSAC, USAC_FAST, USAC_MAGSAC) +typedef TestWithParam usac_Essential; -TEST(usac_Essential, accuracy) { +TEST_P(usac_Essential, accuracy) { + int method = GetParam(); std::vector gt_inliers; const int pts_size = 1500; cv::RNG &rng = cv::theRNG(); @@ -312,26 +315,58 @@ TEST(usac_Essential, accuracy) { int inl_size = generatePoints(rng, pts1, pts2, K1, K2, false /*two calib*/, pts_size, TestSolver ::Fundam, inl_ratio, 0.01 /*noise std, works bad with high noise*/, gt_inliers); const double conf = 0.99, thr = 1.; - for (auto flag : flags) { - cv::Mat mask, E; - try { - E = cv::findEssentialMat(pts1, pts2, K1, flag, conf, thr, mask); - } catch (cv::Exception &e) { - if (e.code != cv::Error::StsNotImplemented) - FAIL() << "Essential matrix estimation failed!\n"; - else continue; - } - // calibrate points - cv::Mat cpts1_3d, cpts2_3d; - cv::vconcat(pts1, cv::Mat::ones(1, pts1.cols, pts1.type()), cpts1_3d); - cv::vconcat(pts2, cv::Mat::ones(1, pts2.cols, pts2.type()), cpts2_3d); - cpts1_3d = K1.inv() * cpts1_3d; cpts2_3d = K1.inv() * cpts2_3d; - checkInliersMask(TestSolver::Essen, inl_size, thr / ((K1.at(0,0) + K1.at(1,1)) / 2), - cpts1_3d.rowRange(0,2), cpts2_3d.rowRange(0,2), E, mask); + cv::Mat mask, E; + try { + E = cv::findEssentialMat(pts1, pts2, K1, method, conf, thr, mask); + } catch (cv::Exception &e) { + if (e.code != cv::Error::StsNotImplemented) + FAIL() << "Essential matrix estimation failed!\n"; + else continue; + } + // calibrate points + cv::Mat cpts1_3d, cpts2_3d; + cv::vconcat(pts1, cv::Mat::ones(1, pts1.cols, pts1.type()), cpts1_3d); + cv::vconcat(pts2, cv::Mat::ones(1, pts2.cols, pts2.type()), cpts2_3d); + cpts1_3d = K1.inv() * cpts1_3d; cpts2_3d = K1.inv() * cpts2_3d; + checkInliersMask(TestSolver::Essen, inl_size, thr / ((K1.at(0,0) + K1.at(1,1)) / 2), + cpts1_3d.rowRange(0,2), cpts2_3d.rowRange(0,2), E, mask); + } +} + +TEST_P(usac_Essential, maxiters) { + int method = GetParam(); + cv::RNG &rng = cv::theRNG(); + cv::Mat mask; + cv::Mat K1 = cv::Mat(cv::Matx33d(1, 0, 0, + 0, 1, 0, + 0, 0, 1.)); + const double conf = 0.99, thr = 0.5; + int roll_results_sum = 0; + + for (int iters = 0; iters < 10; iters++) { + cv::Mat E1, E2; + try { + cv::Mat pts1 = cv::Mat(2, 50, CV_64F); + cv::Mat pts2 = cv::Mat(2, 50, CV_64F); + rng.fill(pts1, cv::RNG::UNIFORM, 0.0, 1.0); + rng.fill(pts2, cv::RNG::UNIFORM, 0.0, 1.0); + + E1 = cv::findEssentialMat(pts1, pts2, K1, method, conf, thr, 1, mask); + E2 = cv::findEssentialMat(pts1, pts2, K1, method, conf, thr, 1000, mask); + + if (E1.dims != E2.dims) { continue; } + roll_results_sum += cv::norm(E1, E2, NORM_L1) != 0; + } catch (cv::Exception &e) { + if (e.code != cv::Error::StsNotImplemented) + FAIL() << "Essential matrix estimation failed!\n"; + else continue; } + EXPECT_NE(roll_results_sum, 0); } } +INSTANTIATE_TEST_CASE_P(Calib3d, usac_Essential, UsacMethod::all()); + TEST(usac_P3P, accuracy) { std::vector gt_inliers; const int pts_size = 3000;