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();
}
2 | No.2 Revision |
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.
3 | No.3 Revision |
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);
}
4 | No.4 Revision |
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);
}