OpenCV模版匹配中有6种方法,我们今天就来分别看下不同方法的效果。
核心函数:cv2.matchTemplate()
result = cv2.matchTemplate(image, templ, method, mask=None)
image:源图像(8位灰度或彩色)。
templ:模板图像,大小不能超过源图像。
method:匹配方法,决定了相似度如何计算。常用以下6种:
| 方法标识符 (OpenCV) | 公式逻辑 | 最佳值是 |
|---|---|---|
cv2.TM_SQDIFF | 平方差 | 最小值 |
cv2.TM_SQDIFF_NORMED | 归一化平方差 | 最小值(越接近0越好) |
cv2.TM_CCORR | 相关性 | 最大值 |
cv2.TM_CCORR_NORMED | 归一化相关性 | 最大值(越接近1越好) |
cv2.TM_CCOEFF | 相关系数 | 最大值 |
cv2.TM_CCOEFF_NORMED | 归一化相关系数 | 最大值(越接近1越好) |
归一化方法(后缀 _NORMED)对光照变化更鲁棒,推荐优先使用。对于 _SQDIFF 系列,完全匹配时理论值为 0,因此要找最小值;其余方法找最大值。
我们就用实例代码来看看效果。
#6种匹配方式的对比import cv2import matplotlib.pyplot as plt
img = cv2.imread('./images/lina.png', 0) #0表示灰度图template = cv2.imread('./images/linat.png', 0)
#定义6种方法列表methods = ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']# w,h = template.shape[:2]w,h = template.shape[1], template.shape[0]print(w,h)for method in methods: img2 = img.copy() #匹配 res =cv2.matchTemplate(img, template, eval(method)) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) if method in ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']: # 选择最小值 top_left = min_loc else: # 选择最大值 top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) cv2.rectangle(img2, top_left, bottom_right, (255, 0, 0), 2) #画子图,画在一起 plt.subplot(121) plt.imshow(res, cmap='gray') plt.axis('off') plt.subplot(122) plt.imshow(img2, cmap='gray') plt.axis('off') plt.suptitle(f'{method} - Result') plt.show()实例效果图如下:

上面这些图中,img的图片如下:

模版图片如下:

6种方法中,有5种方法基本都可以正确匹配找到模版图片,只有cv2.TM_CCORR方法产生了偏差。

夜雨聆风