opencv笔记二十八(模板匹配(matchTemplate,较为低级必须是原图扣出来的一部分,且长宽都不能变才行,原理类似于卷积))

40 篇文章 4 订阅

直观原理来自:

https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

 

它是怎么实现的?

  • 我们需要2幅图像:

    1. 原图像 (I): 在这幅图像里,我们希望找到一块和模板匹配的区域
    2. 模板 (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() //掩膜

);

 

 

代码如下:

 
  1. #include<opencv2\opencv.hpp>

  2. #include<iostream>

  3. #include<math.h>

  4. using namespace cv;

  5. using namespace std;

  6. Mat t1, t2, result,t11;

  7. int n = 0, m = 5;

  8. char *c1 = "OLD", *c2 = "template", *c3 = "result";

  9. void MO(int, void*);

  10. int main(int agrc, char* agrv) {

  11. t1 = imread("test.png");

  12. t2 = imread("testamo.png");

  13. if (!t1.data || !t2.data) {

  14. cout << "wrong";

  15. return -1;

  16. }

  17. namedWindow(c1, 0);

  18. namedWindow(c2, 0);

  19. namedWindow(c3, 0);

  20. createTrackbar("type", c3, &n, m, MO);

  21. MO(0, 0);

  22.  
  23. waitKey(0);

  24. }

  25.  
  26. void MO(int, void*) {

  27. int row = t1.rows - t2.rows + 1;

  28. int col = t1.cols - t2.cols + 1;

  29. result.create(row, col, CV_32FC1);

  30. matchTemplate(t1, t2, result, n, Mat());

  31. normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());//这句很重要不然一片白

  32. Point min, max;

  33. double mi, ma;

  34. minMaxLoc(result, &mi, &ma, &min, &max,Mat());

  35. Point end;

  36. if (n == 0 || n == 1) {

  37. end = min;

  38. }

  39. else {

  40. end = max;

  41. }

  42. t1.copyTo(t11);//没有这个图矩形框直接画在t1上不会消失

  43. rectangle(t11,Rect(end.x, end.y, t2.cols, t2.rows), Scalar(150, 250, 180), 2, 8);

  44. rectangle(result, Rect(end.x, end.y, t2.cols, t2.rows), Scalar(150, 200, 180), 2, 8);

  45.  
  46. imshow(c1, t11);

  47. imshow(c2, t2);

  48. imshow(c3, result);

  49. }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值