Open AutumnSun1996 opened 5 years ago
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
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.
Could this be related? #15214
I think #15214 is a possible solution. Is there any way I can test it on my machine or with my python code?
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.
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.
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
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)
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?
System information (version)
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 bypython cvtest.py
on my machine, including output ofcv.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.