Skip to content

Unexpected exception in solvePnPRansac caused by input points#19253

Merged
alalek merged 2 commits intoopencv:3.4from
mightbxg:bugfix_PnPRansac
Mar 11, 2021
Merged

Unexpected exception in solvePnPRansac caused by input points#19253
alalek merged 2 commits intoopencv:3.4from
mightbxg:bugfix_PnPRansac

Conversation

@mightbxg
Copy link
Copy Markdown
Contributor

@mightbxg mightbxg commented Jan 4, 2021

resolves #17799
relates #14447

When solvePnPRansac is called, it will do RANSAC and then call solvePnPGeneric, in which cvFindExtrinsicCameraParams2 will be called. Sometimes the point-pairs after RANSAC are less than 6, but the DLT algorithm used in cvFindExtrinsicCameraParams2 (SOLVEPNP_ITERATIVE) needs at least 6 points, in this case the function will throw an error. See solvePnPGeneric, cvFindExtrinsicCameraParams2.

The proper logic for solvePnPGeneric should be returning false (0 or -1) instead of throwing an error to the executable, so I added try-block, just like SOLVEPNP_IPPE below.

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@asmorkalov asmorkalov requested a review from vpisarev January 12, 2021 08:40
@vpisarev
Copy link
Copy Markdown
Contributor

