0

can anybody help me understanding why matchTemplate does not provide zero output in areas where the template or the image are zero?

Here is an example

void DumpMatToFile(const Mat &in, string filename)
{
    ostringstream os;
    os << in.size() << endl; 
    for (int y = 0; y < in.size().height; y++)
    {
        for (int x = 0; x < in.size().width; x++)
        {
            os << setw(12) << in.at<float>(y, x) << " ";
        }
        os << endl;
    }

    FILE *f = fopen(filename.c_str(), "wt");
    fwrite(os.str().c_str(), 1, strlen(os.str().c_str()), f);
    fclose(f);
}

void SetTo(Mat &o, float v)
{
    for (int y = 0; y < o.size().height; y++)
    {
        for (int x = 0; x < o.size().width; x++)
            o.at<float>(y, x) = v;
    }
}
void test(float k)
{
    Mat t(2, 2, CV_32FC1, Scalar(1.0f));
    t.at<float>(0, 0) = 1.0f;
    t.at<float>(0, 1) = 1.0f;
    t.at<float>(1, 0) = 1.0f;
    t.at<float>(1, 1) = 1.0f;
    Mat in1(10, 20, CV_32FC1, Scalar(0.0f));
    SetTo(in1, k);
    in1.at<float>(5, 4) = 2.0f;
    in1.at<float>(5, 5) = 2.0f;
    in1.at<float>(6, 4) = 2.0f;
    in1.at<float>(6, 5) = 2.0f;
    Mat res1, res2;
    matchTemplate(in1, t, res1, CV_TM_CCORR);
    DumpMatToFile(t, "c:/temp/t.txt");
    DumpMatToFile(in1, "c:/temp/in1.txt");
    DumpMatToFile(res1, "c:/temp/dump21.txt");
}

calling

test(1.0f);

The result is as expected:

[19 x 9]
4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4
4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   5   6   5   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   6   8   6   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   5   6   5   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4 
4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4 

Instead, calling

test(0.0f);

I got

[19 x 9]
           0  4.21468e-08  5.96046e-08 -4.21468e-08 -1.19209e-07 -4.21468e-08  5.96046e-08            0            0            0            0            0            0            0            0            0            0            0            0 
 2.98023e-08 -2.10734e-08            0  2.10734e-08 -2.98023e-08  2.10734e-08            0            0            0            0            0            0            0            0            0            0            0            0            0 
 5.96046e-08  4.21468e-08            0 -4.21468e-08 -5.96046e-08 -4.21468e-08            0            0            0            0            0            0            0            0            0            0            0            0            0 
 1.01751e-07  4.21468e-08 -4.21468e-08 -4.21468e-08 -1.74578e-08 -4.21468e-08 -4.21468e-08            0            0            0            0            0            0            0            0            0            0            0            0 
           0            0            0            2            4            2            0            0            0            0            0            0            0            0            0            0            0            0            0 
           0            0            0            4            8            4            0            0            0            0            0            0            0            0            0            0            0            0            0 
           0            0            0            2            4            2            0            0            0            0            0            0            0            0            0            0            0            0            0 
           0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0 
           0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0            0 

So why the upper left corner area of the result ccor doe not goes to zero? This imprecision introduces misbehaviours in real cases.

Thanks

Andrea

  • 1
    Actually those numbers are quite close to zero. You can just assume them to be zero. The source of "imprecision" is that OpenCV does not use straightforward way to compute correlation and instead computes it in Fourier space. It is compute effective for big inputs and templates and is almost accurate as well. – Andrey Kamaev Sep 04 '17 at 23:55
  • @AndreyKamaev nailed it with his comment. Note that if you did not want this "imprecision" (really, `e-08` should *not* produce misbehaviors and your code should always check for some really small threshold, not exactly 0 values as precision errors can occur in a lot of places), you could use square difference instead with `CV_TM_SQDIFF` which would actually give you 0s where you are expecting. – alkasm Sep 05 '17 at 06:42

0 Answers0