非极大值抑制(Non-Maximum Suppression,NMS)

本文介绍了非极大值抑制(NMS)在目标检测中的应用。阐述了NMS原理,即选择最大score检测框,移除与其IoU大于阈值的框。还提及NMS loss、Soft - NMS改进方法及代码实现,其在部分模型测试阶段能提升检测效果,此外还介绍了NMS在边缘和特征点检测中的应用。

概述

非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素,可以理解为局部最大搜索。这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二是邻域的大小。这里不讨论通用的NMS算法(参考论文《Efficient Non-Maximum Suppression》对1维和2维数据的NMS实现),而是用于目标检测中提取分数最高的窗口的。例如在行人检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到NMS来选取那些邻域里分数最高(是行人的概率最大),并且抑制那些分数低的窗口。NMS在计算机视觉领域有着非常重要的应用,如视频目标跟踪、数据挖掘、3D重建、目标识别以及纹理分析等。

NMS 在目标检测中的应用

人脸检测框重叠例子
在这里插入图片描述
我们的目的就是要去除冗余的检测框,保留最好的一个.
有多种方式可以解决这个问题,Triggs et al. 建议使用Mean-Shift 算法,利用bbox的坐标和当前图片尺度的对数来检测bbox的多种模式.但效果可能并不如使用强分类器结合NMS的效果好.

目标检测 pipline

在这里插入图片描述
产生proposal后使用分类网络给出每个框的每类置信度,使用回归网络修正位置,最终应用NMS.

NMS 原理

对于Bounding Box的列表B及其对应的置信度S,采用下面的计算方式.选择具有最大score的检测框M,将其从B集合中移除并加入到最终的检测结果D中.通常将B中剩余检测框中与M的IoU大于阈值Nt的框从B中移除(将同类的Bounding Box移除).重复这个过程,直到B为空.

重叠率(重叠区域面积比例IOU)阈值
常用的阈值是 0.3 ~ 0.5.
其中用到排序,可以按照右下角的坐标排序或者面积排序,也可以是通过SVM等分类器得到的得分或概率,R-CNN中就是按得分.
进行的排序
在这里插入图片描述
就像上面的图片一样,定位一个车辆,最后算法就找出了一堆的方框,我们需要判别哪些矩形框是没用的。非极大值抑制的方法是:先假设有6个矩形框,根据分类器的类别分类概率做排序,假设从小到大属于车辆的概率 分别为A、B、C、D、E、F。
(1)从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;

(2)假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。

(3)从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。

就这样一直重复,找到所有被保留下来的矩形框。

代码示例

在R-CNN中使用了NMS来确定最终的bbox,其对每个候选框送入分类器,根据分类器的类别分类概率做排序(论文中称为greedy-NMS).但其实也可以在分类之前运用简单版本的NMS来去除一些框.
python实现的单类别nms:py_cpu_nms.py.

def py_cpu_nms(dets, thresh): 
"""Pure Python NMS baseline.""" 
#x1、y1、x2、y2、以及score赋值
x1 = dets[:, 0] 
y1 = dets[:, 1] 
x2 = dets[:, 2] 
y2 = dets[:, 3] 
scores = dets[:, 4]
#每一个检测框的面积
 areas = (x2 - x1 + 1) * (y2 - y1 + 1) 
 #按照score置信度降序排序 
 order = scores.argsort()[::-1]
keep = [] 
#保留的结果框集合 
while order.size > 0: 
i = order[0] 
keep.append(i) 
#保留该类剩余box中得分最高的一个
#得到相交区域,左上及右下
  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:]])
#计算相交的面积,不重叠时面积为0
  w = np.maximum(0.0, xx2 - xx1 + 1)
  h = np.maximum(0.0, yy2 - yy1 + 1)
  inter = w * h
 #计算IoU:重叠面积 /(面积1+面积2-重叠面积) 
 ovr = inter / (areas[i] + areas[order[1:]] - inter) 
 #保留IoU小于阈值的
 box inds = np.where(ovr <= thresh)[0] 
 #因为ovr数组的长度比order数组少一个,所以这里要将所有下标后移一位
 order = order[inds + 1] 
  return keep

