Reputation: 1547
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 and logo
Upvotes: 0
Views: 8369
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