在当前图像A内寻找与图像B最相似的部分。A为输入图像,B为模板图像。

操作方法是将模板B在图像A滑动,遍历所有像素已完成匹配。

匹配函数

OpenCV中模板匹配的函数语法格式为:

result = cv2.matchTemplate(img, templ, method[, mask])
  • image为原始图像,必须是8位或者32位的浮点型图像
  • templ为模板图像,尺寸必须小于或等于原始图像,并且与原始图像具有相同的类型
  • method为匹配方法,有六种可能,如下表1所示
  • mask为掩模,必须和模板图像templ具有相同的类型和大小

method值以及含义

method的值具体对应的公式关系

返回值result是由每个位置的比较结果所构成的一个结果集,类型是单通道32位浮点型。如果输入图像的尺寸是W*H,模板的尺寸w*h,是则返回值的大小为(W-w+1)*(H-h+1)

遍历

在进行模板匹配时,模板在原始图像内遍历。

在水平方向上:

  • 遍历的起始坐标是原始图像左数第一个像素值(序号从1开始)
  • 最后一次比较是当模板图像位于原始图像的最右侧时,此时其左上角像素点所在的位置是W - w + 1

因此,返回值result在水平方向上的大小为W-w+1(水平方向的比较次数)。

在垂直方向上:

  • 遍历的起始坐标是原始图像顶端第一个像素值(序号从1开始)
  • 最后一次比较是当模板图像位于原始图像的最下侧时,此时其左上角像素点所在的位置是H - h + 1

因此,返回值result在水平方向上的大小为H-h+1(水平方向的比较次数)。

result值

需要注意的是,参数method来决定使用不同的查找方法。对于不同的查找方法,返回值的意义也不同

  • method的值为cv2.TM_SQDIFFcv2.TM_SQDIFF_NORMED时,result值为0表示匹配度最好,值越大,表示匹配度越差
  • method的值为cv2.TM_CCORRcv2.TM_CCORR_NORMEDcv2.TM_CCOEFFcv2.TM_CCOFF_NORMED时,result值为0表示匹配度最差,值越大,表示匹配度越好

因此,需要先确定method的值,然后再确定去查找最大值或者最小值。

查找最值及其所在的位置,可以使用cv2.minMaxLoc()函数实现。该函数语法格式如下:

minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(src[, mask])
  • src为单通道数组
  • minVal为返回的最小值,如果没有最小值,则可以是NULL
  • maxVal为返回的最大值,如果没有最大值,则可以是NULL
  • minLoc为最小值的位置,如果没有最小值,则可以是NULL
  • maxLoc为最大值的位置,如果没有最大值,则可以是NULL

现以cv2.TM_SQDIFFcv2.TM_SQDIFF_NORMED为例,0表示最佳匹配,值越大则匹配效果越差。

找到返回值中最小的位置:

minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(src[, mask])
topLeft = minLoc #如果值越小则匹配效果越差,越大越好,则topLeft = maxLoc

以topLeft点为模板匹配的左上角位置,结合模板的宽度w和高度h可以确定匹配位置的右下角坐标,代码如下:

bottomRight = (topLeft[0]+w, topLeft[1]+h)  #w和h是模板图像的宽度和高度

确定好左上角和右下角之后,可以绘制矩形:

cv2.rectangle(img, topLeft, bottomRight, 255, 2)

示例

例:使用函数cv2.matchTemplate()进行模板匹配,要求参数method的值设置为cv2.TM_SQDIFF,显示函数的返回结果及匹配结果。

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

img = cv2.imread(r'E:\Blog\OpenCV\baicai.png',0)
template = cv2.imread(r'E:\Blog\OpenCV\baicaieye.png',0)
th, tw = template.shape

rv = cv2.matchTemplate(img,template,cv2.TM_SQDIFF)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(rv)

topLeft = minLoc
bottomRight = (topLeft[0]+tw, topLeft[1]+th) 

cv2.rectangle(img, topLeft, bottomRight, 255, 2)
plt.subplot(121), plt.imshow(rv, cmap='gray')
plt.title('MatchResult'),plt.axis('off')
plt.subplot(122), plt.imshow(img, cmap='gray')
plt.title('Detected Point'),plt.axis('off')
plt.show()

运行结果


点击访问我的个人资源收藏网站~~



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

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