模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术。通常被用于目标检测、相似度分析中, 在目标图像中快速找到待匹配对象的位置。
模板匹配API 函数——cv::matchTemplate()
函数声明如下,
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
OutputArray result, int method );
image:待匹配的源图像
templ:模板图像
result:保存结果的矩阵,我们可以通过minMaxLoc() 确定结果矩阵的最大值和最小值的位置
minMaxLoc()函数:查找全局最小和最大稀疏数组元素并返回其值及其位置,函数声明如下,
method :模板匹配的算法
在OpenCV中提供了如下6种匹配度量方法,
enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
1)平方差匹配法CV_TM_SQDIFF
2)归一化平方差匹配法CV_TM_SQDIFF_NORMED
3)相关匹配法CV_TM_CCORR
4)归一化相关匹配法CV_TM_CCORR_NORMED
5)系数匹配法CV_TM_CCOEFF
6)化相关系数匹配法CV_TMCCOEFF_NORMED
通常来讲,随着从简单测量方法(平方差)到更复杂的测量方法(相关系数法),我们可以获得越来越准确的匹配。然而这同时也会以越来越大的计算量为代价。对于选取何种方法,针对不同的匹配情况进行对此分析比较,选取更适合自己应用场景同时兼顾速度和精度的最佳方案。
注意:TM_SQDIFF,TM_SQDIFF_NORMED匹配数值越低表示匹配效果越好,其它四种反之。TM_SQDIFF_NORMED,TM_CCORR_NORMED,TM_CCOEFF_NORMED是标准化的匹配,得到的最大值,最小值范围在0~1之间,其它则需要自己对结果矩阵归一化。
不同的方法会得到差异很大的结果,可以通过测试选择最合适的方法。
模板匹配需要结合minMaxLoc函数一起使用,说明如下,
void minMaxLoc(const SparseMat& a, double* minVal,double* maxVal, int* minIdx=0, int* maxIdx=0);
a: 匹配结果矩阵
&minVal 和 &maxVal: 该矩阵 result 中存储的最小值和最大值
&minLoc 和 &maxLoc: 在结果矩阵中最小值和最大值的坐标
模板匹配功能实现可参考如下代码,
void templateMatching(const Mat& srcImage, const Mat& templateImage)
{
Mat result;
//enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
matchTemplate(srcImage, templateImage, result, TM_CCOEFF_NORMED); //最好匹配为1,值越小匹配越差
double minVal = -1;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
//取大值(视匹配方法而定)
//matchLoc = minLoc;
matchLoc = maxLoc;
cv::Mat image_color;
cv::cvtColor(srcImage, image_color, IMREAD_COLOR);
Mat mask = image_color.clone(); //绘制最匹配的区域
rectangle(mask, matchLoc, Point(matchLoc.x + templateImage.cols, matchLoc.y + templateImage.rows), Scalar(0, , 0), 2, 8, 0);
imshow(匹配后的图像, mask);
waitKey(0);
}
模板匹配函数调用示例如下,
//模板匹配处理的是灰度图
cv::Mat templateImage = imread(E:/Image/broad tm plate.jpg, cv::IMREAD_GRAYSCALE /*cv::IMREAD_COLOR*/);
cv::Mat image = imread(E:/Image/broad.jpg, cv::IMREAD_GRAYSCALE/*cv::IMREAD_COLOR*/);
imshow(templateImage, templateImage);
imshow(image, image);
waitKey(0);
templateMatching(image, templateImage);
注意:
1)图像尺寸比例要一致,模板图像是从测试图像大小的图像中截取得到的
2)处理灰度图
3)模板的样式 需要与图像中待匹配的对象 样式一致
OpenCV官方图片,data/broad.jpg测试,测试图像,
模板图像,
模板匹配效果图,