Opencv模板匹配
模板匹配
1.介绍
模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别成都,这个差别程度的计算方法在opencv中有6种,然后将每次计算的结果放在一个矩阵里,作为输出结果。接入原图形式A x B大小,而模板式a x b大小,则输出结果的矩阵式(A-a+1) x (B-b+1)
2.函数原型:
result = cv2.matchTemplate(image, template, method, mask=None)
3.参数说明
- image:输入的源图像(通常为灰度图),尺寸必须大于模板图像
- template:用于匹配的模板图像(通常为灰度图)
- method:匹配方法,指定计算相似度的算法
- mask:可选参数,模板的掩码,仅在特定匹配方法中使用
4. method类型
TM_SQDIFF:计算平方不同,计算出来的值越小越相关
TM_CCORR:计算相关性,计算出来的值越大越相关
TM_CCEFF:计算相关系数,计算出来的值越大越相关
TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近于0,越相关
TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近于1,越相关
TM_SQDIFF_NORMED:计算归一化相关系数,计算出来的值越接近于1,越相关
其中,归一化的方法(带 NORMED 后缀)通常更推荐使用,因为它们对亮度变化不敏感。
5.返回值
result
是一个单通道的灰度图,其中每个像素值表示对应位置的匹配程度,其尺寸为:
- 宽度:
image.shape[1] - template.shape[1] + 1
- 高度:
image.shape[0] - template.shape[0] + 1
import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取图像(灰度模式)
img = cv2.imread(r'C:\learn\MarkDown\anconda\lena.png', 0)
template = cv2.imread(r'C:\learn\MarkDown\anconda\template.png', 0)# 获取模板尺寸,将前两个值赋值给h和w
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']for meth in methods:# 拷贝图像img2 = img.copy()# 匹配方法的真值 method = eval(meth) 这行代码的作用是将字符串形式的变量名转换为实际的变量(或常量)method = eval(meth)# 进行模板匹配res = cv2.matchTemplate(img, template, method)# 找到最佳匹配位置min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)# 如果式平方差匹配TM_SQDIFF或归一化TM_SQDIFF_NORMED,取小值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(img, 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()
6.多模板匹配
import cv2
import numpy as np# 读取彩色图像
img_rgb = cv2.imread(r'C:\learn\MarkDown\anconda\templatemulExample.png')
# 转换为灰度图,用于模板匹配
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)# 读取模板图像(灰度模式)
template = cv2.imread(r'C:\learn\MarkDown\anconda\templateMulti.png', 0)
# 获取模板的高度和宽度
h, w = template.shape[:2]# 执行模板匹配(使用归一化相关系数方法)
# 注意:正确的常量是TM_CCOEFF_NORMED(包含两个C)
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)# 设置匹配阈值(只保留匹配度大于0.8的区域)
threshold = 0.8 # 修正变量名拼写错误# 找到所有匹配值大于阈值的位置
# np.where返回的是(y, x)形式的坐标,需要转换为(x, y)
loc = np.where(res >= threshold)# 遍历所有匹配位置并绘制矩形
for pt in zip(*loc[::-1]): # loc[::-1]将(y, x)转换为(x, y)# 计算矩形右下角坐标bottom_right = (pt[0] + w, pt[1] + h)# 在彩色图像上绘制红色矩形(BGR格式,(0,0,255)表示红色)cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)# 显示结果图像
cv2.imshow('Matching Results', img_rgb)
# 等待用户按键(注意:正确的函数名是waitKey,K大写)
cv2.waitKey(0)
# 关闭所有窗口
cv2.destroyAllWindows()