Skip to content

Expose maxIters in findFundamentalMat #16498

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Mar 11, 2020

Conversation

etrulls
Copy link
Contributor

@etrulls etrulls commented Feb 4, 2020

Lets the user choose the maximum number of iterations the robust
estimator runs for, similary to findHomography. This can significantly
improve performance (at a computational cost).

This pullrequest changes

I've benchmarked different RANSAC variants for a paper I've been working on. It's also part of an open challenge on local features and robust matchers: you can find a lot more information on the website. OpenCV performs quite poorly compared with other methods, and the main reason is that it caps the maximum number of iterations to 1000, which is a very conservative value. This parameter is exposed by APIs (e.g. homography estimation) but not others.

To show why this matters, I ran some experiments on the validation set for the benchmark, with 2000 SIFT keypoints, cycle-consistent matches with ratio test, and optimal values for the inlier threshold in RANSAC, and a high confidence value (0.999999). These are the results for the 3 scenes in the validation set:

Scene: "REICHSTAG"
mAA with maxIter=100 -> 0.15666
mAA with maxIter=250 -> 0.19526
mAA with maxIter=500 -> 0.22670
mAA with maxIter=1000 (DEFAULT) -> 0.25395
mAA with maxIter=2000 -> 0.28121 (performance=1.11x, cost=1.80x)
mAA with maxIter=5000 -> 0.31519 (performance=1.24x, cost=3.90x)
mAA with maxIter=10000 -> 0.33144 (performance=1.31x, cost=7.32x)
mAA with maxIter=25000 -> 0.34992 (performance=1.38x, cost=16.27x)
mAA with maxIter=50000 -> 0.36061 (performance=1.42x, cost=29.64x)
mAA with maxIter=100000 -> 0.37103 (performance=1.46x, cost=52.21x)
mAA with maxIter=250000 -> 0.37933 (performance=1.49x, cost=110.13x)
mAA with maxIter=500000 -> 0.38571 (performance=1.52x, cost=190.89x)
mAA with maxIter=750000 -> 0.38767 (performance=1.53x, cost=267.67x)
mAA with maxIter=1000000 -> 0.38868 (performance=1.53x, cost=330.49x)

Scene: "SACRE_COEUR"
mAA with maxIter=100 -> 0.22210
mAA with maxIter=250 -> 0.29532
mAA with maxIter=500 -> 0.34046
mAA with maxIter=1000 (DEFAULT) -> 0.38818
mAA with maxIter=2000 -> 0.43300 (performance=1.12x, cost=1.90x)
mAA with maxIter=5000 -> 0.47929 (performance=1.23x, cost=4.20x)
mAA with maxIter=10000 -> 0.51093 (performance=1.32x, cost=7.21x)
mAA with maxIter=25000 -> 0.54429 (performance=1.40x, cost=16.10x)
mAA with maxIter=50000 -> 0.56496 (performance=1.46x, cost=31.83x)
mAA with maxIter=100000 -> 0.57942 (performance=1.49x, cost=52.79x)
mAA with maxIter=250000 -> 0.59559 (performance=1.53x, cost=110.04x)
mAA with maxIter=500000 -> 0.60567 (performance=1.56x, cost=225.25x)
mAA with maxIter=750000 -> 0.60929 (performance=1.57x, cost=322.98x)
mAA with maxIter=1000000 -> 0.61249 (performance=1.58x, cost=363.49x)

Scene: "ST_PETERS_SQUARE"
mAA with maxIter=100 -> 0.06177
mAA with maxIter=250 -> 0.08594
mAA with maxIter=500 -> 0.10710
mAA with maxIter=1000 (DEFAULT) -> 0.12528
mAA with maxIter=2000 -> 0.14732 (performance=1.18x, cost=1.73x)
mAA with maxIter=5000 -> 0.17026 (performance=1.36x, cost=4.42x)
mAA with maxIter=10000 -> 0.19138 (performance=1.53x, cost=8.21x)
mAA with maxIter=25000 -> 0.21833 (performance=1.74x, cost=19.86x)
mAA with maxIter=50000 -> 0.23224 (performance=1.85x, cost=33.72x)
mAA with maxIter=100000 -> 0.24813 (performance=1.98x, cost=74.56x)
mAA with maxIter=250000 -> 0.25763 (performance=2.06x, cost=168.73x)
mAA with maxIter=500000 -> 0.26477 (performance=2.11x, cost=310.28x)
mAA with maxIter=750000 -> 0.27054 (performance=2.16x, cost=445.01x)
mAA with maxIter=1000000 -> 0.27017 (performance=2.16x, cost=518.34x)

mAA means "mean Average Accuracy" and is explained here. Note that the increase in cost can be negligible (~1 sec at 50k iterations on a n1-standard-2 VM in Google Cloud (2 vCPUs, 7.5 GB memory)). 1M iterations is obviously overkill, but I used the same higher bound as in findHomography, for consistency.

I patched the 3.4 branch -- let me know if the patch looks good and I can do the same for 2 and 4.

@etrulls etrulls changed the base branch from master to 3.4 February 9, 2020 07:47
@asmorkalov asmorkalov requested a review from vpisarev February 11, 2020 07:03
@asmorkalov
Copy link
Contributor

@vpisarev could you look at it.

@catree
Copy link
Contributor

catree commented Feb 14, 2020

A general comment.

In my opinion, for this kind of algorithms I would like to have the possibility to tune, change the relevant parameters. Something like the features2d class. Some default parameters that should work for most users, and the possibility to change certain parameter using class setters.
If this approach integrates well with the Java, Python, Javascript bindings, this should be preferred over using function and adding more and more overloads, function parameters in my opinion.

Another possible issue. It looks like the RANSAC used for estimating PnP problem (solvePnPRansac) in calib3d is a different function than for imgproc? If so, a big improvement would be to have some generic implementation: one RANSAC (LMeds, ...) implementation, but a different model when estimating fundamental matrix or PnP problem, etc.

related: #10631 #4321 #11594 #6933

@asmorkalov
Copy link
Contributor

@etrulls Could you rebase the PR on top of branch 3.4 an fix conflicts. The patch looks very interesting, but we cannot test and merge it.

@asmorkalov
Copy link
Contributor

@alalek I re-based the patch on top of 3.4. Please take a look and merge.

@etrulls
Copy link
Contributor Author

etrulls commented Mar 2, 2020

Thanks! Too busy to get around to it last week, sorry.

Copy link
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.

Separate overloads should be created to conform ABI compatibility.

@@ -1941,12 +1942,13 @@ stereoRectifyUncalibrated to compute the rectification transformation. :
CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2,
int method = FM_RANSAC,
double ransacReprojThreshold = 3., double confidence = 0.99,
OutputArray mask = noArray() );
OutputArray mask = noArray(), int maxIters = 1000 );
Copy link
Member

Choose a reason for hiding this comment

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

This change violates OpenCV parameters order policy:

  • input_arrays
  • output_arrays (or function return if single output)
  • algo_parameters
  • optional_algo_parameters_with_default_values
  • optional_output_arrays
  • optional_other_output

Lets the user choose the maximum number of iterations the robust
estimator runs for, similary to findHomography. This can significantly
improve performance (at a computational cost).
@asmorkalov
Copy link
Contributor

@alalek I refactored the patch as discussed. Please take a look.

Copy link
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.

Looks good to me! Thank you 👍

@asmorkalov
Copy link
Contributor

@alalek Could we merge it?

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants