Matchtemplate SQDIFF has minValue != 0 for identical image/template

Based on the SQDIFF formula: OpenCV: Object Detection

I expected to get a minValue of 0 when the template and the image are identical, because the square difference is 0 for each pixel in each channel, so the sum must be 0 too. However, I get different results, I have one example with a 3 channel color-image (using only black and white pixels though) where the minVal is 15266 where I expected 0.

I tried reproducing/understanding with a small-ish image, this is an image I used in my test:

image

It’s 18x15 pixels, 3 channels, all either black (0,0,0) or white (255,255,255). When I pass this to the template match function using SQDIFF (without mask), I get a minValue of 2 iso my expected 0.

Any ideas what I’m not understanding? Using OpenCV 4.13.0.

I’m guessing here:

Hi crackwitz, thanks for that! I’m going to look into that bug, it looks similar. I don’t really have an issue, because the not-0 value is an edge case in my usage.

I’m still not sure if I understand the formula 100% though. Let me clarify how I understand the formula and why I think it should be 0, if you spot an error in my reasoning: shoot!

The formula:

The function slides through image , compares the overlapped patches of size
against templ using the specified method and stores the comparison results in result

Using the same templ and image simplifies this, since there is no sliding, so the summation is only1 “run” of comparisons.

TemplateMatchModes describes the formulae for the available comparison methods (I denotes image,T template, R result, M the optional mask ). The summation is done over template and/or the image patch: x’ = 0…w-1, y’ = 0…h-1

No sliding, so x’=0 and y’=0.

In case of a color image, template summation in the numerator and each sum in the denominator is done over all of the channels and separate mean values are used for each channel

All channels are identical, so mean values should be too, and all 0.

SQDIFF = “square root of difference”, differences are 0 for each pixel, so square root should be 0 too.

If this is correct, I indeed assume it’s a (known) bug.

if you compare the template against itself with SQDIFF, the difference should be zero, so should the squared diff.

SQDIFF involves no roots, only squaring and summing.

if the score in that situation isn’t zero, that’s very likely a bug in the library, and probably it is that bug.

for templates of enough size, the issue I linked says that the score erroneously becomes nonzero because floats (23 bits of mantissa) had been used internally.

that’s what I conclude too. it might be the same bug, or a similar but different bug. in either case, you might want to watch that issue for progress. I see a PR associated to it, so it might only be a matter of “bureaucracy” until it’s in a release.

if the fix is urgent to you, you could try out the PR associated to the issue, before it lands in a numbered release. yes, that’d involve compiling OpenCV.
if the fix is really urgent, you could also code up a temporary replacement for your use case of matchTemplate so you can check that off and move on. not the most convenient option for sure.

Thanks a lot! I’ll follow-up on the bug. To learn, I’m going to compile OpenCV and check if the PR fixes my use case. If it doesn’t, I’ll open a new issue with exact reproducable data.