goodFeaturesToTrack returns also corner value#19392
Conversation
|
This PR is created to support #17836 goodFeaturesToTrack returns also corner value |
| InputArray mask = noArray(), int blockSize = 3, | ||
| bool useHarrisDetector = false, double k = 0.04 ); | ||
| bool useHarrisDetector = false, double k = 0.04, | ||
| OutputArray corners_values = noArray()); |
There was a problem hiding this comment.
UB if we write at the noArray() -- static _InputOutputArray _none -- while someone is reading?
There was a problem hiding this comment.
Added check if writing is actuallly requested (seems the object does not allow write access by default anyway).
| minDistance, noArray(), 3, 3, harrisDetector, 0.04, values); | ||
|
|
||
| SANITY_CHECK(dst); | ||
| SANITY_CHECK(values, 2.f * FLT_EPSILON, ERROR_RELATIVE); |
There was a problem hiding this comment.
I propose to use absolute error 1e-6. It's small enough relatively to values and should cover floating computation issue on different OpenCL devices.
There was a problem hiding this comment.
Switched the tests back to comparison by absolute error.
|
@vpisarev Please review the PR. @amirtu Cherry-picked original PR to presume original author and fixed found issues. We decided to create new PR because patch to extra repository is required. The PR introduces function overload instead of extra parameter with default value, because of API changes in Python. Python wrapper for function with 2 OutputArray parameter returns tuple of results and it breaks existing code. Overloads presume old behavior and introduces Python function with alternative name that returns tuple. |
|
To be merged with opencv/opencv_extra#841 |
|
@vpisarev Could you take a look. Please ignore CN CI builds, they does not handle paired builds with extra right now. |
alalek
left a comment
There was a problem hiding this comment.
Modification of both implementation and tests is not a good idea in general.
You should keep already existed test cases to ensure that there are no regressions in already existed functions.
For new functionality add new tests (or add new test parameters with keeping old checks for old test cases).
| CV_EXPORTS CV_WRAP_AS(goodFeaturesToTrackWithResponse) void goodFeaturesToTrack( | ||
| InputArray image, OutputArray corners, | ||
| int maxCorners, double qualityLevel, double minDistance, | ||
| InputArray mask, int blockSize, | ||
| bool useHarrisDetector, double k, | ||
| OutputArray corners_values); |
There was a problem hiding this comment.
Do not violate OpenCV arguments order: https://github.com/opencv/opencv/wiki/Coding_Style_Guide
or make it optional.
input parameters, output parameters, flags and optional parameters.
- required input arrays
- required output arrays
- required input flags / scalar / non-array parameters
- optional input arrays (mask)
- optional output arrays
- optional input flags / scalar / non-array parameters
| int maxCorners, double qualityLevel, double minDistance, | ||
| InputArray mask, int blockSize, | ||
| bool useHarrisDetector, double k, | ||
| OutputArray corners_values); |
There was a problem hiding this comment.
corners_values
"values" are too abstract. All parameters are "values".
corners_response
|
|
||
| double minDistance = 1; | ||
| TEST_CYCLE() goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, noArray(), blockSize, gradientSize, useHarrisDetector); | ||
| TEST_CYCLE() goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, noArray(), blockSize, gradientSize, useHarrisDetector, 0.04, corners_values); |
There was a problem hiding this comment.
This change drops testing of old function.
You should create new one instead.
| const Corner & c = corner_ptr[i]; | ||
|
|
||
| corners.push_back(Point2f((float)c.x, (float)c.y)); | ||
| corners_values.push_back(eig.getMat(ACCESS_READ).at<float>(c.y, c.x)); |
There was a problem hiding this comment.
.getMat(ACCESS_READ)
.getMat() / .getUMat() in a loop is not a good idea
Did you run perf tests locally?
| denom *= 2.; | ||
| if(type != ftype ) | ||
| denom *= 255.; | ||
| denom *= 255. * 255.; |
There was a problem hiding this comment.
@amirtu Please comment changes in reference code.
There was a problem hiding this comment.
@alalek @asmorkalov Sorry for delayed answer, it has taken me some time to understand the context. Here are approximations of partial derivatives being computed with Sobel operator, the scaling is needed to preserve the energy after this filter: power of two due to averaging and differentiation parts of the filter, block size is considered in advance due to windowing of the image for every point, CV_32FC1 is (probably) normalized, CV_8U is not. First derivatives in both horizontal and vertical direction then should be scaled, as can be seen in cornerEigenValsVecs() (/imgproc/.../corner.cpp). Previously this test reference function was relying only on the relative order of the corner metrics, so scaling was not an issue.
| denom *= 2.; | ||
| if(type != ftype ) | ||
| denom *= 255.; | ||
| denom *= 255. * 255.; |
There was a problem hiding this comment.
@amirtu Please comment changes in reference code.
|
|
asmorkalov
left a comment
There was a problem hiding this comment.
Looks good for me. 👍 Please squash your own commits and presume commits of original author.
mineigen calculation rolled back; gftt function overload added (with quality parameter); perf tests were added for the new api function; external bindings were added for the function (with different alias); fixed issues with composition of the output array of the new function (e.g. as requested in comments) ; added sanity checks in the perf tests; removed C API changes.
979e7f1 to
5e6d441
Compare
modules/features2d/src/gftt.cpp
Outdated
| *keypoint_it = KeyPoint( *corner_it, (float)blockSize ); | ||
| std::vector<float>::iterator quality_it = cornersQuality.begin(); | ||
| for( ; corner_it != corners.end() && keypoint_it != keypoints.end() && quality_it != cornersQuality.end(); ++corner_it, ++keypoint_it, ++quality_it ) | ||
| *keypoint_it = KeyPoint( *corner_it, (float)blockSize, -1, *quality_it ); |
There was a problem hiding this comment.
This part of code looks strange (it was strange before this patch too).
What should we do with "left" uninitialized items when keypoint_it != keypoints.end() && quality_it != cornersQuality.end() is triggered instead of corner_it != corners.end()?
Perhaps it makes sense to put after this loop consistency check:
CV_Assert(corner_it == corners.end());
| ts->printf(cvtest::TS::CONSOLE, "actual error: %g, expected: %g", e, eps); | ||
| ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); |
There was a problem hiding this comment.
Prefer to use GTest's EXPECT_LE(e, eps); instead of legacy "ts->printf()".
It would should failed line at least.
There was a problem hiding this comment.
Fixed, but unfortunately the test itself does not extend GTest so semantics of EXPECT_LE looks oddly.
modules/features2d/src/gftt.cpp
Outdated
| *keypoint_it = KeyPoint( *corner_it, (float)blockSize ); | ||
| CV_Assert(corners.size() == cornersQuality.size()); | ||
|
|
||
| keypoints.clear(); |
There was a problem hiding this comment.
.reserve() is necessary to avoid multiple re-allocations.
…uresToTrack_returns_also_corner_value_PR * goodFeaturesToTrack returns also corner value (cherry picked from commit 4a8f067) * Added response to GFTT Detector keypoints (cherry picked from commit b88fb40) * Moved corner values to another optional variable to preserve backward compatibility (cherry picked from commit 6137383) * Removed corners valus from perf tests and better unit tests for corners values (cherry picked from commit f3d0ef2) * Fixed detector gftt call (cherry picked from commit be29755) * Restored test_cornerEigenValsVecs (cherry picked from commit ea3e118) * scaling fixed; mineigen calculation rolled back; gftt function overload added (with quality parameter); perf tests were added for the new api function; external bindings were added for the function (with different alias); fixed issues with composition of the output array of the new function (e.g. as requested in comments) ; added sanity checks in the perf tests; removed C API changes. * minor change to GFTTDetector::detect * substitute ts->printf with EXPECT_LE * avoid re-allocations Co-authored-by: Anas <anas.el.amraoui@live.com> Co-authored-by: amir.tulegenov <amir.tulegenov@xperience.ai>
PR to extra with sanity data update: opencv/opencv_extra#841
Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.