直观原理来自:
它是怎么实现的?
-
我们需要2幅图像:
- 原图像 (I): 在这幅图像里,我们希望找到一块和模板匹配的区域
- 模板 (T): 将和原图像比照的图像块
我们的目标是检测最匹配的区域:
-
为了确定匹配区域, 我们不得不滑动模板图像和原图像进行 比较 :
-
通过 滑动, 我们的意思是图像块一次移动一个像素 (从左往右,从上往下). 在每一个位置, 都进行一次度量计算来表明它是 “好” 或 “坏” 地与那个位置匹配 (或者说块图像和原图像的特定区域有多么相似).
-
对于 T 覆盖在 I 上的每个位置,你把度量值 保存 到 结果图像矩阵 (R) 中. 在 R 中的每个位置
都包含匹配度量值:
上图就是 TM_CCORR_NORMED 方法处理后的结果图像 R . 最白的位置代表最高的匹配. 正如您所见, 红色椭圆框住的位置很可能是结果图像矩阵中的最大数值, 所以这个区域 (以这个点为顶点,长宽和模板图像一样大小的矩阵) 被认为是匹配的.
-
实际上, 我们使用函数 minMaxLoc 来定位在矩阵 R 中的最大值点 (或者最小值, 根据函数输入的匹配参数) .
具体措施:
六种常见模板匹配:
其中TM_CCORR最不准
T为模板,I为图像,x',y'为模板的长宽。
1,计算平方不同:
2,计算相关性:
3,计算相关系数:
4,计算归一化平方不同
5,计算归一化相关性
6,计算归一化相关系数
汇总表:
API:
matchTemplate(
InputArray image,// 源图像,必须是8-bit或者32-bit浮点数图像
InputArray templ,// 模板图像,类型与输入图像一致
OutputArray result,// 输出结果,必须是单通道32位浮点数,
//假设源图像WxH,模板图像wxh, 则结果必须为W-w+1, H-h+1的大小(每个窗口对比完之后,结果只有一 个数)。
int method,//使用的匹配方法 InputArray mask=noArray()//(optional) )
minMaxLoc ( //寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置
InputArray src, //输入图像
double* minVal, //最小值,可以为0表示不要
double* maxVal=0, //最大值,可以为0表示不要
Point* minLoc=0, //最小值坐标
Point* maxLoc=0, //最大值坐标
const Mat& mask=Mat() //掩膜
);
代码如下:
-
#include<opencv2\opencv.hpp>
-
#include<iostream>
-
#include<math.h>
-
using namespace cv;
-
using namespace std;
-
Mat t1, t2, result,t11;
-
int n = 0, m = 5;
-
char *c1 = "OLD", *c2 = "template", *c3 = "result";
-
void MO(int, void*);
-
int main(int agrc, char* agrv) {
-
t1 = imread("test.png");
-
t2 = imread("testamo.png");
-
if (!t1.data || !t2.data) {
-
cout << "wrong";
-
return -1;
-
}
-
namedWindow(c1, 0);
-
namedWindow(c2, 0);
-
namedWindow(c3, 0);
-
createTrackbar("type", c3, &n, m, MO);
-
MO(0, 0);
-
waitKey(0);
-
}
-
void MO(int, void*) {
-
int row = t1.rows - t2.rows + 1;
-
int col = t1.cols - t2.cols + 1;
-
result.create(row, col, CV_32FC1);
-
matchTemplate(t1, t2, result, n, Mat());
-
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());//这句很重要不然一片白
-
Point min, max;
-
double mi, ma;
-
minMaxLoc(result, &mi, &ma, &min, &max,Mat());
-
Point end;
-
if (n == 0 || n == 1) {
-
end = min;
-
}
-
else {
-
end = max;
-
}
-
t1.copyTo(t11);//没有这个图矩形框直接画在t1上不会消失
-
rectangle(t11,Rect(end.x, end.y, t2.cols, t2.rows), Scalar(150, 250, 180), 2, 8);
-
rectangle(result, Rect(end.x, end.y, t2.cols, t2.rows), Scalar(150, 200, 180), 2, 8);
-
imshow(c1, t11);
-
imshow(c2, t2);
-
imshow(c3, result);
-
}