I'm using OpenCV 3.0.0 to locate an image into another image. A priori the function matchTemplate is what i need to use, but seeing the results i am not sure anymore.
The problem is that depending on the input images, the result is perfectly accurate or completely inaccurate.
Example 1:
Main image
Template
Result
No complaints here. The matching is perfect in this case. But now i replace the images for the ones i want to use and...
Main image
Template
Result
So, not working at all (result rectangle on top right of the image). Any of the methods (in this example CORR NORMED) prints the rectangle where the template is located. All the results are far away from being accurate.
So, my question is, does the result of matchTemplate depend on how many different colors/shapes the main image has? Would SURF or SIFT help me here? Do you guys now any function that would help me locate a template into another image?
Thank you in advance!
PS: I didn't add any code because i guess is not that kind of problem, since the first example works well.
Your problem might be, that template matching isnt scale invariant, your template size doestn fit the objects size.
Using this input, and code I get that output:
input image:
input template:
code: taken basically from opencv tutorial: http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
int main()
{
cv::Mat input = cv::imread("../inputData/TemplateMatch.jpg");
cv::Mat gray;
cv::cvtColor(input,gray,CV_BGR2GRAY);
cv::Mat templ = cv::imread("../inputData/Template2.jpg");
cv::Mat img = input;
cv::Mat result;
/// Create the result matrix
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );
int match_method = CV_TM_SQDIFF;
/// Do the Matching and Normalize
matchTemplate( img, templ, result, match_method );
normalize( result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
cv::Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
{ matchLoc = minLoc; }
else
{ matchLoc = maxLoc; }
/// Show me what you got
cv::rectangle( input, matchLoc, cv::Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), cv::Scalar::all(0), 2, 8, 0 );
cv::rectangle( result, matchLoc, cv::Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), cv::Scalar::all(0), 2, 8, 0 );
cv::imshow("input", input);
cv::imshow("template", templ);
cv::imwrite("../outputData/TemplateMatch.jpg", input);
cv::waitKey(0);
return 0;
}
output: