模板匹配是指在当前图像A内寻找图像B最相似的部分,一般将图像A称为输入图像,将图像B称为模板图像,模板匹配的操作方法是将模板图像B在图像A上滑动,遍历所有像素点以完成匹配
一:模板匹配基础
dst=cv2.matchTemplate(image,templ,method,mask=None)
image:原始图像,必须为8位或者32位的浮点型图像
templ:模板图像,它的尺寸必须小于或者等于原始图像,并且与原始图像具有相同的类型
method:匹配方法。该参数通过TemplateMatchModes实现,有一下6种可能的值。具体含义自行查表
1:cv2.TM_SQDIFF ,值越小,匹配越好
2:cv2.TM_SQDIFF_NORMED,,值越小,匹配越好
3:cv2.TM_CCORR,值越大,匹配越好
4:cv2.TM_CCORR_NORMED,值越大,匹配越好
5:cv2.TM_CCOEFF,值越大,匹配越好
6:cv2.TM_CCOEFF_NORMED,值越大,匹配越好
mask:图像掩膜,必须与模板图像teml具有相同的类型和大小,通常默认即可。
dst:由模板图像遍历原始图像的过程中,两者相互比较的结果所构成的一个集合,类型是单通道32位浮点数。如原始图像尺寸W*H,模板图像w*h,则dst的大小为(W-w+1)*(H-h+1)。
在查找最佳匹配位置时,要注意匹配方式method的选取,method不同,最终选择最佳匹配位置的方式不同。
在查找最值(极值)与最值所在位置时,可以使用cv2.minMaxLoc()函数实现。同时,可以借助函数cv2.rectangle()将该位置标记出来。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread("img/5.jpg",0)
template=cv2.imread("img/15.png",0)
h,w=template.shape[::]
#注意method的类型
dst=cv2.matchTemplate(img,templ=template,method=cv2.TM_SQDIFF)
minVal,maxVal,minLoc,maxLoc=cv2.minMaxLoc(dst)
topLeft=minLoc
#注:先横坐标再纵坐标
bottomRight=(topLeft[0]+w,topLeft[1]+h)
cv2.rectangle(img,topLeft,bottomRight,(0,255,0),2)
plt.subplot(131)
plt.imshow(dst,cmap="gray")
plt.axis("off")
plt.title("matching result")
plt.subplot(132)
plt.imshow(template,cmap="gray")
plt.axis("off")
plt.title("Template")
plt.subplot(133)
plt.imshow(img,cmap="gray")
plt.axis("off")
plt.title("detected point")
plt.show()
一:多模板匹配
函数cv2.minMaxLoc()仅仅能够找出最大值(最小值)及其位置,无法给出所有匹配区域的位置信息,若搜索的模板图像在原始图像中出现了多次,想要匹配多个结果,则需要利用阈值进行处理。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread("img/17.png",0)
template=cv2.imread("img/20.png",0)
w,h=template.shape[::-1]
dst=cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
#设置阈值,阈值的设置与索引的选取和模板匹配方式method有关
thresh=0.95
#返回两个数组,分别为行列索引
loc=np.where(dst>=thresh)
#cv2.rectangle在指定顶点时,先列后行,需要对loc行列位置进行调换。
for pt in zip(*loc[::-1]):
cv2.rectangle(img,pt,(pt[0]+w,pt[1]+h),(0,255,255),1)
plt.subplot(1,2,1)
plt.imshow(dst,"gray")
plt.axis("off")
plt.title("matching result")
plt.subplot(1,2,2)
plt.imshow(img,cmap="gray")
plt.axis("off")
plt.title("detected point")
plt.show()