第15章:模板匹配

第15章:模板匹配

    • 一、模板匹配基础:
      • 1. cv2.matchTemplate()函数:
      • 2. 匹配原理:
      • 3. 查找最值:
    • 二、多模版匹配:
      • 1. 获取匹配位置集合:
      • 2. 循环:
      • 3.调整坐标
      • 4.标记匹配图像的位置

模板匹配是指在当前图像A内匹配与图像B最相似的部分,一般将图像A称为输入图像,将图像B称为模板图像 模板匹配的方法是将模板图像B在图像A上滑动,逐个遍历所有像素以完成匹配。

​ 例如,下图中,大图像“lena”是输入图像,“眼睛”图像是模板图像。查找的方式是,将模板图像在输入图像内从左上角开始滑动,逐个像素遍历整幅输入图像,以查找与其最匹配的部分。

image-20211207201523166

一、模板匹配基础:

1. cv2.matchTemplate()函数:

在OpenCV内,通过函数cv2.matchTemplate()实现模板匹配。语法格式为:

  • result=cv2.matchTemplate(image,templ,method[,mask])

    • image:为原始图像,必须是8位或者32位的浮点型图像。

    • templ:为模板图像。它的尺寸必须小于或等于原始图像,并且与原始图像具有同样的类型。

    • method:为匹配方法。该参数通过TemplateMatchModes实现,有6种可能的值,如表所示。

      image-20211207201540228

      其具体对应的计算公式:

      image-20211207201559360

    • mask: 为模板图像掩模。它必须和模板图像 templ 具有相同的类型和大小。通常情况下该值使用默认值即可。当前,该参数仅支持TM_SQDIFF和TM_CCORR_NORMED两个值。

函数cv2.matchTemplate()的返回值result 是一个结果集。类型是单通道32位浮点型。是由每个位置的比较结果所构成的。

2. 匹配原理:

​ 如果输入图像(原始图像)尺寸是W * H,模板的尺寸是w * h,则返回值的大小为(W-w+1)*(H-h+1)。

在进行模板匹配时,模板在原始图像内遍历。在水平方向上:

  • 遍历的起始坐标是原始图像左数第1个像素值(序号从1开始)。
  • 最后一次比较是当模板图像位于原始图像的最右侧时,此时其左上角像素点所在的位置是W-w+1。

因此,返回值result在水平方向上的大小是W-w+1(水平方向上的比较次数)。

在垂直方向上:

  • 遍历的起始坐标从原始图像顶端的第1个像素开始。
  • 最后一次比较是当模板图像位于原始图像的最下端时,此时其左上角像素点所在位置是H-h+1。

所以,返回值result在垂直方向上的大小是H-h+1(垂直方向上的比较次数)。

如果原始图像尺寸是 W * H,模板的尺寸是w * h,则返回值的大小为(W-w+1)* (H-h+1)。也就是说,模板图像要在输入图像内比较(W-w+1)*(H-h+1)次。

image-20211207202212553

例如,在上图中,左上方的2×2小方块是模板图像,右下方的10×10图像是输入图像(原始图像)。在进行模板匹配时:

  • 首先将模板图像置于输入图像的左上角。
  • 模板图像在向右移动时,最远只能位于输入图像的最右侧边界处,此时模板图像左上角的像素对应着输入图像的第9列(输入图像宽度-模板图像宽度+1=10-2+1=9)。
  • 模板图像在向下移动时,最远只能位于输入图像最下端的边界处。此时模板图像左上角的像素对应着输入图像的第9行(输入图像高度-模板图像高度+1=10-2+1=9)。

根据上述分析可知,比较结果result的大小满足(W-w+1)*(H-h+1),在上例中就是(10-2+1)×(10-2+1),即9×9。也就是说,模板图像要在输入图像内总计比较9×9=81次,这些比较结果将构成一个9×9大小的二维数组。

需要注意的是,函数cv2.matchTemplate()通过参数method来决定使用不同的查找方法。对于不同的查找方法,返回值result具有不同的含义。例如:

  • method的值为cv2.TM_SQDIFF和cv2.TM_SQDIFF_NORMED时,result值为0表示匹配度最好,值越大,表示匹配度越差。
  • method 的值为 cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_CCOEFF 和cv2.TM_CCOEFF_NORMED时,result的值越小表示匹配度越差,值越大表示匹配度越好。

查找方法不同,结果的判定方式也不同。在查找最佳匹配时,首先要确定使用的是何种method,然后再确定到底是查找最大值,还是查找最小值。

3. 查找最值:

