Merge pull request #20012 from ivashmak:bugfix_solvepnp

* fix inliers in solvePnPRansac

* fix inliers in test_usac

* fix inliers in test_usac
This commit is contained in:
Maksym Ivashechkin 2021-05-19 10:09:46 +01:00 committed by GitHub
parent 7d66f1e391
commit 527d86a93d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 11 deletions

View File

@ -402,7 +402,14 @@ bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints,
Ptr<usac::RansacOutput> ransac_output; Ptr<usac::RansacOutput> ransac_output;
if (usac::run(model_params, imagePoints, objectPoints, model_params->getRandomGeneratorState(), if (usac::run(model_params, imagePoints, objectPoints, model_params->getRandomGeneratorState(),
ransac_output, cameraMatrix, noArray(), distCoeffs, noArray())) { 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(); const Mat &model = ransac_output->getModel();
model.col(0).copyTo(rvec); model.col(0).copyTo(rvec);
model.col(1).copyTo(tvec); model.col(1).copyTo(tvec);

View File

@ -539,23 +539,26 @@ Mat findEssentialMat (InputArray points1, InputArray points2, InputArray cameraM
bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints, bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints,
InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec,
bool /*useExtrinsicGuess*/, int max_iters, float thr, double conf, bool /*useExtrinsicGuess*/, int max_iters, float thr, double conf,
OutputArray mask, int method) { OutputArray inliers, int method) {
Ptr<Model> params; Ptr<Model> params;
setParameters(method, params, cameraMatrix.empty() ? EstimationMethod ::P6P : EstimationMethod ::P3P, 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; Ptr<RansacOutput> ransac_output;
if (run(params, imagePoints, objectPoints, params->getRandomGeneratorState(), if (run(params, imagePoints, objectPoints, params->getRandomGeneratorState(),
ransac_output, cameraMatrix, noArray(), distCoeffs, noArray())) { 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(); const Mat &model = ransac_output->getModel();
model.col(0).copyTo(rvec); model.col(0).copyTo(rvec);
model.col(1).copyTo(tvec); model.col(1).copyTo(tvec);
return true; 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; return false;
} }

View File

@ -345,11 +345,16 @@ TEST(usac_P3P, accuracy) {
log(1 - pow(inl_ratio, 3 /* sample size */)); log(1 - pow(inl_ratio, 3 /* sample size */));
for (auto flag : flags) { for (auto flag : flags) {
std::vector<int> inliers;
cv::Mat rvec, tvec, mask, R, P; cv::Mat rvec, tvec, mask, R, P;
CV_Assert(cv::solvePnPRansac(obj_pts, img_pts, K1, cv::noArray(), rvec, tvec, 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::Rodrigues(rvec, R);
cv::hconcat(K1 * R, K1 * tvec, P); 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); 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!"); // CV_Error(cv::Error::StsError, "Essential matrix estimation failed!");
} }
std::vector<int> inliers(pts_size);
// P3P // P3P
inl_size = generatePoints(rng, pts1, pts2, K1, K2, false, pts_size, TestSolver::PnP, 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); 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); 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); checkInliersMask(TestSolver::PnP, inl_size, usac_params.threshold, pts1, pts2, model, mask);
// P6P // P6P
inl_size = generatePoints(rng, pts1, pts2, K1, K2, false, pts_size, TestSolver::PnP, 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); getInlierRatio(usac_params.maxIterations, 6, usac_params.confidence), 0.1, gt_inliers);
cv::Mat K_est; 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); 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); checkInliersMask(TestSolver::PnP, inl_size, usac_params.threshold, pts1, pts2, model, mask);
// Affine2D // Affine2D