OpenCV 从零学习 · 第 12 讲:模板匹配
函数:cv2.matchTemplate / cv2.minMaxLoc | 难度:★★☆☆☆
模板匹配是最简单的目标定位方法:给你一张大图、一张小图(模板),它在每个位置滑一遍,算出"这块区域和小图有多像",最后找到最像的位置并画框。适合目标外观固定、不会大幅缩放旋转的场景。
一、matchTemplate
result = cv2.matchTemplate(image, templ, method)
| 参数 | 含义 |
image | 大图(搜索图) |
templ | 小图(模板),必须比 image 小 |
method | 匹配算法(见下表) |
返回的是一张结果图,尺寸为 (W-w+1, H-h+1)(W/H 是大图宽高,w/h 是模板宽高)。每个像素值代表"以该点左上角为起点时,与大图的相似度"。
| method | 含义 | 最佳值 |
TM_SQDIFF / _NORMED | 平方差,越小越像 | 最小值 |
TM_CCORR / _NORMED | 相关性,越大越像 | 最大值 |
TM_CCOEFF / _NORMED | 相关系数(去均值),最稳 | 最大值 |
实际工程几乎都用 TM_CCOEFF_NORMED(归一化相关系数):不受亮度整体偏移影响,结果落在 -1~1,越接近 1 越像。
二、取出最佳位置 minMaxLoc
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
top_left = max_loc # 不同 method 取 max 还是 min!
if method in (cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED):
top_left = min_loc
w, h = templ.shape[1], templ.shape[0]
cv2.rectangle(image, top_left, (top_left[0]+w, top_left[1]+h), (0,255,0), 2)
场景 A · 在大图里找 logo / 图标
截一张 app 界面图,把要找的按钮小图当模板,
截一张 app 界面图,把要找的按钮小图当模板,
matchTemplate 后框出位置——这正是图色脚本"找图"的 OpenCV 正经做法(比大漠更通用、可跨分辨率做归一化)。
场景 B · 多目标匹配
一张图里有多处相同的图标:不用 minMaxLoc(只给一个点),而是遍历 result,凡是
一张图里有多处相同的图标:不用 minMaxLoc(只给一个点),而是遍历 result,凡是
val > 0.8 的位置都画框,并做非极大值抑制(距离过近的合并)避免重复框。
⚠ 新手必踩坑
- 模板必须比大图小,否则报尺寸错误。
- 用
TM_SQDIFF系列时最佳是最小值/top_left=min_loc;其它 method 是最大值/top_left=max_loc。选错会框到完全不相关的地方。 - 模板匹配的致命弱点:目标旋转、缩放、形变就失效。要解决尺度问题,见下一讲图像金字塔做多尺度匹配。
本讲要点
matchTemplate返回结果图,尺寸比原图小一圈(W-w+1, H-h+1)。- 首选
TM_CCOEFF_NORMED;SQDIFF 取 min,其余取 max。 - 只适合目标外观固定;旋转/缩放场景需配合金字塔或改用特征点(第 14 讲)。
下一讲:第 13 讲 · 图像金字塔(pyrDown / pyrUp)——用"缩放"让模板匹配应对不同大小的目标,也为后续特征提取打基础。
