Merge pull request #20012 from ivashmak:bugfix_solvepnp
authorMaksym Ivashechkin <maksimivashechkin@gmail.com>
Wed, 19 May 2021 09:09:46 +0000 (10:09 +0100)
committerGitHub <noreply@github.com>
Wed, 19 May 2021 09:09:46 +0000 (12:09 +0300)
* fix inliers in solvePnPRansac

* fix inliers in test_usac

* fix inliers in test_usac

modules/calib3d/src/solvepnp.cpp
modules/calib3d/src/usac/ransac_solvers.cpp
modules/calib3d/test/test_usac.cpp

index b3ce1aa514a56f4401bb756a0d293b85ee3bce2f..1e5591f710b93256c0d2a541fa2c905fd86938d9 100644 (file)
@@ -402,7 +402,14 @@ bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints,
     Ptr<usac::RansacOutput> ransac_output;
     if (usac::run(model_params, imagePoints, objectPoints, model_params->getRandomGeneratorState(),
             ransac_output, cameraMatrix, noArray(), distCoeffs, noArray())) {
-        usac::saveMask(inliers, ransac_output->getInliersMask());
+        if (inliers.needed()) {
+            const auto &inliers_mask = ransac_output->getInliersMask();
+            Mat inliers_;
+            for (int i = 0; i < (int)inliers_mask.size(); i++)
+                if (inliers_mask[i])
+                    inliers_.push_back(i);
+            inliers_.copyTo(inliers);
+        }
         const Mat &model = ransac_output->getModel();
         model.col(0).copyTo(rvec);
         model.col(1).copyTo(tvec);
index eb7e1776787070b705f80b1675d551b8703bf91c..b7f3e6e0c15a0def4951c01cd31eed26153b4c60 100644 (file)
@@ -539,23 +539,26 @@ Mat findEssentialMat (InputArray points1, InputArray points2, InputArray cameraM
 bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints,
        InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec,
        bool /*useExtrinsicGuess*/, int max_iters, float thr, double conf,
-       OutputArray mask, int method) {
+       OutputArray inliers, int method) {
     Ptr<Model> params;
     setParameters(method, params, cameraMatrix.empty() ? EstimationMethod ::P6P : EstimationMethod ::P3P,
-            thr, max_iters, conf, mask.needed());
+            thr, max_iters, conf, inliers.needed());
     Ptr<RansacOutput> ransac_output;
     if (run(params, imagePoints, objectPoints, params->getRandomGeneratorState(),
             ransac_output, cameraMatrix, noArray(), distCoeffs, noArray())) {
-        saveMask(mask, ransac_output->getInliersMask());
+        if (inliers.needed()) {
+            const auto &inliers_mask = ransac_output->getInliersMask();
+            Mat inliers_;
+            for (int i = 0; i < (int)inliers_mask.size(); i++)
+                if (inliers_mask[i])
+                    inliers_.push_back(i);
+            inliers_.copyTo(inliers);
+        }
         const Mat &model = ransac_output->getModel();
         model.col(0).copyTo(rvec);
         model.col(1).copyTo(tvec);
         return true;
     }
-    if (mask.needed()){
-        mask.create(std::max(objectPoints.getMat().rows, objectPoints.getMat().cols), 1, CV_8U);
-        mask.setTo(Scalar::all(0));
-    }
     return false;
 }
 
index fb5641bd1ec6c87073aa8f6faf79fe1b653e00ce..6e6d8cecf392b31215752c15e3e4fbfc1000606d 100644 (file)
@@ -345,11 +345,16 @@ TEST(usac_P3P, accuracy) {
                    log(1 - pow(inl_ratio, 3 /* sample size */));
 
         for (auto flag : flags) {
+            std::vector<int> inliers;
             cv::Mat rvec, tvec, mask, R, P;
             CV_Assert(cv::solvePnPRansac(obj_pts, img_pts, K1, cv::noArray(), rvec, tvec,
-                    false, (int)max_iters, (float)thr, conf, mask, flag));
+                    false, (int)max_iters, (float)thr, conf, inliers, flag));
             cv::Rodrigues(rvec, R);
             cv::hconcat(K1 * R, K1 * tvec, P);
+            mask.create(pts_size, 1, CV_8U);
+            mask.setTo(Scalar::all(0));
+            for (auto inl : inliers)
+                mask.at<uchar>(inl) = true;
             checkInliersMask(TestSolver ::PnP, inl_size, thr, img_pts, obj_pts, P, mask);
         }
     }
@@ -416,19 +421,27 @@ TEST(usac_testUsacParams, accuracy) {
             // CV_Error(cv::Error::StsError, "Essential matrix estimation failed!");
     }
 
+    std::vector<int> inliers(pts_size);
     // P3P
     inl_size = generatePoints(rng, pts1, pts2, K1, K2, false, pts_size, TestSolver::PnP,
     getInlierRatio(usac_params.maxIterations, 3, usac_params.confidence), 0.01, gt_inliers);
-    CV_Assert(cv::solvePnPRansac(pts2, pts1, K1, dist_coeff, rvec, tvec, mask, usac_params));
+    CV_Assert(cv::solvePnPRansac(pts2, pts1, K1, dist_coeff, rvec, tvec, inliers, usac_params));
     cv::Rodrigues(rvec, R); cv::hconcat(K1 * R, K1 * tvec, model);
+    mask.create(pts_size, 1, CV_8U);
+    mask.setTo(Scalar::all(0));
+    for (auto inl : inliers)
+        mask.at<uchar>(inl) = true;
     checkInliersMask(TestSolver::PnP, inl_size, usac_params.threshold, pts1, pts2, model, mask);
 
     // P6P
     inl_size = generatePoints(rng, pts1, pts2, K1, K2, false, pts_size, TestSolver::PnP,
     getInlierRatio(usac_params.maxIterations, 6, usac_params.confidence), 0.1, gt_inliers);
     cv::Mat K_est;
-    CV_Assert(cv::solvePnPRansac(pts2, pts1, K_est, dist_coeff, rvec, tvec, mask, usac_params));
+    CV_Assert(cv::solvePnPRansac(pts2, pts1, K_est, dist_coeff, rvec, tvec, inliers, usac_params));
     cv::Rodrigues(rvec, R); cv::hconcat(K_est * R, K_est * tvec, model);
+    mask.setTo(Scalar::all(0));
+    for (auto inl : inliers)
+        mask.at<uchar>(inl) = true;
     checkInliersMask(TestSolver::PnP, inl_size, usac_params.threshold, pts1, pts2, model, mask);
 
     // Affine2D