匹配多个结果需要使用多模板匹配,本节详细介绍如何实现多模板匹配,并且获取多模板匹配的结果。想要匹配多个结果,需要利用阈值进行处理。

有些情况下要搜索的模板图像,很可能在输入图像类出现了多次,这时就需要找出多个匹配结果。而函数cv2.minMaxLoc()仅仅能找出最值,无法给出所有匹配区域的位置信息。所以,想要匹配多个结果,使用函数cv2.minMaxLoc()是无法实现的,需要利用阈值进行处理。下面将分步骤进行介绍。

1、获取匹配位置的集合

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

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

例:查找在一维数组a中,数值大于5的元素索引。

import numpy as np
a = np.array([3,6,8,1,2,15])
b = np.where(a>5)
print(b)

运行结果:

(array([1, 2, 5], dtype=int64),)

说明索引为1、2、5的数组元素,它们的值是大于5的(数组的索引从0开始)

例2:查找在二维数组am中,数值大于5的元素索引。

import numpy as np
a = np.array([[3,6,8,1,2,15],[2,12,4,1,34,0],[3,11,2,2,7,4]])
b = np.where(a>5)
print(b)

运行结果:

(array([0, 0, 0, 1, 1, 2, 2], dtype=int64),

array([1, 2, 5, 1, 4, 1, 4], dtype=int64))

也就是说在数组a中,[0, 1]、[0, 2]、[0, 5]、[1, 1]、[1, 4]、[2, 1]、[2, 4]位置上的元素大于5


也就是说,函数np.where()可以找出函数cv2.matchTemplate()返回值中,那些位置上的值是大于阈值的。

loc = np.where(res >= threshold)

2、循环

语法:https://www.runoob.com/python/python-for-loop.html

在获取匹配值的索引集合后,可以采用如下语句遍历所有匹配的位置,对这些位置做标记:

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

3、在循环中使用函数zip

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

例:使用zip()函数将t内对应的元素打包成一个个元组,并打印由这些元组组成的列表。

x = [1,2,3]
y = [4,5,5]
z = [7,8,9]
t = (x,y,z)
print(t)
for i in zip(*t):
    print(i)

运行结果:

([1, 2, 3], [4, 5, 5], [7, 8, 9]) #print的结果

(1, 4, 7)
(2, 5, 8)
(3, 5, 9)

再回到第一步里面的那个例子:

例2:查找在二维数组am中,数值大于5的元素索引。

import numpy as np
a = np.array([[3,6,8,1,2,15],[2,12,4,1,34,0],[3,11,2,2,7,4]])
print(a)
b = np.where(a>5)
for i in zip(*b):
    print(i)

运行结果:

[[ 3 6 8 1 2 15]
[ 2 12 4 1 34 0]
[ 3 11 2 2 7 4]]
(0, 1)
(0, 2)
(0, 5)
(1, 1)
(1, 4)
(2, 1)
(2, 4)

4、调整坐标

使用函数numpy.where()在函数cv2.matchTemplate()的输出值中查找指定值,得到的形式为“(行号,列号)”的位置索引。

但是,cv2.rectangle()中用于指定顶点的参数所用的形式为"(列号,行号)"的位置索引。所以在绘制方形之前,需要将行列互换。

可以使用如下语句实现loc内行列位置的互换:

loc[::-1]

例1:改变第三部结果的二维索引位置。

import numpy as np
a = np.array([[3,6,8,1,2,15],[2,12,4,1,34,0],[3,11,2,2,7,4]])
b = np.where(a>5)
for i in zip(*b):
    print(i[::-1])

运行结果:

(1, 0)
(2, 0)
(5, 0)
(1, 1)
(4, 1)
(1, 2)
(4, 2)

5、标记匹配图像的位置

关于矩形的对角顶点:

  • 其中的一个对角顶点可以通过for循环语句,从确定满足条件的匹配位置集合内获取
  • 另一个对角点,可以通过计算得到
for i in 匹配位置集合:
    cv2.rectangle(输入图像, i, (i[0]+w, i[1]+h), 255, 2)

例:使用模板匹配方式,标记在输入图像内与模板图匹配的多个子图像。

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

img = cv2.imread(r'E:\Blog\OpenCV\mulbaicai.png',0)
template = cv2.imread(r'E:\Blog\OpenCV\meye.png',0)
w,h = template.shape[::-1]
res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.7
loc = np.where(res>=threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(img,pt,(pt[0]+w,pt[1]+h),255,2)
plt.imshow(img,cmap='gray')
plt.xticks([]),plt.yticks([])
plt.show()

运行结果:

匹配结果


素材:

mulbaicai

meye


博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2022/OpenCV49.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 05 月 26 日
如果觉得我的文章对你有用,请随意赞赏