NMS loss

值的注意的是对多类别检测任务,如果对每类分别进行NMS,那么当检测结果中包含两个被分到不同类别的目标且其IoU较大时,会得到不可接受的结果。如下图所示:
在这里插入图片描述
参考论文《Rotated Region Based CNN for Ship Detection》(IEEE2017会议论文)的Multi-task for NMS部分。

Soft-NMS

上述NMS算法的一个主要问题是当两个ground truth的目标的确重叠度很高时,NMS会将具有较低置信度的框去掉(置信度改成0),参见下图所示.
在这里插入图片描述
论文:《Improving Object Detection With One Line of Code》
在这里插入图片描述
改进方法在于将置信度改为IoU的函数:f(IoU),具有较低的值而不至于从排序列表中删去.
1:线性函数
在这里插入图片描述
:函数值不连续,在某一点的值发生跳跃.
2:高斯函数
在这里插入图片描述
时间复杂度同传统的greedy-NMS,为O(N2).

soft-NMS python代码实现:

ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih) 
ov = iw * ih / ua 
#iou between max box and detection box 
if method == 1: 
# linear 
if ov > Nt: 
  weight = 1 - ov 
else:
  weight = 1
elif method == 2: # gaussian 
  weight = np.exp(-(ov * ov)/sigma)
   else: 
 # original NMS
 if ov > Nt:
      weight = 0 
 else: weight = 1 
 # re-scoring 
 修改置信度 boxes[pos, 4] = weight*boxes[pos, 4]

效果

在这里插入图片描述
在基于proposal方法的模型结果上应用比较好,检测效果提升:
在这里插入图片描述
在R-FCN以及Faster-RCNN模型中的测试阶段运用Soft-NMS,在MS-COCO数据集上mAP@[0.5:0.95]能够获得大约1%的提升. 如果应用到训练阶段的proposal选取过程理论上也能获得提升. 在自己的实验中发现确实对易重叠的目标类型有提高(目标不一定真的有像素上的重叠,切斜的目标的矩形边框会有较大的重叠).
而在SSD,YOLO等非proposal方法中没有提升.

其他应用

边缘检测:Canny算子中的非极大值抑制是沿着梯度方向进行的,即是否为梯度方向上的极值点;特征点检测:在角点检测等场景下说的非极大值抑制,则是检测中心点处的值是否是某一个邻域内的最大值.

