Skip to content

goodFeaturesToTrack returns also corner value#19392

Merged
alalek merged 10 commits intoopencv:masterfrom
amirtu:OCV-165_finalize_goodFeaturesToTrack_returns_also_corner_value_PR
Feb 15, 2021
Merged

goodFeaturesToTrack returns also corner value#19392
alalek merged 10 commits intoopencv:masterfrom
amirtu:OCV-165_finalize_goodFeaturesToTrack_returns_also_corner_value_PR

Conversation

@amirtu
Copy link
Copy Markdown
Member

@amirtu amirtu commented Jan 25, 2021

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

  • 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

@amirtu
Copy link
Copy Markdown
Member Author

amirtu commented Jan 25, 2021

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());
Copy link
Copy Markdown
Member Author

@amirtu amirtu Feb 1, 2021

Choose a reason for hiding this comment

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

UB if we write at the noArray() -- static _InputOutputArray _none -- while someone is reading?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added check if writing is actuallly requested (seems the object does not allow write access by default anyway).

@asmorkalov asmorkalov changed the title Temporary PR: finalize PR 17836 goodFeaturesToTrack w/ corner values goodFeaturesToTrack returns also corner value Feb 3, 2021
minDistance, noArray(), 3, 3, harrisDetector, 0.04, values);

SANITY_CHECK(dst);
SANITY_CHECK(values, 2.f * FLT_EPSILON, ERROR_RELATIVE);
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 propose to use absolute error 1e-6. It's small enough relatively to values and should cover floating computation issue on different OpenCL devices.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Switched the tests back to comparison by absolute error.

@asmorkalov asmorkalov requested a review from vpisarev February 3, 2021 09:27
@asmorkalov
Copy link
Copy Markdown
Contributor

@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.

@amirtu
Copy link
Copy Markdown
Member Author

amirtu commented Feb 3, 2021

To be merged with opencv/opencv_extra#841

Copy link
Copy Markdown
Contributor

@asmorkalov asmorkalov left a comment

Choose a reason for hiding this comment

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

Well done! 👍

@asmorkalov
Copy link
Copy Markdown
Contributor

@vpisarev Could you take a look. Please ignore CN CI builds, they does not handle paired builds with extra right now.

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.

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).

Comment on lines +2026 to +2031
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);
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.

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);
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.

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);
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 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));
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.

.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.;
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.

why?

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.

@amirtu Please comment changes in reference code.

Copy link
Copy Markdown
Member Author

@amirtu amirtu Feb 11, 2021

Choose a reason for hiding this comment

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

@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.;
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.

@amirtu Please comment changes in reference code.

@amirtu
Copy link
Copy Markdown
Member Author

amirtu commented Feb 12, 2021

new PR for merge in 3.4: #19511

@asmorkalov asmorkalov self-requested a review February 12, 2021 07:10
Copy link
Copy Markdown
Contributor

@asmorkalov asmorkalov 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 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.
@amirtu amirtu force-pushed the OCV-165_finalize_goodFeaturesToTrack_returns_also_corner_value_PR branch from 979e7f1 to 5e6d441 Compare February 12, 2021 07:20
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.

Thank you! Looks good to me 👍

*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 );
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 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());

Copy link
Copy Markdown
Member Author

@amirtu amirtu Feb 15, 2021

Choose a reason for hiding this comment

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

Noted with thanks 👌

Comment on lines +509 to +510
ts->printf(cvtest::TS::CONSOLE, "actual error: %g, expected: %g", e, eps);
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
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.

Prefer to use GTest's EXPECT_LE(e, eps); instead of legacy "ts->printf()".
It would should failed line at least.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed, but unfortunately the test itself does not extend GTest so semantics of EXPECT_LE looks oddly.

*keypoint_it = KeyPoint( *corner_it, (float)blockSize );
CV_Assert(corners.size() == cornersQuality.size());

keypoints.clear();
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.

.reserve() is necessary to avoid multiple re-allocations.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed.

@alalek alalek merged commit 47426a8 into opencv:master Feb 15, 2021
@alalek alalek mentioned this pull request Apr 9, 2021
a-sajjad72 pushed a commit to a-sajjad72/opencv that referenced this pull request Mar 30, 2023
…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>
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.

4 participants