@mightbxg, thank you for the contribution. Maybe, inserting try-catch into solvePnPGeneric is not a good idea. I suggest to insert try-catch into solvePnPRansac or some RANSAC callbacks if it uses ones (I can't remember it right now). This way you will make a pure bugfix instead of bugfix+compatibility break.

BTW, please, keep in mind that in the upcoming OpenCV 5.0 (the "next" branch) the implementation of solvePnP, including the RANSAC flavor, will change. And both in the master branch and the next branch there is new RANSAC framework (called USAC) available that provides much better performance. You are welcome to try it out. If it works well on your dataset, then switching to this USAC is probably a better idea than trying to fix the obsolete solution that will eventually be thrown away.

@vpisarev vpisarev self-assigned this Jan 20, 2021
Copy link
Copy Markdown
Contributor

@vpisarev vpisarev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to move try-catch outside of solvePnPGeneric into solvePnPRansac. Otherwise some user may experience undefined behaviour instead of exception in the corner cases

@asmorkalov
Copy link
Copy Markdown
Contributor

@mightbxg Friendly reminder.

@mightbxg
Copy link
Copy Markdown
Contributor Author

@vpisarev Thanks a lot for you suggestions. I think you are right about not modifying solvePnPGeneric, so I removed the try-catch block and added a point-num-checking in solvePnPRansac before it calls solvePnP. The commit is now amended.

Here is the test data that can reproduce the problem. Load points from the yaml file and call solvePnPRansac using params below, then an error will be thrown out (OpenCV 3.4.12 and 4.5.1 are both affected):

Mat rvec, tvec;
bool ret = solvePnPRansac(pts3d, pts2d, Mat::eye(3, 3, CV_64FC1), noArray(), rvec, tvec, false, 100, 4. / 460.0);

I looked into the document about USAC and it's quite exciting, I will try it later. However, as the traditional solvePnPRansac in OpenCV 3&4 is widely used and may be used for much longer time, I think it's necessary to fix this issue.

@mightbxg mightbxg requested a review from vpisarev January 26, 2021 10:13
Copy link
Copy Markdown
Contributor Author

@mightbxg mightbxg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed try-catch block from solvePnPGeneric. Added a point-num-checking in solvePnPRansac before it calls solvePnP. The commit is amended.

@vpisarev
Copy link
Copy Markdown
Contributor

vpisarev commented Feb 2, 2021

@mightbxg, thank you!
Since you are on it, may I ask you to add a tiny test to
https://github.com/opencv/opencv/blob/3.4/modules/calib3d/test/test_solvepnp_ransac.cpp
that does what you've described?

  1. initialize 2d point and 3d point arrays, e.g. 5 points in each
  2. then call solvePnPRansac enclosed in EXPECT_THROW:
EXPECT_THROW(solvePnPRansac(...), cv::Exception);

@mightbxg
Copy link
Copy Markdown
Contributor Author

mightbxg commented Feb 3, 2021

@mightbxg, thank you!
Since you are on it, may I ask you to add a tiny test to
https://github.com/opencv/opencv/blob/3.4/modules/calib3d/test/test_solvepnp_ransac.cpp
that does what you've described?

  1. initialize 2d point and 3d point arrays, e.g. 5 points in each
  2. then call solvePnPRansac enclosed in EXPECT_THROW:
EXPECT_THROW(solvePnPRansac(...), cv::Exception);

@vpisarev Sorry, I'm not sure about the purpose of adding this test. Is it for showing that the problem was there before fix (as I described before) or the problem is gone after fix?

To clarify, let me describe the problem again. The role of "Exception" is to inform the user of his/her "bad usage". For instance, P3P need 4 points, and when 3 points are input, there should be an Exception to tell the user that the usage is wrong.
However, an Exception caused by intermediate calculation is unexpected. When I call solvePnPRansac with 69 points (data I provided above), then I should get a result (even if it's false) rather than an Exception. Because I cannot determine if the input data is "wrong" before RANSAC calculation.

For the former purpose (reproduce the problem), should I just create an "issue" based on the not-fixed branch 3.4?

For the latter purpose, I presume this test should be added to the pull request. But as the problem is already fixed, solvePnPRansac will return false instead of throwing cv::Exception. Maybe I should enclose solvePnPRansac calling with EXPECT_FALSE instead of EXPECT_THROW? Moreover, should I add a new commit for the test or squash it to the existing commit?

int npoints1 = compressElems(&opoints_inliers[0], mask, 1, npoints);
compressElems(&ipoints_inliers[0], mask, 1, npoints);

if ( flags == SOLVEPNP_ITERATIVE && npoints1 < 6 )
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it is a little bit more complex.

When 3D points are not planar, cvFindExtrinsicCameraParams2 uses DLT algorithm which indeed requires at least 6 points.

But with coplanar 3D points, cvFindExtrinsicCameraParams2 should work with at least 4 points.


BTW, see here: #8782 my previous comment about the behavior of solvePnPRansac and this PR: #9086

In my opinion, behavior of solvePnPRansac is still not totally clear / intuitive.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then cvFindExtrinsicCameraParams2 may get good result with 4 points, but may throw Exception with 5 points.

I think CV_CheckGE in cvFindExtrinsicCameraParams2 is not a good idea. But since it returns void (not bool), throwing Exception may be the only option to inform that the result is bad.

As a result, try-catch seems inevitable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then cvFindExtrinsicCameraParams2 may get good result with 4 points, but may throw Exception with 5 points.

Not sure to follow correctly. In cvFindExtrinsicCameraParams2 it checks first if the 3D points are coplanar. For coplanar case, it should never throw exception, except theoretically for degenerate cases like all collinear points but this is not handled/detected.

And there are already a check for at least 4 points if useExtrinsicGuess is false:

CV_Assert((count >= 4) || (count == 3 && useExtrinsicGuess)); // it is unsafe to call LM optimisation without an extrinsic guess in the case of 3 points. This is because there is no guarantee that it will converge on the correct solution.

Copy link
Copy Markdown
Contributor Author

@mightbxg mightbxg Feb 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cvFindExtrinsicCameraParams2 does check if the 3D points are coplanar. And if not, it may throw exception.

When someone calls cvFindExtrinsicCameraParams2 directly, he can make sure the input points are more than 4. If he knows that the points may not be coplanar, he can make sure the points are more than 6. In this cases, cvFindExtrinsicCameraParams2 won't throw exceptions, because the user calls it in the "right" way.

However, codes in solvePnPRansac does not guarantee that. When the user knows the points used to solve PnP are very likely to be noncoplanar, the only thing he can do is to input as many points as possible (6 at least). But RANSACE procedure (the intermediate calculation) may reduce the points and make them not suitable for cvFindExtrinsicCameraParams2. That's why I think Exception here is not supposed to happen. It's NOT the user's fault.

To fix this, solvePnPRansac should either check the coplanarity before calling solvePnP, or call solvePnP with try-catch. The former solution may add unnecessary calculation.

@alalek
Copy link
Copy Markdown
Member

alalek commented Feb 3, 2021

purpose of adding this test.

Main purpose is avoiding same/similar regressions in the future.

that the problem was there before fix
the problem is gone after fix

These cases should work too (as described - fail before, pass after the fix).

@mightbxg
Copy link
Copy Markdown
Contributor Author

mightbxg commented Feb 4, 2021

I mistakenly force-pushed branch 3.4 to my own branch (mightbxg:bugfix_PnPRansac), and github closed this pull request automatically. Sorry for that. I will reopen this later.

@mightbxg
Copy link
Copy Markdown
Contributor Author

mightbxg commented Feb 4, 2021

@catree Calling solvePnP with try-catch in solvePnPRansac may be better. Test case is added. @alalek @vpisarev

@mightbxg mightbxg reopened this Feb 4, 2021
@asmorkalov asmorkalov requested a review from vpisarev February 4, 2021 07:04
@catree
Copy link
Copy Markdown
Contributor

catree commented Feb 4, 2021

@mightbxg

Calling solvePnP with try-catch in solvePnPRansac may be better.

I have not re-read the code carefully, but one possible other option could be to log somehow the error to warn the user that SOLVEPNP_ITERATIVE was not successful but still returns rvec and tvec solution computed from the Minimal Sample Sets (MSS)?

Because if I recall correctly, to compute solution for the MSS, 5 points are used and EPnP method. Consensus set is also 5 points, so it should be possible to return directly rvec and tvec computed during the MSS step.

@mightbxg
Copy link
Copy Markdown
Contributor Author

mightbxg commented Feb 5, 2021

@catree You are right about the MSS step. It can calculate and return rvec and tvec, even if error occurs in the following steps.

The user can know if SOLVEPNP_ITERATIVE was successful or not by checking the returned bool value of solvePnPRansac.

As a computing library, I don't think OpenCV should "log something" for the user.

@catree
Copy link
Copy Markdown
Contributor

catree commented Feb 5, 2021

@mightbxg

The user can know if SOLVEPNP_ITERATIVE was successful or not by checking the returned bool value of solvePnPRansac.

The thing is that if solvePnPRansac returns false, you are not supposed to use rvec and tvec passed in parameters.
How could you differentiate between the method completely fails and this very specific case where the consensus set is 5 points correctly estimated, but SOLVEPNP_ITERATIVE later fails?

(I don't have the solution.)

(try/catch approach seems fine for me at first sight.)

@mightbxg
Copy link
Copy Markdown
Contributor Author

mightbxg commented Feb 7, 2021

@catree

How could you differentiate between the method completely fails and this very specific case where the consensus set is 5 points correctly estimated, but SOLVEPNP_ITERATIVE later fails?

I got your point. Your opinion is that if the MSS stage passed (EPNP for 5 or more points), then solvePnPRansac should return true, even if SOLVEPNP_ITERATIVE stage fails. Because the result of MSS stage is still "correct" to use.

I agree with that in some degree. But since the user calls solvePnPRansac with flags = SOLVEPNP_ITERATIVE(not SOLVEPNP_EPNP) and input points much more than 6, maybe he only wants the result from ITERATIVE stage (EPNP may have lower precision)?

So, this question seems a little subjective and may need more discussion. The existing code in solvePnPRansac prefer to return false if SOLVEPNP_ITERATIVE stage fails, and my pull request didn't change that.

@catree
Copy link
Copy Markdown
Contributor

catree commented Feb 8, 2021

@mightbxg

I see two approaches with this specific case:

  • log using the OpenCV logging system an info/debug/verbose message to state that SOLVEPNP_ITERATIVE failed due to non coplanar 3D data and less than 6 points, but result from EPnP is still returned
  • return EPnP results and return true

or:

  • return false
  • and also add log info (it does not hurt to add logging info, for instance LOG_LEVEL_DEBUG level will only print in debug build mode)

I have a slight preference for the first approach, but second solution is fine also for me.

In any case, root case of this specific situation should be investigated, because:

  • if you have a bunch of 3D data
  • but the RANSAC method failed to find a consensus set bigger than 5 points
  • it means that the root case can come from the 3D data, 2D data (e.g. very bad 2D features matching, or bad RANSAC parameters (e.g. too strict reprojection error threshold?)

@mightbxg
Copy link
Copy Markdown
Contributor Author

@catree
All right, I think you are right, and I took your first suggestion, commit is now amended.

With this change, the user can choose to accept the result when solvePnPRansac returns true, even if it's calculated by MSS stage. He can also choose to reject it if he thinks the result is not good enough by checking the number of inliers (Apparently, 5 inliers means the result cannot be from ITERATIVE stage).

BTW, I noticed someone else is working on this issue too #19492. His test data seems more concise.

Copy link
Copy Markdown
Contributor Author

@mightbxg mightbxg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solvePnPRansac returns true even if the solvePnP stage failed. In this case, result from MSS stage is taken, and the exception content from solvePnP is put into log.

Copy link
Copy Markdown
Contributor

@catree catree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick review.

Yes, probably we could try to fuse the two PRs.

/cc @Johnzdh

catch (const cv::Exception& e)
{
result = 0;
CV_UNUSED(e);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it needed since it is used in CV_LOG_DEBUG?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure about this, but I have seen same usage in calibinit.cpp. Maybe in Release build, CV_LOG_DEBUG doesn't use e, then CV_UNUSED can supress the warning?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that it is to probably suppress warning in release mode.

Mat camera_mat = Mat::eye(3, 3, CV_64FC1);
Mat rvec, tvec;
vector<uchar> inliers;
bool result = solvePnPRansac(pts3d, pts2d, Mat::eye(3, 3, CV_64FC1), noArray(), rvec, tvec, false, 100, 4. / 460.0, 0.99, inliers);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. / 460.0

Reprojection error is in pixel unit (default value is 8). Wondering if it explains why you only have a consensus set of 5 points?

Copy link
Copy Markdown
Contributor Author

@mightbxg mightbxg Feb 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my test data, the 2D points are from the normalized image coordiante system, that's why the camera matrix is Mat::eye(3, 3, CV_64FC1). So, the reprojection error here is not in pixel unit.

As you can see, the focal length of my camera is about 460.0, and the tolerance of reprojection error is set to 4 pixels. It should be fine.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. I did not see that the camera matrix is identity.

vector<Point3f> pts3d;
vector<Point2f> pts2d;

pts3d = {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the buildbot (https://pullrequest.opencv.org/#/summary/opencv) errors.

This requires C++11 features.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed now.

@mightbxg mightbxg force-pushed the bugfix_PnPRansac branch 2 times, most recently from 4203efa to 1b6cf69 Compare February 11, 2021 05:11
Copy link
Copy Markdown
Contributor Author

@mightbxg mightbxg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes:

  • Store test data with cv::Mat instead of std::vector to avoid c++11 feature (initializer list).
  • Reduce test data to minimum set (6 input points)

Copy link
Copy Markdown
Contributor

@catree catree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor suggestions.

Thanks for your contribution. I am also an external contributor and it is great to see contributions from the community.


TEST(Calib3d_SolvePnPRansac, bad_input_points)
{
Mat pts2d = (Mat_<float>(6, 2) <<
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add some comments before this line to explain this test:

  • with this specific data
  • when computing the final pose using points in the consensus set with SOLVEPNP_ITERATIVE and solvePnP()
  • an exception is thrown from solvePnP because there are 5 non-coplanar 3D points and the DLT algorithm needs at least 6 non-coplanar 3D points
  • with PR Unexpected exception in solvePnPRansac caused by input points #19253 we choose to return true, with the pose estimated from the MSS stage instead of throwing the exception

Copy link
Copy Markdown
Contributor Author

@mightbxg mightbxg Feb 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, it does need some explanation.

@mightbxg mightbxg changed the title False assertion in solvePnPGeneric Unexpected exception in solvePnPRansac caused by input points Feb 12, 2021
@mightbxg
Copy link
Copy Markdown
Contributor Author

@catree @vpisarev @asmorkalov
Please let me know if further modification is needed.

@vpisarev
Copy link
Copy Markdown
Contributor

thank you, looks good to me! 👍

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vpisarev @asmaloney
Need to discuss the change below.

Function result values:

result = solvePnP (1) existed code (2) This PR (3) PR 19492 case4(no PR)
result > 0 true true true true
result<=0 false true (❓) false false
exception exception true (❓) true (❓) false

if( _inliers.needed() )
_inliers.release();

return false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part changes behavior of the case which is not covered by PR's description:

  • result = solvePnP() doesn't throw exception
  • it returns result <= 0

Alternative #19492 preserves behavior of non-exception case.


When I call solvePnPRansac with 69 points (data I provided above), then I should get a result (even if it's false) rather than an Exception.

false code path is changed.

solvePnPRansac returns true even if the solvePnP stage failed. In this case, result from MSS stage is taken, and the exception content from solvePnP is put into log.

Only exception's case is logged, but returned value is forced "true" for other cases too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, the logging strategy here is problematic.

Copy link
Copy Markdown
Member

@alalek alalek Feb 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main question is about the final returned value.

result = solvePnP (1) existed code (2) This PR (3) PR 19492 case4(no PR)
result > 0 true true true true
result<=0 false true (❓) false false
exception exception true (❓) true (❓) false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant to @ someone else (not me)?

@mightbxg
Copy link
Copy Markdown
Contributor Author

@alalek
I have changed the logging strategy so that non-exception case can also be logged.

In conclusion, this PR introduced changes about solvePnPRansac:

  1. The case that error occurs (an Exception is thrown) in solvePnP stage is treated as solvePnP() failing (no solution returned by solvePnPGeneric), and the error info is logged.
  2. solvePnPRansac is considered as success (it returns true) when MSS stage passed but solvePnP stage failed (no solution or error occurs). In this case, result from MSS stage is taken, and an warning message is logged.

The second change is what should be discussed here. Like you've said, the behavior of non-exception case in the existing OpenCV codes is to return false. But I personally agree with @catree, that it should return true to tell the user that the result from MSS stage is also "correct" to use.

@alalek
Copy link
Copy Markdown
Member

alalek commented Feb 19, 2021

So, what is the purpose of this solvePnP() call? Does it becomes as optional result refinement?
Should be guarantee that result is feasible after the main RANSAC code?

Why we can't just tune model_points ( = 5 by default for now) ?

@mightbxg
Copy link
Copy Markdown
Contributor Author

@alalek

  1. With this PR's changes, the solvePnP stage indeed becomes optional result-refinement. However, user can know if the result is from solvePnP stage or MSS stage by checking the number of inliers.
  2. In the existing codes, when solvePnPRansac is called with exactly 5 input points and flags=SOLVEPNP_ITERATIVE, it will call solvePnP with flags=SOLVEPNP_EPNP (just like the MSS stage), and return ture (with EPnP result). So, I think the result after RANSAC is just fine.
  3. Increasing model_points is a potential solution (need discussion). But if we change it to 6, then what will we do when the number of input points is 5? Should we use other ransac kernel method rather than EPnP or just return false?

@catree
Copy link
Copy Markdown
Contributor

catree commented Feb 19, 2021

Just did a very quick look on the new comments. Need to re-read everything later in details, and think more about the behavior changes / matrix.


Increasing model_points is a potential solution (need discussion).

Normally, the RANSAC algorithm is based upon the assumption to use the minimal number of data to compute a solution, and then check if this solution agrees with the whole data. The solution that gives the bigger consensus set is retained.
Then, the final solution is computed using all the data in the consensus set.

So increasing the number of model_points to 6 will increase the combinatorial. From my knowledge, 4 points is enough for 6D pose computation. In OpenCV, 5 points is used because I think it is recommended to use 5 points in the EPnP paper, and EPnP is the default method for the MSS stage (there are exceptions depending on the input solvePnPRansac parameters...).

There are I think some workshop on this topic:

@catree
Copy link
Copy Markdown
Contributor

catree commented Feb 21, 2021

We should try to fix only this specific case:

  • somehow the biggest consensus set is only 5 points
  • these five 3D points are not coplanar, thus calling solvePnP() with SOLVEPNP_ITERATIVE flag will throw an exception

In my opinion, computing the final pose with SOLVEPNP_ITERATIVE flag should use useExtrinsicGuess=true and rvec, tvec estimated during the MSS step. Because this consensus set has been found using 3D points with reprojection errors below a threshold, so no need to compute again an initial solution before the refinement. This was one of my interrogations in #8782


So in this specific case, since it is not possible mathematically to compute 3D pose with 5 points and the DLT algorithm, I propose to:

  • somehow detect this case: by catching the exception and comparing the exception message?, by checking if the 3D points are coplanar?
  • and instead of returning rvec, tvec from the MSS step
  • use solvePnP() with SOLVEPNP_ITERATIVE flag and useExtrinsicGuess=true

And not change the behavior for the other cases:

  • e.g. if the biggest consensus set is greater than 5 points but an exception is thrown, the same behavior before / after this PR should be retain
  • maybe this would allow detecting these new failure cases from users, and fix the algorithm if possible

@mightbxg
Copy link
Copy Markdown
Contributor Author

The initial reason of this PR is: I found my SLAM program crashes frequently because of the 5-points-issue, and it cannot be avoided outside OpenCV without try-catch, which I think is unreasonable.

The main problem for me is the unexpected exception, not the returned value in this case. I (and maybe most of SLAM developers who use solvePnPRansac) don't care about the returned value if inliers are as few as 5. In fact, I reject the PnP results with inliers fewer than 10, because they may add more measurement errors to the SLAM system.

On the other hand, as @vpisarev have said, solvePnPRansac may eventually be replaced by USAC. Is it necessary to modify solvePnPRansac such a lot?

@alalek alalek merged commit b995de4 into opencv:3.4 Mar 11, 2021
@alalek alalek mentioned this pull request Mar 13, 2021
@alalek alalek mentioned this pull request Apr 9, 2021
@kundanSingh11
Copy link
Copy Markdown

still getting this issue in android

OpenCV(4.10.0) Error: Unspecified error (> DLT algorithm needs at least 6 points for pose estimation from 3D-2D point correspondences. (expected: 'count >= 6'), where
> 'count' is 4
> must be greater than or equal to
> '6' is 6
) in void cvFindExtrinsicCameraParams2(const CvMat *, const CvMat *, const CvMat *, const CvMat *, CvMat *, CvMat *, int), file /home/ci/opencv/modules/calib3d/src/calibration.cpp, line 1280

Any help ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants