模板匹配就是按照一定的相似性规则,在一张图像中寻找与模板最相似的区域。
参考opencv官网:https://docs.opencv.org/3.4.1/de/da9/tutorial_template_matching.html
模板匹配的过程如下:
左上角小狗图像为定义的模板,下面的图片为待匹配图像,匹配的过程就是按照从左到右,从上到下的顺序,依次遍历全图,通过定义的相似度评判准则,计算模板与当前位置图像块的相似度,进而得到最相似位置,实现目标定位。
常见的相似度准则有:
即:平方差、归一化平方差、相关系数、归一化相关系数、互相关五种。
下面就是代码,这里只实现了两种:平方误差及绝对误差
#include <opencv2/opencv.hpp>
#include <math.h>
#include <iostream>
using namespace cv;
using namespace std;
#define SQDIFF 0
#define SADIFF 1
float templateMatch(const Mat & src, const Mat & temp, int & i_match, int & j_match, int Match_methold)
{
int src_cols = src.cols;
int src_rows = src.rows;
int temp_cols = temp.cols;
int temp_rows = temp.rows;
int i_end = src_rows - temp.rows + 1;
int j_end = src.cols - temp.cols + 1;
float match_degree = FLT_MAX;
for (int i = 0; i < i_end; i++)
{
for (int j = 0; j < j_end; j++)
{
float match_ij = 0.0;
for (int m = 0; m < temp_rows; m++)
{
for (int n = 0; n < temp_cols; n++)
{
uchar val_s = src.at<uchar>(i + m, j + n);
uchar val_t = temp.at<uchar>(m, n);
if (Match_methold == SQDIFF)
{
match_ij += float((val_t - val_s) * (val_t - val_s));
}
else if (Match_methold == SADIFF)
{
match_ij += float(abs(val_t - val_s));
}
}
}
//cout << match_ij << endl;
if (match_ij < match_degree)
{
match_degree = match_ij;
i_match = i;
j_match = j;
}
}
}
return match_degree;
}
int main()
{
Mat src = imread("messi5.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat temp = imread("face.png", CV_LOAD_IMAGE_GRAYSCALE);
float match_degree = 0;
int i_match = -1, j_match = -1;
match_degree = templateMatch(src, temp, i_match, j_match, SQDIFF);
cout << i_match << j_match << match_degree << endl;
Mat src_color;
cvtColor(src, src_color, COLOR_GRAY2BGR);
rectangle(src_color, Rect(j_match, i_match, temp.cols, temp.rows), Scalar(255, 0, 0));
imshow("result", src_color);
waitKey(0);
return 0;
}
匹配结果: