Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

if template is present in the image at point P(x,y), templateMatching returns P(x+epsilon,y+epsilon) where epsilon might be 0 or very small if the match is similar. Exact match will returns exact position.

BTW if "exact" means T-I=0 you can use a simple slider difference like below

int ExactMatch(const Mat& I, const Mat &T, std::vector<Point> &matches)
{
    //Mat I; // the image
    //Mat T; // the template
    //std::vector<Point> matches; // vector of exact match point

    matches.clear();
    Rect R(Point(0, 0), T.size()); //a rect roi over the image
    Mat delta;
    int nx = I.cols - T.cols;   // numbers of horiz sliding ROI
    int ny = I.rows - T.rows;   // numbers of vert sliding ROI
    double maxValue;
    Point maxLoc,match;
    for (int x = 0; x < nx; x++)
        for (int y = 0; y < ny; y++)
        {
            absdiff(T, I(R), delta);  //delta = |T - I(R) |
            // search for max in the difference
            minMaxLoc(delta, NULL, &maxValue, NULL, &maxLoc);
            //max==0 means delta == 0 means exact match
            if (maxValue == 0)
            {
                match = Point(x, y);
                cout << "Exact found at " << match << endl;
                matches.push_back(match);
            }
        }
    return (int)matches.size();
}

if template is present in the image at point P(x,y), templateMatching returns P(x+epsilon,y+epsilon) where epsilon might be 0 or very small if the match is similar. Exact match will returns exact position.

BTW if "exact" means T-I=0 you can use a simple slider difference like below

int ExactMatch(const Mat& I, const Mat &T, std::vector<Point> &matches)
{
    //Mat I; // the image
    //Mat T; // the template
    //std::vector<Point> matches; // vector of exact match point

    //works only on grayscale image because to minMaxLoc
    cvAssert((I.channels()==1)   && (T.channels()==1))
    matches.clear();
    Rect R(Point(0, 0), T.size()); //a rect roi over the image
    Mat delta;
    int nx = I.cols - T.cols;   // numbers of horiz sliding ROI
    int ny = I.rows - T.rows;   // numbers of vert sliding ROI
    double maxValue;
    Point maxLoc,match;
    for (int x = 0; x < nx; x++)
        for (int y = 0; y < ny; y++)
        {
            R.x = x; R.y = y;
            absdiff(T, I(R), delta);  //delta = |T - I(R) |
            // search for max in the difference
            minMaxLoc(delta, NULL, &maxValue, NULL, &maxLoc);
            //max==0 means delta == 0 means exact match
            if (maxValue == 0)
            {
                match = Point(x, y);
                cout << "Exact found at " << match << endl;
                matches.push_back(match);
            }
        }
    return (int)matches.size();
}

UPDATE:

Despite of above code works (on 1channel images) it is really inefficient. The way templateMatch/CV_TM_SQDIFF is much faster and general.

if template is present in the image at point P(x,y), templateMatching returns P(x+epsilon,y+epsilon) where epsilon might be 0 or very small if the match is similar. Exact match will returns exact position.

BTW if "exact" means T-I=0 you can use a simple slider difference like below

int ExactMatch(const Mat& I, const Mat &T, std::vector<Point> &matches)
{
    //Mat I; // the image
    //Mat T; // the template
    //std::vector<Point> matches; // vector of exact match point

    //works only on grayscale image because to minMaxLoc
    cvAssert((I.channels()==1)   && (T.channels()==1))
    matches.clear();
    Rect R(Point(0, 0), T.size()); //a rect roi over the image
    Mat delta;
    int nx = I.cols - T.cols;   // numbers of horiz sliding ROI
    int ny = I.rows - T.rows;   // numbers of vert sliding ROI
    double maxValue;
    Point maxLoc,match;
    for (int x = 0; x < nx; x++)
        for (int y = 0; y < ny; y++)
        {
            R.x = x; R.y = y;
            absdiff(T, I(R), delta);  //delta = |T - I(R) |
            // search for max in the difference
            minMaxLoc(delta, NULL, &maxValue, NULL, &maxLoc);
            //max==0 means delta == 0 means exact match
            if (maxValue == 0)
            {
                match = Point(x, y);
                cout << "Exact found at " << match << endl;
                matches.push_back(match);
            }
        }
    return (int)matches.size();
}

UPDATE:

Despite of above code works (on 1channel images) it is really inefficient. The way templateMatch/CV_TM_SQDIFF is much faster and general.

UPDATE2: This should works on Java:

Imgproc.matchTemplate(source, template, resultMatrix, Imgproc.TM_SQDIFF_NORMED);
epsilon = 0.1; // increase to be more tolerant
while (true)
{
    MinMaxLocResult mmr = Core.minMaxLoc(resultMatrix);
    if (mmr.minVal > epsilon )
            break; // no more matches

    Point matchLoc = mmr.minLoc;
    System.out.print("\nMatch found at: "); System.out.print(matchLoc);
    System.out.print("\tDifference: "); System.out.print(mmr.minVal);
    // clean scores around current match
    Imgproc.rectangle( resultMatrix,
        new Point(matchLoc.x - template.cols()/2, matchLoc.y - template.rows()/2),
        new Point(matchLoc.x + template.cols()/2, matchLoc.y + template.rows()/2),
        2*epsilon,-1);
    // draw a rectangle around match
    Imgproc.rectangle( source, matchLoc,
        new Rect(matchLoc, template.size()),
        new Scalar(0, 255, 0), 1);
}

if template is present in the image at point P(x,y), templateMatching returns P(x+epsilon,y+epsilon) where epsilon might be 0 or very small if the match is similar. Exact match will returns exact position.

BTW if "exact" means T-I=0 you can use a simple slider difference like below

int ExactMatch(const Mat& I, const Mat &T, std::vector<Point> &matches)
{
    //Mat I; // the image
    //Mat T; // the template
    //std::vector<Point> matches; // vector of exact match point

    //works only on grayscale image because to minMaxLoc
    cvAssert((I.channels()==1)   && (T.channels()==1))
    matches.clear();
    Rect R(Point(0, 0), T.size()); //a rect roi over the image
    Mat delta;
    int nx = I.cols - T.cols;   // numbers of horiz sliding ROI
    int ny = I.rows - T.rows;   // numbers of vert sliding ROI
    double maxValue;
    Point maxLoc,match;
    for (int x = 0; x < nx; x++)
        for (int y = 0; y < ny; y++)
        {
            R.x = x; R.y = y;
            absdiff(T, I(R), delta);  //delta = |T - I(R) |
            // search for max in the difference
            minMaxLoc(delta, NULL, &maxValue, NULL, &maxLoc);
            //max==0 means delta == 0 means exact match
            if (maxValue == 0)
            {
                match = Point(x, y);
                cout << "Exact found at " << match << endl;
                matches.push_back(match);
            }
        }
    return (int)matches.size();
}

UPDATE:

Despite of above code works (on 1channel images) it is really inefficient. The way templateMatch/CV_TM_SQDIFF is much faster and general.

UPDATE2: This should works on Java:Java: UPDATE3: small fix (please be tolerant to syntax error. I don't have a java machine)

Mat resultMatrix = new Mat();
int result_cols =  source.cols() - template.cols() + 1;
int result_rows = source.rows() - template.rows() + 1;
resultMatrix.create( result_rows, result_cols, CvType.CV_32FC1 );
Imgproc.matchTemplate(source, template, resultMatrix, Imgproc.TM_SQDIFF_NORMED);
 epsilon = 0.1; // increase to be more tolerant
while (true)
{
    MinMaxLocResult mmr = Core.minMaxLoc(resultMatrix);
    if (mmr.minVal > epsilon )
            break; // no more matches

    Point matchLoc = mmr.minLoc;
    System.out.print("\nMatch found at: "); System.out.print(matchLoc);
    System.out.print("\tDifference: "); System.out.print(mmr.minVal);
    // clean scores around current match
    Imgproc.rectangle( resultMatrix,
Imgproc.rectangle(resultMatrix,
        // clean around center
        new Point(matchLoc.x - template.cols()/2, matchLoc.y - template.rows()/2),
        new Point(matchLoc.x + template.cols()/2, matchLoc.y + template.rows()/2),
        2*epsilon,-1);
// set to a value greater than your threshold
        new Scalar(epsilon+1, epsilon+1, epsilon+1), -1);
    // draw a rectangle around match
    Imgproc.rectangle( source, Imgproc.rectangle(source, 
        matchLoc,
        new Rect(matchLoc, template.size()),
Point(matchLoc.x + template.cols(), matchLoc.y + template.rows()),
        new Scalar(0, 255, 0), 1);
}