Opencv 学习笔记:多模板匹配(多目标定位 + 重复框过滤)

多模板匹配是单模板匹配的扩展,可在图像中定位多个相同模板目标,核心解决 "单目标匹配→多目标筛选→重复框过滤" 问题。本文修复原代码核心问题,演示完整的多模板匹配实现,新手可直接复用。

核心代码实现

python 复制代码
import cv2 as cv
import numpy as np

# 1. 读取模板和待匹配图像(增加空值校验)
tpl = cv.imread('.\image\19.bmp')  # 模板图像
target = cv.imread('.\image\20.bmp')  # 待匹配图像
if tpl is None or target is None:
    print('图像读取失败,请检查路径!')
    exit()

# 显示模板和待匹配图像
cv.namedWindow('tpl', cv.WINDOW_NORMAL)
cv.resizeWindow('tpl', 600, 600)
cv.imshow('tpl', tpl)
cv.imshow('target', target)

# 2. 定义匹配算法(优先归一化相关系数,鲁棒性最强)
TM_SQDIFF = cv.TM_SQDIFF          # 平方差:0最好
TM_SQDIFF_NORMED = cv.TM_SQDIFF_NORMED
TM_CCORR = cv.TM_CCORR            # 相关性:1最好
TM_CCORR_NORMED = cv.TM_CCORR_NORMED
TM_CCOEFF = cv.TM_CCOEFF          # 相关系数:1最好
TM_CCOEFF_NORMED = cv.TM_CCOEFF_NORMED  # 推荐使用

# 3. 执行多模板匹配(关键:待匹配图在前,模板在后!)
result = cv.matchTemplate(target, tpl, TM_CCOEFF_NORMED)
# 归一化匹配结果,统一数值范围[0,1]
cv.normalize(result, result, 0, 1, cv.NORM_MINMAX, -1)

# 4. 筛选高匹配度位置(阈值0.8,可根据实际场景调整)
threshold = 0.8
# 获取所有匹配度≥阈值的坐标(np.where返回(行,列),需反转为(列,行))
locs = np.where(result >= threshold)
# 转换坐标格式:(x,y)
match_locs = list(zip(*locs[::-1]))

# 5. 重复框过滤(避免相邻重复标注)
filtered_locs = []
temp_loc = None
tpl_h, tpl_w = tpl.shape[:2]  # 模板的宽高(匹配框尺寸)
gap_threshold = 110  # 重复框判定阈值(像素)

for loc in match_locs:
    # 首次匹配或当前框与上一个框间距≥阈值,保留
    if temp_loc is None or (abs(loc[0] - temp_loc[0]) > gap_threshold) or (abs(loc[1] - temp_loc[1]) > gap_threshold):
        filtered_locs.append(loc)
        temp_loc = loc

# 6. 绘制所有匹配框(在待匹配图像上标注)
draw_img = target.copy()
for (x, y) in filtered_locs:
    # 匹配框右下角坐标:x+tpl_w, y+tpl_h
    cv.rectangle(draw_img, (x, y), (x + tpl_w, y + tpl_h), (0, 0, 255), 3)

# 7. 显示匹配结果
cv.namedWindow('img', cv.WINDOW_NORMAL)
cv.resizeWindow('img', 600, 600)
cv.imshow('img', draw_img)

cv.waitKeyEx(0)
cv.destroyAllWindows()

关键知识点解析

1. 多模板匹配核心流程

步骤 核心操作 作用说明
匹配计算 cv.matchTemplate(target, tpl, 算法) 生成全图匹配度矩阵
阈值筛选 np.where(result >= 0.8) 过滤低匹配度位置,只保留高置信度目标
坐标转换 zip(*locs[::-1]) 将 np.where 返回的 (行,列) 转为图像 (列,行) 坐标
重复过滤 间距判断abs(x1-x2) > 110 避免同一目标被多次标注
绘制标注 cv.rectangle() 可视化所有匹配目标

2. 核心避坑点

  • 参数顺序 :原代码matchTemplate(tpl, target)顺序颠倒,正确应为(待匹配图, 模板),否则匹配结果完全错误;
  • 匹配框尺寸 :框的宽高需取模板图像tpl_w/tpl_h,而非 target,原代码用 target 尺寸会导致框大小错误;
  • 重复过滤逻辑 :原代码temp_loc[0]+110 < loc[0]仅判断单方向,改为abs()绝对值判断,避免漏过滤;
  • 绘图载体 :在target.copy()上绘图,避免修改原始图像。

3. 优化技巧

  • 阈值调优:阈值 0.8 是经验值,目标清晰时可提高(如 0.9),目标模糊时可降低(如 0.7);
  • 批量模板:若需匹配多个不同模板,可循环加载模板并执行匹配,最后合并结果;
  • 效率提升:对大图像,可先缩放后匹配,再还原坐标,减少计算量;
  • 更优去重:复杂场景可改用非极大值抑制(NMS)算法,替代简单间距判断。

总结

  1. 多模板匹配核心是阈值筛选 + 重复框过滤,区别于单模板匹配的 "找极值";
  2. matchTemplate参数顺序必须是(待匹配图, 模板),匹配框尺寸取模板宽高;
  3. 重复框过滤需用绝对值间距判断,避免单方向判断导致漏过滤。
相关推荐
木风小助理6 小时前
未来JS架构:Realm隔离——从全局共享到独立环境的必然
学习
九成宫6 小时前
计算机网络期末复习——第5章:链路层 Part One
网络·笔记·计算机网络·软件工程
非凡ghost6 小时前
批量校正图像方向(校正PDF页面方向)
windows·学习·pdf·软件需求
科技林总6 小时前
【系统分析师】5.1 数据库管理系统
学习
o(╥﹏╥)6 小时前
Learn how Gen AI 学习笔记
人工智能·笔记·学习
xqqxqxxq6 小时前
《智能仿真无人机平台(多线程V1.0)技术笔记》(初识线程,带你理解程序运行的基本流程)
java·笔记
进阶小白猿6 小时前
Java技术八股学习Day23
java·网络·学习
臭东西的学习笔记6 小时前
论文学习——酶动力学参数预测的机器学习模型研究进展
人工智能·学习·机器学习
啊巴矲7 小时前
小白从零开始勇闯人工智能:计算机视觉初级篇(初识Opencv下)
人工智能·opencv·计算机视觉
落雨盛夏7 小时前
深度学习|李哥考研——(无)监督学习相关分类
深度学习·学习·分类