cv2.matchTemplate(img,template,cv2.TM_SQDIFF)
参数一:原图图像对象名称
参数二:模板图像对象名称
参数三:差别程度的计算方法(六选一推荐使用带归一化的)
模板匹配和卷积原理很像,模板从原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv中有六种,然后将每次计算的结果放入一个矩阵里,作为结果输出。
假如原图像是A×B的大小,而模板是a×b的大小,则输出结果的矩阵是(A-a+1)×(B-b+1)
import cv2
import numpy as np
from matplotlib import pyplot as pltdef show_photo(name,picture):#图像显示函数cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/A.jpg',0)
template = cv2.imread('E:\Jupyter_workspace\study\data/Aa.jpg',0)
h, w =template.shape[:2]img.shape#结果为:(300,300) (h,w)template.shape#结果为:(100,100) (h,w)res = cv2.matchTemplate(img,template,cv2.TM_SQDIFF)
res.shape#结果为:(201, 201)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
min_val#结果为:-16.0
max_val#结果为:88739848.0
min_loc#结果为:(99, 60)
max_loc#结果为:(61, 0)
差别程度方法名称 | 效果 |
---|---|
TM_SQDIFF | 计算平方不同,计算出来的值越小,越相关 |
TM_CCORR | 计算相关性,计算出来的值越大,越相关 |
TM_CCOEFF | 计算相关系数,计算出来的值越大,越相关 |
TM_SQDIFF_NORMED | 计算归一化平方不同,计算出来的值越接近0,越相关 |
TM_CCORR_NORMED | 计算归一化相关性,计算出来的值越接近1,越相关 |
TM_CCOEFF_NORMED | 计算归一化相关系数,计算出来的值越接近1,越相关 |
尽量用后三个归一化操作效果更好
六种具体差别程度公式参考手册
import cv2
import numpy as np
from matplotlib import pyplot as pltdef show_photo(name,picture):#图像显示函数cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/A.jpg',0)
template = cv2.imread('E:\Jupyter_workspace\study\data/Aa.jpg',0)
show_photo('img',img)#原图
show_photo('template',template)#匹配模板,需要从原图中找到与之相对应
h, w =template.shape[:2]methods = ['cv2.TM_CCOEFF','cv2.TM_CCOEFF_NORMED','cv2.TM_CCORR','cv2.TM_CCORR_NORMED','cv2.TM_SQDIFF','cv2.TM_SQDIFF_NORMED']
res = cv2.matchTemplate(img,template,cv2.TM_SQDIFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)for meth in methods:img2 = img.copy()#匹配方法的真假值method = eval(meth)print(method)res = cv2.matchTemplate(img, template, method)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)#如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:top_left = min_locelse:top_left = max_locbottom_right = (top_left[0] + w, top_left[1]+ h)#画矩阵cv2.rectangle(img2, top_left, bottom_right, 255, 2)plt.subplot(121), plt.imshow(res,cmap='gray')plt.xticks([]), plt.yticks([])#隐藏坐标轴plt.subplot(122), plt.imshow(img2,cmap='gray')plt.xticks([]), plt.yticks([])plt.suptitle(meth)plt.show()
原图:
模板:
匹配多个对象
上面的模板匹配原图中只有一个模板的存在
下面进行匹配原图中存在多个模板,进行多个对象的匹配
import cv2
import numpy as np
from matplotlib import pyplot as pltdef show_photo(name,picture):#图像显示函数cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img_rgb = cv2.imread('E:\Jupyter_workspace\study\data/mario.jpg')#原图
show_photo('img_rgb',img_rgb)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('E:\Jupyter_workspace\study\data/mario_1.jpg',0)#模板,0为灰度图,1为原色
show_photo('template',template)
h, w = template.shape[:2]#template.shape为[h,w,c]这里只用h和w即可,c为颜色通道,彩色为3(BGR),灰度图不显示res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8#取匹配程度大于80%的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):#*表示可选参数bottom_right = (pt[0] + w, pt[1] + h)cv2.rectangle(img_rgb, pt, bottom_right, (0,0,255), 2)show_photo('img_rgb',img_rgb)
原图:
模板:
匹配多个对象: