Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Imgproc: templmatch: Add support for mask for all methods #15214

Merged
merged 5 commits into from
May 14, 2020

Conversation

jumostedu
Copy link
Contributor

@jumostedu jumostedu commented Aug 3, 2019

resolves #6919
resolves #14076

Current situation

There are multiple requests for supporting a mask in the matchTemplate() function, see #14076. Currently only the matching methods CV_TM_SQDIFF and CV_TM_SQDIFF support a mask, and there is justified doubt (#6919) about the correctness.

This pullrequest changes

This pull request adds support for masked template matching for all methods, adds the appropriate documentation, as well as tests (which pass). The mask works in an expectable way (the old implementation is scrubbed): The mask is multiplied to the template and to each image patch that is matched.

# disable_ipp:Mac=ON

force_builders=Linux AVX2,Custom
buildworker:Custom=linux-3
build_image:Custom=ubuntu:18.04
CPU_BASELINE:Custom=AVX512_SKX
disable_ipp=ON

@jumostedu
Copy link
Contributor Author

So I see that some tests fail, suspiciously only on MacOSX, namely exactly all CCOEFF[_NORMED] tests with multiple channels. That seems very strange, and I think it might hint to some lower level issue.

I suspect, that maybe crossCorr() is not behaving identical. From my code the problem could be invoked here. I did not find any real documentation for crossCorr(), but on my build (linux), if the result Mat passed to crossCorr() has multiple channels just like the inputs, it does per channel correlation and saves every channel individually (it sums them up if the result has only one channel). Maybe this behavior of crossCorr() is not used anywhere else and somehow is faulty on MacOSX.

I did not have a deeper look into crossCorr(), I just used it as it is, hoping that it is an efficient low level DFT implementation.

Other than that I have no idea where these test errors on MacOSX come from.

@asmorkalov
Copy link
Contributor

@jumostedu Do you have a chance to finish the patch? CI bot reports issues, please take a look.

@jumostedu
Copy link
Contributor Author

@jumostedu Do you have a chance to finish the patch? CI bot reports issues, please take a look.

I have not found time to try to fix the errors on MacOSX so far, but I will try to have a look again the next week(s).

@jumostedu jumostedu changed the title imgproc: templmatch: Add support for mask for all methods WIP: imgproc: templmatch: Add support for mask for all methods Nov 24, 2019
@jumostedu
Copy link
Contributor Author

I can not say, what the problem is, that causes the tests to fail on MacOSX, my code does not contain anything platform specific. My guess would be that it's something inside the crossCorr() function (the one defined in templmatch.cpp), probably the hal::DFT2D. Is crossCorr() tested anywhere for multiple channels? filter2D() uses it, but the tests for it seem to be only randomly done for multiple channels.

I also don't have a Mac, so I can really only debug this by looking at the CI results/output here. This is not a great way to do it, so if someone has a Mac and wants to dive into this, they're welcome.

I've written short tests to narrow down if the problem is really crossCorr() with multiple channels. But I don't know how to restart the builds and tests, it says

Pending — Waiting for builds

Pushing to my branch or does not seem to do it. Neither does adding force_builders_only=Mac,linux to the PR description. On https://pullrequest.opencv.org/#/summary/opencv every build is

not_queued

some days now. @alalek , how can I retrigger the CI tests?

@asmorkalov
Copy link
Contributor

@jumostedu I re-started CI for you. CI starts automatically every time when you push changes, so manual triggering usually is not required.

@Jordak
Copy link

Jordak commented Feb 10, 2020

As an interested party, has this PR seen any movement through CI recently?

@VadimLevin
Copy link
Contributor

@alalek can you proceed with review? I resolved the problem with the clang build (I reproduced the original problem on Ubuntu 18.04 clang 9.0.0-2 Release) and removed crossCorr from the public interface. I think if it is required it should be done as separate PR.

@asmorkalov
Copy link
Contributor

@VadimLevin @alalek are there any open items in the PR? Could we merge it?

@asmorkalov asmorkalov changed the title WIP: imgproc: templmatch: Add support for mask for all methods Imgproc: templmatch: Add support for mask for all methods Apr 8, 2020
@jumostedu
Copy link
Contributor Author

@VadimLevin Thanks for fixing the problem (and prettying up the code :)), I did not realize it was a compiler dependent problem.

If you want, I can remove the test for CrossCorr (df07c97) (as it is removed by @VadimLevin 's commit anyway). Or we could leave it in, if someone ever wants to make a test they could use it as reference (if they find it in the git history).

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.

Thank you for contribution!

Need to take a look on "mask" design more carefully.
/cc @vpisarev

modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/test/test_templmatchmask.cpp Outdated Show resolved Hide resolved
modules/imgproc/include/opencv2/imgproc.hpp Outdated Show resolved Hide resolved
modules/imgproc/include/opencv2/imgproc.hpp Outdated Show resolved Hide resolved
Comment on lines +844 to +853
// It does not matter what to use Mat/MatExpr, it should be evaluated to perform assign subtraction
Mat temp_res = img_mask_corr.mul(sum(templx_mask).div(mask_sum));
Copy link
Member

Choose a reason for hiding this comment

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

I believe there is some bug in MatExpr, need to prepare simple reproducer for tests with similar code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should probably be a separate issue. I'm did obviously not resolve this, so you may resolve this conversation yourself :)

@VadimLevin
Copy link
Contributor

@jumostedu Are you planning to finalize this PR and pass the review or should I do this on my own?

@jumostedu
Copy link
Contributor Author

@VadimLevin Yeah, I'll do it within the next few (two or three) days. Thanks for your help!

Add support for masked template matching. Fix/scrub old implementation
for masked matching, as it did partly not even really do a meaningful
masking, and only supported limited template matching methods.

Add documentation including formulas for masked matching.
jumostedu and others added 4 commits April 13, 2020 13:24
Test accuracy by comparing to naive implementation for one point.
Test compatibility/correctness by comparing results without mask and
with all ones mask.
All tests are done for all methods, all supported depths, and for 1 and
3 channels.
Add a test for the crossCorr function in templmatch.cpp. crossCorr() had
to be added to exported functions to be testable.

This test can maybe help to identify the problem with template matching
on MacOSX.
If it should be exported, it should be done as separate PR.
@jumostedu
Copy link
Contributor Author

I just realized I can then extend the test to test to using 8U masks with 32F image and template, as well as single channel mask with multichannel image and template, so I did that.

@asmorkalov
Copy link
Contributor

@jumostedu Do you have a chance to finalize the patch?

@jumostedu
Copy link
Contributor Author

@jumostedu Do you have a chance to finalize the patch?

From my side I think I've resolved all open points. If you want me to rebase something, I can do that. Other than that there's a review pending by @vpisarev

@asmorkalov
Copy link
Contributor

@vpisarev could you look at it again?

@vpisarev vpisarev self-assigned this Apr 28, 2020
@vpisarev
Copy link
Contributor

@jumostedu, @alalek, @asmorkalov, sorry for delay.
This is excellent job by the contributor and the reviewers, thank you! 👍

@alalek alalek merged commit 5b095df into opencv:master May 14, 2020
@anwar6953
Copy link

anwar6953 commented Sep 15, 2020

I am using 4.4.0 and seeing unexpected behavior.
I'm using matchTemplate against the image itself, which should produce 100% match. It does indeed (I'm using cv2.TM_SQDIFF_NORMED).
However, when I pass in a mask that is a subset of the overall image, it then yields a nonzero value for the best match, which is unexpected.

In python:

minMaxLoc = cv2.minMaxLoc(cv2.matchTemplate(img, img, cv2.TM_SQDIFF_NORMED, mask=mask_white(img)))

This yields minMaxLoc[0] to be 0 if mask is None, but yields ~0.00000045 when I generate a mask.
The mask I generate simply sets non-white colors in the image to 0, and all other pixels to (255,255,255).

@VadimLevin
Copy link
Contributor

@anwar6953 OpenCV uses (in most cases) single precision in computations involving floating point numbers and TM_SQDIFF_NORMED is one of them. According to the IEEE 754 (floating point standard) single precision float has 7 significant digits, but in my experience you can trust only up to 5-6 digits, so you have approximately zero, which is expected. The source of the difference in the result (0 vs approx 0) may be caused by different data flow in computations.

@anwar6953
Copy link

Fair enough that it is approximately zero.
I just thought it was odd that adding a mask resulting in a nonzero, when a mask should only increase the match rate.

Thanks for the explanation.

echuraev pushed a commit to echuraev/opencv that referenced this pull request Jun 6, 2021
* imgproc: templmatch: Add support for mask for all methods

Add support for masked template matching. Fix/scrub old implementation
for masked matching, as it did partly not even really do a meaningful
masking, and only supported limited template matching methods.

Add documentation including formulas for masked matching.

* imgproc: test: Add tests for masked template matching

Test accuracy by comparing to naive implementation for one point.
Test compatibility/correctness by comparing results without mask and
with all ones mask.
All tests are done for all methods, all supported depths, and for 1 and
3 channels.

* imgproc: test: templmatch: Add test for crossCorr

Add a test for the crossCorr function in templmatch.cpp. crossCorr() had
to be added to exported functions to be testable.

This test can maybe help to identify the problem with template matching
on MacOSX.

* fix: Fixed wrong evaluations of the MatExpr on Clang

* fix: removed crossCorr from public interface.

If it should be exported, it should be done as separate PR.

Co-authored-by: Vadim Levin <vadim.levin@xperience.ai>
drothlis added a commit to stb-tester/stb-tester that referenced this pull request May 23, 2022
drothlis added a commit to stb-tester/stb-tester that referenced this pull request May 23, 2022
drothlis added a commit to stb-tester/stb-tester that referenced this pull request May 23, 2022
a-sajjad72 pushed a commit to a-sajjad72/opencv that referenced this pull request Mar 30, 2023
* imgproc: templmatch: Add support for mask for all methods

Add support for masked template matching. Fix/scrub old implementation
for masked matching, as it did partly not even really do a meaningful
masking, and only supported limited template matching methods.

Add documentation including formulas for masked matching.

* imgproc: test: Add tests for masked template matching

Test accuracy by comparing to naive implementation for one point.
Test compatibility/correctness by comparing results without mask and
with all ones mask.
All tests are done for all methods, all supported depths, and for 1 and
3 channels.

* imgproc: test: templmatch: Add test for crossCorr

Add a test for the crossCorr function in templmatch.cpp. crossCorr() had
to be added to exported functions to be testable.

This test can maybe help to identify the problem with template matching
on MacOSX.

* fix: Fixed wrong evaluations of the MatExpr on Clang

* fix: removed crossCorr from public interface.

If it should be exported, it should be done as separate PR.

Co-authored-by: Vadim Levin <vadim.levin@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.

Template matching with mask Is masked matchTemplate implementation correct?
7 participants