Fix hardcoded maxIters
authorSergei Shutov <serg.shutov@gmail.com>
Thu, 15 Dec 2022 12:00:48 +0000 (14:00 +0200)
committerAlexander Smorkalov <alexander.smorkalov@xperience.ai>
Wed, 21 Dec 2022 06:51:59 +0000 (09:51 +0300)
modules/calib3d/src/five-point.cpp
modules/calib3d/src/usac.hpp
modules/calib3d/src/usac/ransac_solvers.cpp
modules/calib3d/test/test_usac.cpp

index 735f8e6..9b82dcb 100644 (file)
@@ -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);
index 8daf4f5..2a3e0eb 100644 (file)
@@ -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,
index fe64907..cca1340 100644 (file)
@@ -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<Model> params;
-    setParameters(method, params, EstimationMethod::Essential, thr, 1000, prob, mask.needed());
+    setParameters(method, params, EstimationMethod::Essential, thr, maxIters, prob, mask.needed());
     Ptr<RansacOutput> ransac_output;
     if (run(params, points1, points2, params->getRandomGeneratorState(),
             ransac_output, cameraMatrix1, cameraMatrix1, noArray(), noArray())) {
index 8297ab1..fc36e8c 100644 (file)
@@ -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<UsacMethod> usac_Essential;
 
-TEST(usac_Essential, accuracy) {
+TEST_P(usac_Essential, accuracy) {
+    int method = GetParam();
     std::vector<int> 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<double>(0,0) + K1.at<double>(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<double>(0,0) + K1.at<double>(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<int> gt_inliers;
     const int pts_size = 3000;