opencv学习记录之模板匹配
Posted miaorn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv学习记录之模板匹配相关的知识,希望对你有一定的参考价值。
模板匹配是指在图像A中寻找与图像B最相似的部分,一般A称为输入图像,B称为模板图像
模板匹配函数
result = cv2.matchTemplate(image , temp1 , method , [,mask])
result 函数每次计算模板和输入图像的重叠区域相似度之后将结果存入映射图像result中,
result图像中每个点都代表一次相似度的比较,类型是单通道32位浮点型
若输入图像的尺寸位W×H,模板图像为w×h,则返回值为(W-w+1)×(H-h+1)
模板在原始图像上遍历,左上角的坐标从(0,0)开始到(W-w+1)×(H-h+1)
image为原始图像,即输入图像,必须是8位或者32位浮点型图像
temp1 位模板图像,尺寸必须小于或等于输入图像,并且与其类型相同
method位匹配方法,
参数值 | 对应数值 | 说明 | 公式 |
cv2.TM_SQDIFE | 0 | 以方差位依据进行匹配。若完全匹配,则结果位零;若不匹配,则会得到一个很大的值 | |
cv2.TM_SQDIFE_NORMED | 1 | 标准(归一化)平方差匹配 |
|
cv2.TM_ CCORR | 2 | 相关匹配,这类方法将模板图像与输入图像相乘,如果乘积较大 ,表示匹配程度较高;如果乘积位0,表示匹配效果最差 |
|
cv2.TM_CCORR_NORMED | 3 | 标准(归一化)相关匹配 |
|
cv2.TM_CCOEFF | 4 | 相关系数匹配,这类方法将模板图像与其均值的相对值,和输入图像与其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性 |
|
cv2.TM_ CCOEFF_NORMED | 5 | 标准(归一化)相关系数匹配 |
|
(I表示输入图像,T表示模板图像,R表示输出的结果图像,x,y表示位值信息
mask为模板图像掩模,必须与模板图像具有相同大小和类型,通常情况下使用默认值
从上表中可以看出method为,cv2.TM_SQDIFE和cv2.TM_SQDIFE时,result值为0表示匹配度最好,值越大,匹配度月差
method值为cv2.TM_CCORR , cv2.TM_CCORR_NORMED , cv2_TMCCOEFF 和 cv2.TM_CCOEFF_NORMED时,result的值
越小表示匹配度越差,值越大表示越好
查找方式的不同代表查找最佳匹配时也要先确定method值
然后使用函数查找最值与其为值
minVal , maxVal , minLoc , maxLoc = cv2.minMaxLoc( src , [,mask])
minVal 为返回的最小值,若没有则可以是NULL
maxVal为为返回最大值,若没有则可以是NULL
minLoc 为返回的最小值位置,若没有则可以是NULL
maxLoc 为返回的最大值位置,若没有则可以是NULL
返回值中的位置,时模板匹配位置的左上角坐标,结合模板图像的宽度w和高度h可以得到右下角的坐标(x+w,y+h)
可以通过函数将该位置用白色标记出来
Img = cv2.rectangle( img , pt1 , pt2 , colot [,thickness])
img 表示要标记的目标图像
pt1是矩形的顶点,
pt2是pt1的对角顶点
color是矩形的颜色
thickness是矩形边线的宽度
1 import cv2 2 import numpy as np 3 from matplotlib import pyplot as plt 4 img = cv2.imread("/home/miao/dog.jpg" , 0) 5 template = cv2.imread("/home/miao/dog_ex.jpg" , 0) 6 w , h = template.shape[::-1] 7 rv = cv2.matchTemplate(img , template , cv2.TM_SQDIFF) 8 minVal , maxVal , minLoc , maxLoc = cv2.minMaxLoc(rv) 9 topLeft = minLoc 10 bottomRight = ( topLeft[0] + w , topLeft[1] + h) 11 cv2.rectangle(img , topLeft , bottomRight, 255, 2) 12 # 13 plt.subplot(221) 14 plt.imshow(img , cmap = ‘gray‘) 15 plt.title("original") 16 plt.xticks([]) 17 plt.yticks([]) 18 # 19 plt.subplot(222) 20 plt.imshow(template , cmap = ‘gray‘) 21 plt.title("template") 22 plt.xticks([]) 23 plt.yticks([]) 24 # 25 plt.subplot(223) 26 plt.imshow(rv , cmap = ‘gray‘) 27 plt.title("rv") 28 plt.xticks([]) 29 plt.yticks([]) 30 # 31 plt.show()
这里的template应是60×40不知怎样将其调整为原始图像的大小
多模板匹配
获取位置的集合
1 import numpy as np 2 a = np.array([[2,4,6,34,6] , [4,23,56,1,23] , [41,52,12,34,2]] ) 3 b = np.where(a >5) 4 print(b)
得到
(array([0, 0, 0, 1, 1, 1, 2, 2, 2, 2]), array([2, 3, 4, 1, 2, 4, 0, 1, 2, 3]))
若参数为一维数组则返回值为一维索引
若参数为二维数组则返回的是位置,因此会有两组索引数组表示返回值的位置如上
通过函数np.where()得到两组索引数组后
通过函数zip() 可以将t内对应的元素打包成一个元组,这些元组组成列表
1 x = [1,2,3] 2 y = [4,5,6] 3 z = [7,8,9] 4 t = (x,y,z) 5 print(t) 6 for i in zip(*t): 7 print(i)
([1, 2, 3], [4, 5, 6], [7, 8, 9]) (1, 4, 7) (2, 5, 8) (3, 6, 9)
使用函数where()后得到的参数形式为(行号,列号)的位置索引,
而函数cv2.rectangle()指定顶点的参数所使用的形式为(列号,行号),可通过切片来实现行列互换
1 import numpy as np 2 loc = ([3,4,5,2] , [34,45,67,56]) 3 print(loc) 4 print(loc[::-1])
([3, 4, 5, 2], [34, 45, 67, 56])
([34, 45, 67, 56], [3, 4, 5, 2])
多模板匹配
1 import cv2 2 import numpy as np 3 from matplotlib import pyplot as plt 4 img = cv2.imread("/home/miao/Figure.png" , 0) 5 template = cv2.imread("/home/miao/dog_ex.png" , 0) 6 w , h = template.shape[::-1] 7 res = cv2.matchTemplate(img , template , cv2.TM_CCOEFF_NORMED) 8 threshold = 0.45 9 loc = np.where( res >= threshold) 10 for pt in zip(*loc[::-1]): 11 cv2.rectangle(img , pt , (pt[0] + w , pt[1] + h) , 255 , 1) 12 plt.imshow(img , cmap = ‘gray‘) 13 plt.axis(‘off‘) 14 plt.show()
由于该模板图是手动截出来的,在处理过程中导致出现图像中右侧出现的矩形框,
出现的宽度远远大于一是因为存在多个指定阈值0.45的情况,所以都做了标记
------------恢复内容结束------------
以上是关于opencv学习记录之模板匹配的主要内容,如果未能解决你的问题,请参考以下文章