查找最值(极值)与最值所在的位置,可以使用 cv2.minMaxLoc()函数实现。语法格式如下:

  • minVal,maxVal,minLoc,maxLoc=cv2.minMaxLoc(src[,mask])
    • src:为单通道数组。
    • minVal:为返回的最小值,如果没有最小值,则可以是NULL(空值)。
    • maxVal:为返回的最大值,如果没有最小值,则可以是NULL。
    • minLoc:为最大值的位置,如果没有最大值,则可以是NULL。
    • maxLoc:为最大值的位置,如果没有最大值,则可以是NULL。
    • mask:为用来选取掩模的子集,可选项

函数 cv2.minMaxLoc()能够查找整个数组内的最值及它们的位置,并且可以根据当前的掩模集来选取特定子集的极值。有关该函数的更多说明及实例,请参考第12章。

综上所述,函数cv2.matchTemplate()返回值中的最值位置就是模板匹配的位置。

例如,当method的值为cv2.TM_SQDIFF和cv2.TM_SQDIFF_NORMED时,0表示最佳匹配,值越大,则表示匹配效果越差。当使用这两种方法时,要寻找最小值所在的位置作为最佳匹配。如下语句能够找到cv2.matchTemplate()函数返回值中最小值的位置:

  • minVal,maxVal,minLoc,maxLoc=cv2.minMaxLoc(matchTemplate函数的返回值)

    topLeft=minLoc # 查找最小值所在的位置

以topLeft点为模板匹配位置的左上角坐标,结合模板图像的宽度w和高度h可以确定匹配位置的右下角坐标,代码如下所示:

  • bottomRight=(topLeft[0]+w,topLeft[1]+h)  #w和h是模板图像的宽度和高度

当 method 的值为 cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_CCOEFF 和cv2.TM_CCOEFF_NORMED时,cv2.matchTemplate()函数的返回值越小,表示匹配度越差,而返回值越大则表示匹配度越好。此时,要寻找最大值所在的位置作为最佳匹配。

通过上述方式,我们确定了模板匹配的矩形对角坐标位置,接下来可以借助函数cv2.rectangle()将该位置用白色标记出来。

函数cv2.rectangle的语法格式为:

  • Img=cv.rectangle(img,pt1,pt2,color[,thickness])
    • img:表示要标记的目标图像。
    • pt1:是矩形的顶点。
    • pt2:是pt1的对角顶点。
    • color:是要绘制矩形的颜色或灰度级(灰度图像)。
    • thickness:是矩形边线的宽度。

因此,使用的标记语句为:cv2.rectangle(img,topLeft,bottomRight,255,2)

import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('../lena.bmp')
template = cv2.imread('../template.bmp')th, tw = template.shape[:2]
rv = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(rv)top_left = min_loc
bottom_right = (top_left[0] + tw, top_left[1] + th)
new_img = img.copy()
cv2.rectangle(new_img, top_left, bottom_right, 255, 2)plt.subplot(131)
plt.imshow(template, cmap='gray')
plt.title('template')
plt.axis('off')plt.subplot(132)
plt.imshow(rv, cmap='gray')
plt.title('matcing result')
plt.axis('off')plt.subplot(133)
plt.imshow(new_img, cmap='gray')
plt.title('result')
plt.axis('off')plt.show()

image-20211208120016436

二、多模版匹配:

前面的例子中,我们在输入图像lena中搜索其眼部子图,该子图在整个输入图像内仅出现了一次。但是,有些情况下,要搜索的模板图像很可能在输入图像内出现了多次,这时就需要找出多个匹配结果。而函数 cv2.minMaxLoc()仅仅能够找出最值,无法给出所有匹配区域的位置信息。所以,要想匹配多个结果,使用函数 cv2.minMaxLoc()是无法实现的,需要利用阈值进行处理,来获取所有匹配的集合。

1. 获取匹配位置集合:

numpy模块中的函数where()能够获取模板匹配位置的集合。对于不同的输入,其返回的值是不同的。

  • 当输入(参数)是一维数组时,返回值是一维索引,只有一组索引数组。
  • 当输入是二维数组时,返回的是匹配值的位置索引,因此会有两组索引数组表示返回值的位置。

例如:

# 当输入数组是一维时
import numpy as npa=np.array([3,6,8,1,2,88])
b=np.where(a>5)
print(b)# 输出结果
(array([1,2,5],dtype=int64),)
# 当输入数组是二维时
import numpy as npam=np.array([[3,6,8,77,66],[1,2,88,3,98],[11,2,67,5,2]])
b=np.where(am>5)
print(b)# 输出结果
(array([0,0,0,0,1,1,2,2],dtype=int64),
array([1,2,3,4,2,4,0,2],dtype=int64))

综上所述,函数 np.where()可以找出在函数 cv2.matchTemplate()的返回值中,哪些位置上的值是大于阈值threshold的。

具体实现时,可以采用的语句为:

  • loc=np.where(res >=threshold)
    • res:是函数cv2.matchTemplate()进行模板匹配后的返回值。
    • threshold:是预设的阈值
    • loc:是满足“res >=threshold”的像素点的索引集合。

