OpenCV基础教学(二十一):模板匹配技术详解
模板匹配是计算机视觉中一种重要的目标检测方法,它通过在较大图像中搜索特定模板图像的位置来识别目标。本文将详细讲解模板匹配的基本原理与实现方法。
总流程图:

一、什么是模板匹配?
1.1 模板匹配的概念
模板匹配是一种在较大图像(源图像)中查找与给定模板图像(小图像)最相似区域的技术。简单来说,就是将模板图像在源图像上滑动,计算每个位置的相似度,找到最佳匹配位置。
1.2 模板匹配的应用场景
- 目标检测:在图像中检测特定物体
- 图像配准:对齐两幅相似的图像
- 质量检测:检查产品是否与标准模板一致
- 特征提取:在图像中定位特定特征
二、模板匹配详细步骤

python
# 导入Opencv库
import cv2
import numpy as np
# 1. 读取图片
image_np = cv2.imread('./picture.png')
template = cv2.imread('./muban.png')
# 2. 对读取到的模板图及原图像进行灰度化
image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# 获取模板图的宽和高,方便后面进行绘图
h, w = template_gray.shape[:2]
# 3. 进行模板匹配的操作
res = cv2.matchTemplate(image_np_gray, template_gray, cv2.TM_CCOEFF_NORMED)
print(res)
# 4. 对返回的结果做进一步处理
threshold = 0.57
# 对某数组的数据进行判断,如果满足条件,就返回其对应的坐标
# 这里要注意的是,他返回的是行和列的坐标。
# 对应到Opencv里,就是某一个点的y和x的坐标
location = np.where(res > threshold)
# print(location)
# print(location[::-1])
# for i in zip(*location[::-1]):
# print(i)
# 5. 对得到的点的坐标进行翻转处理,并再原图中框出来
for left_top in zip(*location[::-1]):
right_bottom = (left_top[0] + w, left_top[1] + h)
cv2.rectangle(image_np, left_top, right_bottom, (0, 0, 255))
# # 6. 显示模板匹配的结果
cv2.imshow('image_np', image_np)
cv2.waitKey(0)
2.1 读取图像和模板
python
# 导入OpenCV库
import cv2
import numpy as np
# 1. 读取图片
image_np = cv2.imread('./picture.png') # 源图像
template = cv2.imread('./muban.png') # 模板图像
2.2 灰度化处理
为了提高匹配速度,通常将图像转换为灰度图像:
python
# 2. 对读取到的模板图及原图像进行灰度化
image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# 获取模板图的宽和高,方便后面进行绘图
h, w = template_gray.shape[:2]
print(f"模板图像尺寸: 宽度={w}, 高度={h}")
2.3 进行模板匹配
使用matchTemplate()函数进行模板匹配:
python
# 3. 进行模板匹配的操作
res = cv2.matchTemplate(image_np_gray, template_gray, cv2.TM_CCOEFF_NORMED)
print("匹配结果矩阵形状:", res.shape)
2.4 设置阈值并提取匹配位置
python
# 4. 对返回的结果做进一步处理
threshold = 0.57
# 对某数组的数据进行判断,如果满足条件,就返回其对应的坐标
# 这里要注意的是,他返回的是行和列的坐标。
# 对应到OpenCV里,就是某一个点的y和x的坐标
location = np.where(res >= threshold)
# 打印匹配位置的数量
print(f"找到 {len(location[0])} 个匹配位置")
2.5 绘制匹配结果
python
# 5. 对得到的点的坐标进行翻转处理,并在原图中框出来
# 注意:location返回的是(y, x)坐标,需要转换为(x, y)
for left_top in zip(*location[::-1]):
right_bottom = (left_top[0] + w, left_top[1] + h)
cv2.rectangle(image_np, left_top, right_bottom, (0, 0, 255), 2)
# 6. 显示模板匹配的结果
cv2.imshow('image_np', image_np)
cv2.waitKey(0)
cv2.destroyAllWindows()
三、关键函数详解
3.1 cv2.matchTemplate()
python
cv2.matchTemplate(image, templ, method[, result])
功能:在源图像中搜索模板图像
参数说明:
image:源图像(搜索图像),必须是8位或32位浮点型templ:模板图像,不能大于源图像,且类型必须相同method:匹配方法,指定如何计算匹配度result:可选的输出结果图像
返回值:
- 一个二维数组,表示每个位置的匹配度分数
3.2 匹配方法详解
OpenCV提供了6种匹配方法:
| 方法 | 公式 | 特点 |
|---|---|---|
TM_SQDIFF |
R(x,y) = Σ[T(x',y') - I(x+x',y+y')]² | 平方差匹配,数值越小匹配越好 |
TM_SQDIFF_NORMED |
R(x,y) = Σ[T(x',y') - I(x+x',y+y')]² / √(ΣT² × ΣI²) | 归一化平方差匹配 |
TM_CCORR |
R(x,y) = Σ[T(x',y') × I(x+x',y+y')] | 相关匹配,数值越大匹配越好 |
TM_CCORR_NORMED |
R(x,y) = Σ[T(x',y') × I(x+x',y+y')] / √(ΣT² × ΣI²) | 归一化相关匹配 |
TM_CCOEFF |
R(x,y) = Σ[T'(x',y') × I'(x+x',y+y')] | 相关系数匹配 |
TM_CCOEFF_NORMED |
R(x,y) = Σ[T'(x',y') × I'(x+x',y+y')] / √(ΣT'² × ΣI'²) | 归一化相关系数匹配 |
常用方法:
TM_CCOEFF_NORMED:归一化相关系数匹配,最常用TM_CCORR_NORMED:归一化相关匹配TM_SQDIFF_NORMED:归一化平方差匹配
3.3 np.where()
python
np.where(condition)
功能:返回满足条件的数组元素的坐标
参数说明:
condition:条件表达式
返回值:
- 满足条件的元素的坐标元组(行索引,列索引)
注意:
- 返回的坐标是(y, x)格式
- 需要使用
[::-1]翻转得到(x, y)格式
四、总结
模板匹配是一种简单而有效的目标检测技术,通过在源图像中滑动模板并计算相似度来找到目标位置。
主要知识点总结:
- 基本原理:将模板图像在源图像上滑动,计算每个位置的相似度
- 关键函数 :
cv2.matchTemplate()和cv2.minMaxLoc() - 匹配方法:6种不同的匹配方法及其特点
- 多目标检测:通过阈值设置检测多个目标实例
- 局限性:对尺度、旋转和光照变化敏感
实际应用建议:
- 选择合适的匹配方法 :
TM_CCOEFF_NORMED是最常用的方法 - 设置合理的阈值:根据实际需求调整阈值大小
- 预处理图像:使用灰度化、直方图均衡化等预处理技术
- 考虑改进方法:对于尺度或旋转变化,使用多尺度或旋转不变匹配
模板匹配虽然简单,但在特定条件下(目标尺寸、方向、光照变化不大)仍然非常有效。对于更复杂的情况,可以考虑使用特征匹配或深度学习的方法。
下一篇预告:我们将学习霍夫变换技术,这是一种用于检测图像中直线、圆等几何形状的重要方法。敬请期待!