模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术.
模板匹配函数:
void matchTemplate(InputArray image, InputArray temp1, OutputArray result, int method);
参数说明:
image,待搜索的图像,且需为 8 位或 32 位浮点型图像。
temp1,搜索模板,需要和原图片有一样的数据类型,且尺寸不能大于源图像。
result,比较结果的映射图像,其必须为单通道、32 位浮点型图像,大小为 (image.cols - temp1.cols +1)×(image.rows - temp1.rows +1)
method,匹配方法,
enum TemplateMatchModes {
TM_SQDIFF = 0, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\f]
TM_SQDIFF_NORMED = 1, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
TM_CCORR = 2, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\f]
TM_CCORR_NORMED = 3, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
TM_CCOEFF = 4, //!< \f[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\f]
//!< where
//!< \f[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\f]
TM_CCOEFF_NORMED = 5 //!< \f[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\f]
};
使用案例:
bool use_mask;
Mat img;
Mat templ;
Mat mask;
Mat result;
int match_method=0;
void MatchingMethod(int, void *, Mat rem) {
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create(result_rows, result_cols, CV_32FC1);
bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED);
if (use_mask && method_accepts_mask) {
matchTemplate(img, templ, result, match_method, mask);
}
else {
matchTemplate(img, templ, result, match_method);
}
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
double minVal;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) {
matchLoc = minLoc;
}else {
matchLoc = maxLoc;
}
// rectangle(rem, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows),
// Scalar::all(0), 8, 8, 0);
rectangle(rem, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows),
Scalar::all(0), 2, 8, 0);
}
JNIEXPORT void JNICALL
Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv *, jobject, jlong addrGray,
jlong addrRgba) {
Mat &mGr = *(Mat *) addrGray;
Mat &mRgb = *(Mat *) addrRgba;
vector<KeyPoint> v;
looperAddNum++;
if (looperAddNum > 60) {
looperAddNum = 0;
if (looperIndexNum < 100)
looperIndexNum += 1;
}
img = mRgb.clone();
Rect r(mRgb.cols / 8 * 2, mRgb.rows / 8 * 2, mRgb.cols / 8 * 4, mRgb.rows / 8 * 4);
templ = img(r);
MatchingMethod(0, 0, mRgb);
LOGI("index %d", looperIndexNum);
}