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

Strange results of matchTemplate using TM_CCORR_NORMED with mask #15768

Open
AutumnSun1996 opened this issue Oct 24, 2019 · 9 comments
Open

Strange results of matchTemplate using TM_CCORR_NORMED with mask #15768

AutumnSun1996 opened this issue Oct 24, 2019 · 9 comments

Comments

@AutumnSun1996
Copy link

System information (version)
  • OpenCV => 4.1.1 (opencv-python)
  • Operating System / Platform => Windows 10 x64
  • Compiler => Visual Studio 14 2015 Win64
Detailed description

Results of cv.matchTemplate(image, needle, cv.TM_CCORR_NORMED, mask=mask)
sometimes contains many values larger than 1 at stange position.

It happens only for TM_CCORR_NORMED with mask.
Also, it seems if the image has odd width the problem will not be triggered.

Steps to reproduce

This only happens with some special shapes of image, it seems odd width never trigger the bug.

opencvtest.zip

out.txt shows the result produced by python cvtest.py on my machine, including output of cv.getBuildInformation().

I'm not sure what causes this problem.
Opencv 3.4.4 on windows and 3.1.0 on mac has the same problem, but the err_count varies.
Another build of 4.1.1 on linux doesn't has this problem.

@alalek
Copy link
Member

alalek commented Oct 24, 2019

larger than 1 at strange position

Floating-point calculations are not very accurate in general.
What is the max observed value?

If you have strong requirement of [0; 1] range, then it is better to clamp values after matchTemplate() call

@AutumnSun1996
Copy link
Author

There are values like 17.003805 or 3.4028235e+38.
The problem is when this problem occurs, the values after clamp maybe still not what we want from the function.
My usage is to check of two images are similar, using a fixed thresh.
When the problem happens, my program always thinks the two images are the same, while they are quit different.

@catree
Copy link
Contributor

catree commented Oct 24, 2019

Could this be related? #15214

@AutumnSun1996
Copy link
Author

I think #15214 is a possible solution.
Is there any way I can test it on my machine or with my python code?

@AutumnSun1996
Copy link
Author

I found some clues about the problem. It seems like some sort of overflow or underflow problem.
If the image and needle has only zeros, the result will be nan.
And when the image and needle are close to zero, the strange results appears, and likely with some nan.
The 4.4.0 version fixed the problem in some conditions, but not all.
There are still 3.4028235e+38 (0xffff7f7f) and -3.4028235e+38(0xffff7fff) in results.

I implemented a TM_CCORR_NORMED algorithm in pytorch. It still gives nan, but not strange huge floats.

@pbrimmers-isra
Copy link

I still have same problem with version 4.5.2 that nan and inf are occuring with TM_CCORR_NORMED and mask provided.
I currently asssume that these values are not usefull and have an extra step to set these values to 0 but this means an extra step with iteration over full array.

@joecabezas
Copy link

Have same issue when using template matching on version 4.5.3, with a mask, come values in the result comes as nan, which is expected if the method is using division by zero in the underlying implementation or something shen using masks

@chriscauley
Copy link

If anyone's looking for a one line fix, you can just set them to zero. This is definitely a hack though.

    res = cv2.matchTemplate(img1, img2, cv2.TM_CCORR_NORMED, mask=img2)
    res[res == float('inf')] = 0 # bug https://github.com/opencv/opencv/issues/15768                     
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

@hmzawz2
Copy link

hmzawz2 commented Mar 17, 2023

images.zip
Here is an example. Use template image to match source image (with a all 1 mask, same size as template image), the result response map has inf and -inf. My code is like this:

    // source is source.png, tmpl is template.png
    cv::Mat mask(tmpl.rows, tmpl.cols, CV_8UC1, cv::Scalar(1));
    cv::Mat opencv_res_map;
    cv::matchTemplate(source, tmpl, opencv_res_map, cv::TM_CCOEFF_NORMED, mask);
    opencv_res_map.convertTo(opencv_res_map, CV_64FC1);

    // check
    for (int idy = 0; idy < opencv_res_map.rows; idy++)
    {
        for (int idx = 0; idx < opencv_res_map.cols; idx++)
        {
            const double& d1 = opencv_res_map.at<double>(idy, idx);
            if (d1 < -1.-1e-9 || d1 > 1.+1e-9)
            {
                // inf or -inf
            }
        }
    }

And I use opencv4.5.5 on windows11, msvc 19.

If this problem is caused by overflow, should we check whether other results value is correct?

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

No branches or pull requests

7 participants