第十五章: 模板匹配

模板匹配就是在给定的图片中查找和模板最相似的区域。 实现的方法是:将模板在图片上滑动(从左向右,从上向下),遍历所有滑窗,计算匹配度,将所有计算结果保存在一个矩阵种,并将矩阵中匹配度最高的值作为匹配结果。

一、单模板匹配

1、匹配函数:result = cv2.matchTemplate(img, temp, method[, mask]) img:要进行匹配的图像,必须是8位或者32位的浮点型图像 tem:模板图像,尺寸要要小于原图,数据类型要和原图一样。 method:匹配方法,也就是相似度计算方法,opencv提供了6种计算方法(主要是下面三种,另外三种是下面三种方式的归一化结果):     平方差匹配cv2.TM_SQDIFF:以方差为依据进行匹配。如果完全匹配,匹配值为0,匹配值越大,越不匹配。     相关匹配cv2.TM_CCORR:将模板图像和输入图像相乘,如果匹配值越大,表示匹配程度越高,如果乘积等于0,则表示完全不匹配。     相关系数匹配cv2.TM_CCOEFF:将模板图像与其均值的相对值,和输入图像与其均值的相对值,进行匹配。1表示完美匹配,-1表示糟糕匹配,0表示没有任何相关性,是随机序列。 函数返回值result是一个矩阵,大小是(W-w+1, H-h+1),其中W,H是原图的宽高,w,h是模板的宽高。矩阵里面的每个元素表示的是宽高和模型一样大小的矩形的顶点。 2、查找最佳匹配的位置坐标:minval, maxval, minloc, maxloc = cv2.minMaxLoc(array[, mask]) 为什么要返回这么多对象,因为匹配函数cv2.matchTemplate()由于参数method设定的不同,其返回值值result中表示最佳匹配的结果不同,比如参数method=cv2.TM_SQDIFF,那我们想直到最佳匹配区域的坐标值就是return对象里面的最小值以及最小值对应的坐标值。如果method=cv2.TM_CCORR,或者cv2.TM_CCOEFF,那我们要找的最佳匹配区域就是return中的最大值及最大值对应的坐标值。 minval1、maxval1是array中的最值,minloc1、maxloc1是array中最值对应的坐标点,但是这个坐标点是(列,行)的形式!!! 3、用矩形框把最佳匹配区域框出来:img = cv2.rectangle(img, pt1, pt2, color, thickness) 说明:pt1和pt2都是(列,行)的形式   #例15.1 使用cv2.matchTemplate()函数的不同计算方法进行模板匹配

import cv2

import numpy as np

import matplotlib.pyplot as plt

img = cv2.imread(r'C:\Users\25584\Desktop\lena.bmp',0) #img.shape返回(512, 512)

template = cv2.imread(r'C:\Users\25584\Desktop\temp.bmp',0) #template.shape返回(40, 200)

result1 = cv2.matchTemplate(img, template, cv2.TM_SQDIFF) #result1.shape返回(473, 313)

result2 = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED) #如果是cv2.TM_CCORR匹配出来的效果非常差!为什么????

result3 = cv2.matchTemplate(img, template, cv2.TM_CCOEFF)

minval1, maxval1, minloc1, maxloc1 = cv2.minMaxLoc(result1) #minval1和result1.min()返回值一样

minval2, maxval2, minloc2, maxloc2 = cv2.minMaxLoc(result2)

minval3, maxval3, minloc3, maxloc3 = cv2.minMaxLoc(result3)

img1 = img.copy()

img1 = cv2.rectangle(img1, minloc1, (minloc1[0]+200, minloc1[1]+40), 255, 2)

img2 = img.copy()

img2 = cv2.rectangle(img2, maxloc2, (maxloc2[0]+200, maxloc2[1]+40), 255, 2)

img3 = img.copy()

img3 = cv2.rectangle(img3, maxloc3, (maxloc3[0]+200, maxloc3[1]+40), 255, 2)

#可视化:

plt.figure(figsize=(16,6))

plt.subplot(161), plt.imshow(img, cmap='gray') #原图

plt.subplot(162), plt.imshow(template, cmap='gray') #模板

plt.subplot(163), plt.imshow(result1, cmap='gray') #匹配的返回值

plt.subplot(164), plt.imshow(img1, cmap='gray') #

plt.subplot(165), plt.imshow(img2, cmap='gray') #

plt.subplot(166), plt.imshow(img3, cmap='gray') #

plt.show() 说明:模板匹配不适用尺度变换、视角变换后的图像!!! 如果非要匹配,我们就要使用关键点匹配算法,比较经典的关键点检测算法包括SIFT和SURF等,主要思路是先通过关键点检测算法获取模板和检测图像中的关键点,然后使用关键点匹配算法处理。因为这些关键点可以很好的处理尺度变换、视角变换、旋转变化、光照变化等,具有很好的不变性。 二、多模板匹配 当要匹配的图像中有多个模板图像时,就是模板图像在原图中出现多次时,这时就要找出多个匹配结果。 1、匹配函数:result = cv2.matchTemplate(img, temp, method[, mask])的返回对象result里面就会有多个符合条件的点2、找出result中的多个符合条件的点:因为result是一个二维array,在二维array中值大于阈值0.99(因为我们这里假设匹配方法是cv2.TM_CCOEFF_NORMED,是相关系数匹配),所以要用:loc = np.where(result>=0.99),这样就把result里面大于0.99的值的横纵坐标找出来了。loc返回值是一个元组,元组的第一个元素是一个array,这个array是索引出来的所有符合条件的点的横坐标索引,元组的第二个元素是所有符合条件的点的列索引。3、用for循环画图。循环的时候是循环zip(*loc),这样循环的时候就是把loc中的每个元素对应位置进行遍历。 但是这里要注意的是画图的时候是(列,行)索引来画的,但是循环的时候循环的是最值的(行,列)坐标,所以画图的时候要行列翻转一下。 #例15.2 练习多模板匹配

import cv2

import numpy as np

import matplotlib.pyplot as plt

img = cv2.imread(r'C:\Users\25584\Desktop\lena4.bmp',0) #img.shape返回(540, 700)

template = cv2.imread(r'C:\Users\25584\Desktop\lena4Temp.bmp',0) #template.shape返回(51, 103)

result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED) #result.shape返回(490, 598)

plt.figure(figsize=(16,8))

plt.subplot(131), plt.imshow(img, cmap='gray') #原图

plt.subplot(132), plt.imshow(template, cmap='gray') #模板

plt.subplot(133), plt.imshow(result, cmap='gray') #匹配的返回值

loc = np.where(result >= 0.99)

img1 = img.copy()

for pt in zip(*loc):

cv2.rectangle(img1, pt[::-1], (pt[::-1][0]+103, pt[::-1][1]+51), 255,1)

#可视化:

plt.figure(figsize=(16,8))

plt.imshow(img1, cmap='gray') #

plt.show()

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。