read

OpenCV has a matchTemplate function that let you seach for matches between an image and a given template.

There is a tutorial on that.

However, the tutorial falls short. It only explain how to match 1 occurence.

I know the answer is somewhere in the result.. But I am a newbie and cannot figure out. Do are others.

I found the best answer from: OpenCV-Code.com

The genius part of the code is that it finds a match with minMaxLoc, then it floodFill it. Then it can repeat.

I have used it for an iOS project to count the number of matching templates. Here’s the code:

// Returns number of matching templates
+ (int)matchTemplate:(UIImage*)templateImage in:(UIImage*)src {
    // http://opencv-code.com/quick-tips/how-to-handle-template-matching-with-multiple-occurences/
    cv::Mat ref = [src CVMat];
    cv::Mat tpl = [templateImage CVMat];
    cv::Mat gref, gtpl;
    cv::cvtColor(ref, gref, CV_BGR2GRAY);
    cv::cvtColor(tpl, gtpl, CV_BGR2GRAY);
    
    cv::Mat res(ref.rows-tpl.rows+1, ref.cols-tpl.cols+1, CV_32FC1);
    cv::matchTemplate(gref, gtpl, res, CV_TM_CCOEFF_NORMED);
    cv::threshold(res, res, 0.9, 1., CV_THRESH_TOZERO);
    
    int count = 0;
    while (true)
    {
        double minval, maxval, threshold = 0.9;
        cv::Point minloc, maxloc;
        cv::minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);
        
        if (maxval >= threshold)
        {
            cv::rectangle(
                          ref,
                          maxloc,
                          cv::Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows),
                          CV_RGB(0,255,0), 2
                          );
            cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.));
            count++;
        }
        else
            break;
    }
    
    NSLog(@"# of matches: %d", count);

    return count;
}

Image

@samwize

¯\_(ツ)_/¯

Back to Home