多模板匹配---OpenCV-Python开发指南(34)

举报
择城终老 发表于 2021/07/27 00:17:12 2021/07/27
【摘要】 目录 多模板匹配获取匹配位置的集合循环在循环中使用zip()替换坐标 实战多模板匹配 多模板匹配 在上一篇的实战中,我们通过人物眼睛的子图,找出了其在图像中出现位置。但是,有些情况下,并不仅仅只有一次,比如我们讲解傅里叶变换时,曾介绍一张草原的狮子图。如果匹配某个草,可能单个图像内会有很多,这个时候就要找出多个匹配结果。 而函数cv2.minMax...

多模板匹配

在上一篇的实战中,我们通过人物眼睛的子图,找出了其在图像中出现位置。但是,有些情况下,并不仅仅只有一次,比如我们讲解傅里叶变换时,曾介绍一张草原的狮子图。如果匹配某个草,可能单个图像内会有很多,这个时候就要找出多个匹配结果。

而函数cv2.minMaxLoc()仅仅能找出最值,无法给出所有匹配区域的位置信息。所以,要想匹配多个结果,就需要进行如下4个步骤:

获取匹配位置的集合

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

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

比如,我们的灰度图像一般都是二维数组。下面,我们来查找一个二维数组中,值大于8的元素索引:

import numpy as np

img = np.array([[2, 4, 6, 8, 10], [9, 60, 10, 30, 4], [55, 21, 11, 7, 5]])
result = np.where(img > 5)
print(result)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

运行之后,控制台会输出如下内容:
输出结果
如果你对Numpy不是很了解的化。下面博主在将数据转换以下,基本上都能看懂了。转换之后,格式如下:
转换
第一行为大于5的值的X坐标,第二行为大于5的值的Y坐标。那么上面大于5的数组索引为:[0,2],[0,3],[0,4],[1,0],[1,1],[1,2],[1,3],[2,0],[2,1],[2,2],[2,3]。你可以回溯对比看看是不是一致的。

通过np.where()函数可以找出在cv2.matchTemplate()函数的返回值中,哪些位置上的值是大于阈值threshold的。具体操作代码如下:

loc=np.where(res>threshold)

  
 
  • 1

循环

因为我们找到的原图对应的模板图像不止一个,要处理多个值,肯定会用到循环。因此,在获取匹配值的索引后,可以采用如下语句遍历所有匹配的位置,对这些位置做标记:

for i in 匹配位置集合:
	标记匹配位置

  
 
  • 1
  • 2

在循环中使用zip()

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

例如,我们获取的索引为x,y,z。下面我们使用zip()将它们打包成元组。代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = np.array([[2, 4, 6, 8, 10], [9, 60, 10, 30, 4], [55, 21, 11, 7, 5]])
result = np.where(img > 5)
for i in zip(*result): print(i)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里我们还是使用上面的值,输出结果如下:
符合条件
这里自动将我们刚才满足条件的索引打包成了元素格式。是不是比刚才的控制台输出结果更加的直观呢?

替换坐标

我们上面得到的结果是符合条件的索引:(行号,列号),但我们需要绘制匹配位置的矩形,需要的是(列号,行号)。

所以,在使用cv2.rectangle()绘制矩形前,要先将函数numpy.where()得到的位置索引行列互换,行列互换可以通过如下代码实现:

import numpy as np

img = np.array([[2, 4, 6, 8, 10], [9, 60, 10, 30, 4], [55, 21, 11, 7, 5]])
result = np.where(img > 5)
for i in zip(*result[::-1]): print(i)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行之后,输出结果如下:
行列互换

实战多模板匹配

既然我们已经了解了标记绘制多个模板位置的4个步骤。下面,我们直接将上面的代码整理以下,即可完成多模板的匹配。具体代码如下所示:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("34.jpg", 0)
template = cv2.imread("4_1.jpg", 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.9
loc = np.where(res >= 0.9)
for i in zip(*loc[::-1]): cv2.rectangle(img, i, (i[0] + w, i[1] + h), 255, 1)
plt.imshow(img, cmap="gray")
plt.axis("off")
plt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这里的代码与上面4个步骤一摸一样,具体就不做过多的讲解了。运行之后,多个模板也就匹配完成。
匹配多个模板
附录:

模板图

模板图
原图

原图

文章来源: liyuanjinglyj.blog.csdn.net,作者:李元静,版权归原作者所有,如需转载,请联系作者。

原文链接:liyuanjinglyj.blog.csdn.net/article/details/114031709

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。