2. 循环:

处理多个值,通常需要用到循环。因此,在获取匹配值的索引集合后,可以采用如下语句遍历所有匹配的位置,对这些位置做标记:

for i in 匹配位置集合:

​ 标记匹配位置。

在循环处理匹配位置的时候,可以在循环中使用函数zip():

函数zip()用可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
例如:

import numpy as npam = np.random.randint(0, 50, size=(3, 5))
print(am)
b = np.where(am > 20)
print(b)
for i in zip(*b):print(i)# 输出结果
[[37 39 43 48 49][16 48 37 23 25][44 40  0 44 38]]
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int64), array([0, 1, 2, 3, 4, 1, 2, 3, 4, 0, 1, 3, 4], dtype=int64))
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(2, 0)
(2, 1)
(2, 3)
(2, 4)

因此,如果希望循环遍历由np.where()返回的模板匹配索引集合,可以采用的语句为:

for i in zip(*模板匹配索引集合):

​ 标记处理

3.调整坐标

函数 numpy.where()可以获取满足条件的模板匹配位置集合,然后可以使用函数cv2.rectangle()在上述匹配位置绘制矩形来标注匹配位置。

使用函数numpy.where()在函数cv2.matchTemplate()的输出值中查找指定值,得到的形式为“(行号,列号)”的位置索引。但是,**函数cv2.rectangle()中用于指定顶点的参数所使用的是形式为“(列号,行号)”的位置索引。**所以,在使用函数cv2.rectangle()绘制矩形前,要先将函数numpy.where()得到的位置索引做“行列互换”。可以使用如下语句实现loc内行列位置的互换:

  • loc[::-1]

4.标记匹配图像的位置

函数cv2.rectangle()可以标记匹配图像的具体位置,分别指定要标记的原始图像、对角顶点、颜色、矩形边线宽度即可。

关于矩形的对角顶点:

  • 其中的一个对角顶点A可以通过for循环语句从确定的满足条件的“匹配位置集合”内获取。

  • 另外一个对角顶点,可以通过顶点A的位置与模板的宽(w)和高(h)进行运算得到。
    因此,标记各个匹配位置的语句为:

    • for i in 匹配位置集合:

      ​ cv2.rectangle(输入图像,i, (i[0] + w, i[1] + h ), 255, 2)

import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('../four_lena.bmp')
template = cv2.imread('../template.bmp')h, w = template.shape[:2]
rst = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED)
print(rst)
threshold = 0.99
loc = np.where(rst >= threshold)
new_img = img.copy()
for pt in zip(*loc):cv2.rectangle(new_img, pt, (pt[0] + w, pt[1] + h), 255, 1)plt.subplot(121)
plt.imshow(template, cmap='gray')
plt.title('template')
plt.axis('off')plt.subplot(122)
plt.imshow(new_img, cmap='gray')
plt.title('rst')
plt.axis('off')plt.show()

image-20211208152700302

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第16章:霍夫变换

第16章:霍夫变换一、霍夫直线变换:1. 霍夫直线变换原理:2. HoughLines函数:3. HoughLinesP函数:2. 霍夫圆环变换:霍夫变换是一种在图像中寻找直线、圆形以及其他简单形状的方法。霍夫变换采用类似于投票的方…

一个java处理JSON格式数据的通用类(三)

