You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CV入门:模板匹配中如何消除重复的位置检测点?

解决模板匹配中重复位置检测点的问题

嘿,看来你已经在模板匹配的路上走了一段了!要消除重复的检测点,**非极大值抑制(Non-Maximum Suppression, NMS)**是最常用的方案,它能帮你保留最匹配的结果,去掉那些重叠度太高的重复检测框。

我结合你的代码,给你完整的解决方案:

第一步:补全模板匹配的基础流程

先把模板匹配的核心步骤补全,拿到所有可能的匹配位置和对应得分:

import numpy as np
import cv2

# 读取主图像和模板(直接把模板读成灰度图,省一步转换)
inputImage = cv2.imread('Trolley_problem.jpg')
inputImageGray = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
humanTemplate = cv2.imread('h1.jpg', 0)
templateH, templateW = humanTemplate.shape[:2]

# 执行归一化模板匹配,得到匹配得分矩阵
result = cv2.matchTemplate(inputImageGray, humanTemplate, cv2.TM_CCOEFF_NORMED)

第二步:筛选候选检测框

设定一个匹配得分阈值(比如0.8,可根据实际效果调整),把得分高于阈值的位置都提取出来作为候选:

threshold = 0.8
# 提取所有得分达标位置的坐标,转换成(x,y)格式并带上对应得分
locations = np.where(result >= threshold)
candidates = []
for (x, y) in zip(*locations[::-1]):
    # 每个候选框存储为(x1, y1, x2, y2, 匹配得分)
    candidates.append((x, y, x + templateW, y + templateH, result[y, x]))

第三步:实现非极大值抑制去重

NMS的核心逻辑是:先按匹配得分从高到低排序,保留得分最高的框,再去掉和它重叠度(IoU)超过阈值的重复框。咱们自己写一个简单的NMS函数:

def non_max_suppression(boxes, overlap_threshold):
    if len(boxes) == 0:
        return []
    
    # 把候选框转换成numpy数组,方便计算
    boxes = np.array(boxes)
    x1, y1, x2, y2, scores = boxes[:,0], boxes[:,1], boxes[:,2], boxes[:,3], boxes[:,4]
    
    # 计算每个框的面积,按得分降序排序
    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    order = scores.argsort()[::-1]
    
    keep = []
    while order.size > 0:
        # 保留当前得分最高的框
        i = order[0]
        keep.append(boxes[i])
        
        # 计算当前框与剩余框的重叠区域坐标
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])
        
        # 计算重叠区域的宽高和IoU(交并比)
        w = np.maximum(0, xx2 - xx1 + 1)
        h = np.maximum(0, yy2 - yy1 + 1)
        overlap = (w * h) / areas[order[1:]]
        
        # 只保留重叠度低于阈值的框
        indices = np.where(overlap <= overlap_threshold)[0]
        order = order[indices + 1]
    
    return keep

第四步:应用NMS并绘制最终结果

把候选框传入NMS函数得到去重后的结果,再绘制到原图上:

# 应用非极大值抑制,重叠阈值设为0.3(可根据对象间距调整)
filtered_boxes = non_max_suppression(candidates, overlap_threshold=0.3)

# 绘制去重后的检测框和得分
for box in filtered_boxes:
    x1, y1, x2, y2, score = box
    cv2.rectangle(inputImage, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
    cv2.putText(inputImage, f"{score:.2f}", (int(x1), int(y1)-5), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

# 展示结果
cv2.imshow("Detected Objects", inputImage)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键参数说明

  • threshold:匹配得分阈值,值越高筛选越严格,只有得分达标才会被视为候选。
  • overlap_threshold:NMS重叠阈值,IoU超过这个值的框会被判定为重复,一般在0.2-0.5之间调整。

这样处理后,就不会再出现一堆重复的检测点啦,只会保留最匹配、最具代表性的检测框。

内容的提问来源于stack exchange,提问作者Rao208

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:37:16