<think>好的,我现在需要回答用户关于非极大值抑制NMS)算法在后处理中的具体应用和实现步骤的问题。用户特别提到了NMS的后处理、实现过程和作用,我需要确保回答结构清晰,涵盖这些方面,并参考提供的引用资料。 首先,我得回顾NMS的基本原理。根据引用[4],NMS是抑制极大值的元素,搜索局部极大值,常用于目标检测中处理重叠框。用户提供的引用[2]提到NMS在遮挡情况下的问题,而引用[3]则涉及YOLO中的应用。我需要整合这些信息。 接下来,作用部分。需要说明NMS的主要目的是消除冗余检测框,保留最佳结果。引用[2]和[4]都提到了这一点,尤其是处理滑动窗口产生的重叠框。这部分应该放在回答的前面,明确作用。 然后是具体应用场景。根据引用[3],YOLO中使用NMS处理检测结果,生成最终的边界框。引用[1]提到目标检测和边缘检测中的应用,可能需要提到这些例子,比如目标检测中的边界框抑制,边缘检测中的非极大值抑制。 实现步骤是关键部分。根据引用[4],步骤包括按置信度排序、选择最高分框、计算IOU、抑制重叠框,循环处理。需要详细描述每一步,可能结合引用中的例子,比如YOLOv9的处理过程(引用[3])。同时,引用[1]中的C++实现可以辅助说明步骤,但用户可能需要更通用的步骤而代码细节。 还需要注意阈值的作用,如置信度阈值和IOU阈值,引用[3]提到阈值过滤,这也是实现步骤中的一部分。此外,用户的问题是关于后处理,所以需要强调NMS是在模型输出后的处理阶段应用,如引用[3]中YOLOv9的后处理。 可能还需要提到NMS的变体,比如Soft-NMS(引用[2]),但用户主要问的是基础实现,所以可以简要提及作为扩展,但重点在标准NMS。 最后,生成相关问题,需根据内容提出,比如步骤优化、不同方法的比较、参数影响等。 需要检查是否符合系统级指令:使用正确LaTeX格式,独立公式用$$,行内用$。例如,IOU的计算可能需要公式,但用户的问题中没有明确提到公式,所以可能不需要。如果有公式的话,用正确格式。 确保回答结构清晰,分点说明作用、应用、实现步骤,可能用序号或小标题。同时引用资料在适当位置标注,如[^1]、[^2]等。 现在组织内容: 1. 作用:消除冗余框,保留最佳检测结果,提升检测精度。[^4][^2] 2. 应用场景:目标检测后处理(YOLO[^3],C++实现[^1]),边缘检测中的特征点处理[^1] 3. 实现步骤: a. 按置信度排序 b. 选最高分框,加入结果集 c. 计算与其他框的IOU,超过阈值则抑制 d. 循环处理剩余框 e. 重复直至处理完所有框[^4][^3] 4. 参数:IOU阈值、置信度阈值的影响[^3][^4] 5. 问题与改进:遮挡情况下的问题,Soft-NMS[^2] 确保每个部分都有引用支持,自然添加引用标识。例如,在说明步骤时,提到YOLOv9的处理引用,或者在IOU计算时引用[^4]。 最后,生成相关问题,如优化方法、参数选择、与Soft-NMS比较等。</think>非极大值抑制NMS)是目标检测后处理中的核心算法,主要用于消除冗余检测框并保留最佳结果。以下是其具体作用、应用场景和实现步骤的详细说明: --- ### **一、NMS的作用** 1. **消除冗余检测框**:在滑动窗口或密集预测模型中,同一目标可能生成多个重叠的边界框。NMS通过抑制低置信度的框,保留局部最高分的检测结果[^4]。 2. **提升检测精度**:避免重复检测导致的结果混乱,确保每个目标仅对应一个最优边界框[^2]。 --- ### **二、应用场景** 1. **目标检测后处理**:如YOLO系列模型对预测框进行筛选(例如YOLOv9处理后得到尺寸为$torch.Size([5, 6])$的张量)。 2. **边缘检测**:抑制极大值点,保留边缘的清晰度[^1]。 3. **特征点匹配**:在特征描述子中筛选关键点。 --- ### **三、实现步骤** 1. **按置信度排序** 将所有检测框按置信度(score)从高到低排序,生成列表$B = \{b_1, b_2, ..., b_n\}$。 2. **初始化结果集** 创建空列表$keep$用于存储保留的检测框。 3. **迭代筛选过程** ```plaintext while B不为空: a. 选择B中最高分的框b_max,加入keep b. 计算b_max与B中剩余框的IOU(交并比) c. 从B中删除所有与b_max的IOU超过阈值(如0.5)的框 ``` **IOU计算公式**: $$ \text{IOU} = \frac{\text{Area}(b_{\text{max}} \cap b_i)}{\text{Area}(b_{\text{max}} \cup b_i)} $$ 若IOU > 阈值,则认为两框检测同一目标,需抑制低分框[^4][^3]。 4. **输出最终结果** 返回列表$keep$作为最终的检测框集合。 --- ### **四、关键参数与优化** - **IOU阈值**:通常设为0.3~0.7,值越大保留的框越多,反之越严格[^3]。 - **置信度阈值**:预过滤低置信度检测框,减少NMS计算量。 - **Soft-NMS改进**:通过降低重叠框的置信度而直接删除,缓解目标遮挡导致的漏检问题[^2]。 --- ### **五、代码示例(Python伪代码)** ```python def nms(boxes, scores, iou_threshold=0.5): sorted_indices = sorted(range(len(scores)), key=lambda k: scores[k], reverse=True) keep = [] while sorted_indices: current = sorted_indices.pop(0) keep.append(current) # 计算IOU并筛选 sorted_indices = [i for i in sorted_indices if iou(boxes[current], boxes[i]) < iou_threshold] return keep ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值