/** *//** * 从json数组中解析出java Integer型对象数组 * param jsonString * return */ public static Double[] getDoubleArray4Json(String jsonString)...{ JSONArray jsonArray JSONArray.fromObject(jsonString); Doubl…

【树莓派学习笔记】九、C语言寄存器操作控制GPIO

目录CPU型号确定寄存器的地址问题GPIO寄存器GPFESLnGPSETnGPCLRn重要函数mmap函数munmap函数点灯程序平台:树莓派3B 版本: 2021-05-07-raspios-buster-armhf CPU型号确定 由 pinout命令可知,所用的板子Soc型号为BCM2837 寄存器的地址问题…

bzoj2527

首先环可以变成链来处理,对于l>r的情况就是修改区间[1,r],[l,mx]然后不难想到整体二分,二分答案k,然后算1~k场流星雨对国家的贡献然后判定将国家划分变成子问题解决,没什么难的终于不是tle,poi良心了一把 1 type wayrecord2 …

第17章:图像分割提取

第17章:图像分割提取一、用分水岭算法实现图像分割提取:1. 算法原理:2. 相关函数介绍:(1) 形态学函数回顾:(2) 距离变换函数distanceTransform:(3) 确定未知区域:(4) 函数connectedComponents对…

[转]可伸缩系统的架构经验

最近,阅读了Will Larson的文章Introduction to Architecting System for Scale,感觉很有价值。作者分享了他在Yahoo!与Digg收获的设计可伸缩系统的架构经验。在我过往的架构经验中,由于主要参与开发企业软件系统,这种面向企业内部…

【Linux技巧】cmake、make命令多线程编译,大大提高编译速度

目录获取最大可用线程数自动以最大线程数编译makecmake效果系统:Debian 获取最大可用线程数 nprocnproc命令可返回当前可用的最大线程数 树莓派3B (BCM2837):4 RK3399 Pro:6 自动以最大线程数编译 make sudo make -j $(nproc)cmake su…

redis学习(九)——数据持久化

一、概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的。所以,我们需要将内存中的数据持久化!典型的需要持久…

【机器视觉学习笔记】生成高斯滤波器掩膜(C++)

目录原理二维高斯分布生成高斯掩膜(小数形式)源码及效果平台:Windows 10 20H2 Visual Studio 2015 OpenCV 4.5.3 本文算法摘自高斯滤波(GaussianFilter)原理及C实现 —— 小武~~ 原理 高斯滤波和均值滤波一样,都是利用一个掩膜…

第18章:视频处理

第18章:视频处理一、VideoCapture类:1. VideoCapture类中相关方法介绍:(1) 初始化:(2) 初始化判断方法:(3) 捕获帧:(4) 释放:(5) 属性设置:(6) 捕获多摄像头(视频文件)数据&#xff…

C++的常量折叠(一)

前言 前几天女票问了我一个阿里的面试题,是有关C语言的const常量的,其实她一提出来我就知道考察的点了:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配区是很普通的栈或者全局区域。也就是说const常量只…

【机器视觉学习笔记】二值图像和灰度图像的膨胀、腐蚀、开运算、闭运算算法(C++)

目录二值图像原理腐蚀结构的原点设置在结构内部情况举例结构的原点设置在结构的外部情况举例膨胀结构的原点设置在结构的内部情况举例结构的原点设置在结构的外部情况举例开闭运算完整源码效果原图腐蚀运算膨胀运算开运算闭运算灰度图像原理腐蚀膨胀开闭运算完整源码效果原图腐…

【机器视觉学习笔记】二值图像连通区域提取算法(C++)

目录原理二值图像连通区域(Connected Component)连通区域分析(Connected Component Analysis,Connected Component Labeling)算法:Two-Pass(两遍扫描法)思路:Two-Pass算法的简单步骤…

【机器视觉学习笔记】Harris 角点检测算法(C++)

目录原理算法步骤优缺点源码效果原图输出平台:Windows 10 20H2 Visual Studio 2015 OpenCV 4.5.3 本文摘自2、Harris角点检测算法 —— 诺亚方舟369 原理 Harris算子是对Moravec算子的改进,包括: (1)Harris算子用…

剖析ASSERT函数

2019独角兽企业重金招聘Python工程师标准>>>  搜集与总结了assert函数的用法,记于此,以备后续与查找使用: ****身在Windows的世界,但还是深爱着我的它---Linux****I love Linux forever***** …

MSP430G2553 移植 Contiki RTOS 实时操作系统

目录新建工程移植过程关于时间多任务示例main.c内存使用情况效果平台:Code Composer Studio 10.4.0 MSP-EXP430G2 LaunchPad 试验板 MSP430G2553 LaunchPad™ Development Kit (MSP‑EXP430G2ET) contiki下载:contiki-os Github 本文参考自二、Contiki…

Raphael JS 矢量客户端开源框架

之前有基于svg进行矢量绘制,当时是自己写的一些js类库,最近项目中需要,对Raphael做了一些了解,总体不错。 Raphael可以对浏览器的兼容做的不错,基于IE的会自动使用vml进行绘制,其他浏览器基于svg进行绘制&a…

mac os x10.8下如何使用git与github

2019独角兽企业重金招聘Python工程师标准>>> 1、准备工作: 下载安装git客户端 http://code.google.com/p/git-osx-installer/downloads/list?can3(安装了git客户端,命令行中才有git命令) 注册github账号 https://github.com/ -->Pricing …

使用 VS 附加到进程 调试发布的网站

适用场景:调试已发布的网站。 1、把项目 bin 目录下的 pdb 文件复制到服务器上相应网站的 bin 目录下。 2、把VS的调试工具中的 x64 文件夹复制到服务器任意位置。 3、服务器中打开调试工具,并配置端口(注意端口是否可用)。 4、在…

Github git 命令下载加速

目录手动输入法批处理文件系统:Windows 10 20H2 手动输入法 在要下载到的目录按住shift右键 选择在此处打开Powershell窗口 如要下载的仓库地址: 通常的git命令下载: git clone https://github.com/apache/incubator-nuttx.gitCNPMJS.ORG…