Bhushan
Bhushan

Reputation: 1547

Template matching in openCV [JAVA]

I am using OpenCV(opencv_java248). I have one template image. This template image have logo some company. I want to know if this logo contain in other image. I got following code somewhere.

public void run(String inFile, String templateFile, String outFile,
        int match_method) {
    System.out.println("Running Template Matching");

    Mat img = Highgui.imread(inFile);
    Mat templ = Highgui.imread(templateFile);

    // / Create the result matrix
    int result_cols = img.cols() - templ.cols() + 1;
    int result_rows = img.rows() - templ.rows() + 1;
    Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

    // / Do the Matching and Normalize
    Imgproc.matchTemplate(img, templ, result, match_method);
    // Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new
    // Mat());
    Imgproc.threshold(result, result, 0.5, 1.0, Imgproc.THRESH_TOZERO);
    // / Localizing the best match with minMaxLoc
    MinMaxLocResult mmr = Core.minMaxLoc(result);

    Point matchLoc;
    if (match_method == Imgproc.TM_SQDIFF
            || match_method == Imgproc.TM_SQDIFF_NORMED) {
        matchLoc = mmr.minLoc;
    } else {
        matchLoc = mmr.maxLoc;
    }
    double threashhold = 0.40;
    if (mmr.maxVal > threashhold) {
        Core.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
                matchLoc.y + templ.rows()), new Scalar(0, 255, 0));
    }
    // Save the visualized detection.
    Highgui.imwrite(outFile, img);
}

It is working great when template and target image is of same scale. My question is how can I make it scale irrelevant ? My search image Target Image and logo Template

Upvotes: 0

Views: 8369

Answers (1)

user3510227
user3510227

Reputation: 576

Some images of what you want to match or some code would be really useful.

I don't know the Java API but did recently look into something similar written in C++. Converting should be fairly straightforward as the process will be same in either language.

Firstly perform template matching as normal, read in your images and create a mat to hold the result.

cv::Mat drawing = cv::imread(_drawing); //Read drawing
cv::Mat tmp = cv::imread(_tmp);  //Read template
cv::Mat res(drawing.rows - tmp.rows + 1, drawing.cols - tmp.cols + 1, CV_32FC1); //Create result matrix

//Perform template matching, normalise results 0 -> 1
cv::matchTemplate(tmp, drawing, res, CV_TM_CCOEFF_NORMED);
cv::threshold(res, res, 0.8, 1.0, CV_THRESH_TOZERO); //Can thresh to filter results if needed

Now that the result is populated, create variables for holding the min/max scores and their locations within the result matrix.

A tolerance value is used to filter acceptable results, where 1.0 can be seen as a 100% match and 0.25 as 25%.

//min/max values and acceptable tolerance
double min, max, tolerance = 0.90;
cv::Point minloc, maxloc; //min/max value locations

Now extract values from the result and check your max value against your tolerance, if it's within the tolerance its a match.

You can also loop this process and check through all the results to see if your image contains multiple occurences of the template.

//Loop through all results
while (true){

    //Pull out min/max values from results matrix
    cv::minMaxLoc(res, &min, &max, &minloc, &maxloc);

    //Is max within tolerance
    if (max >= tolerance){

        //Yes - Match found, do stuff //

        //Blank out that result in matrix so next highest can be extracted
        cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(0.1), cv::Scalar(1.0));

    }
    else
        break; //No more results within tolerance, break search
}

You'll likely need to experiment with tolerances / image quality and what counts as a pass. But for simple matching this works fairly well.

Edit - Template Matching & Scale

Standard template matching performs very poorly with scaling simply because of how it works - the search window can only be as small as the provided template, so finding anything smaller (or larger) is going to be difficult.

Refining template matching for scale invariance isn't the easiest thing to do, a simple method you could try is creating scaled variations of the template (have a look at OpenCVs Image Pyramids).

There are also plenty of papers out there covering more advanced variations of template matching if interested (a Google search will bring most up).

You might want to look into feature detection which is invariant to scale and rotation.

Again, if you could post a picture of your logo and search image that would help, there might be a simple alternative.

Upvotes: 5

Related Questions