0
点赞
收藏
分享

微信扫一扫

目标检测基础(NMS)

目标检测基础(NMS)

什么是非最大值抑制

非最大值抑制是一种主要用于目标检测的技术,旨在从一组重叠框中选择最佳边界框。在下图中,非最大值抑制的目的是删除黄色和蓝色框,这样我们只剩下绿色框作为最终的预测结果。

计算NMS的步骤

为了了解什么是boundingbox,以及IOU的含义,我在前篇发表了关于IOU的文章。前篇文章中描述的术语将在本文中继续介绍。

我们首先描述NMS在这个特定示例中的工作过程,然后解释一个更通用的算法,将其扩展到不同的场景下。

1、术语定义

我们将使用的每个边界框的格式如下:
b o x _ l i s t = [ x 1 ,    y 1 ,    x 2 ,    y 2 ,    c l a s s    c o n f i d e n c e ] box\_list=[x1,\ \ y1,\ \ x2,\ \ y2,\ \ class\ \ confidence] box_list=[x1,  y1,  x2,  y2,  class  confidence]
让我们假设,对于上述这个特定的图像我们有3个边界框,即:
b b o x _ l i s t = [ b l u e _ b o x , y e l l o w _ b o x , g r e e n _ b o x ] bbox\_list=[blue\_box,yellow\_box,green\_box] bbox_list=[blue_box,yellow_box,green_box]
对于每个框,相关定义如下
b l u e _ b o x = [ x 3 ,    y 3 ,    x 4 ,    y 4 ,    " C a t "    0.85 ] y e l l o w _ b o x = [ x 5 ,    y 5 ,    x 6 ,    y 6 ,    " C a t "    0.75 ] g r e e n _ b o x = [ x 1 ,    y 1 ,    x 2 ,    y 2 ,    " C a t "    0.9 ] blue\_box=[x3,\ \ y3,\ \ x4,\ \ y4,\ \ "Cat"\ \ 0.85] \\yellow\_box=[x5,\ \ y5,\ \ x6,\ \ y6,\ \ "Cat"\ \ 0.75] \\green\_box=[x1,\ \ y1,\ \ x2,\ \ y2,\ \ "Cat"\ \ 0.9] blue_box=[x3,  y3,  x4,  y4,  "Cat"  0.85]yellow_box=[x5,  y5,  x6,  y6,  "Cat"  0.75]green_box=[x1,  y1,  x2,  y2,  "Cat"  0.9]

2、根据置信度过滤候选框

作为NMS中的第一步,我们按照置信度降序对框进行排序。排序后我们得到结果为:
b b o x _ l i s t = [ g r e e n _ b o x , b l u e _ b o x , y e l l o w _ b o x ] bbox\_list=[green\_box,blue\_box,yellow\_box] bbox_list=[green_box,blue_box,yellow_box]
然后我们定义一个置信度阈值。任何置信度低于此阈值的框都将被删除。对于本例,假设置信度阈值为0.8。使用该阈值,我们将删除黄色框,因为其置信度<0.8。这就给我们留下了:
b b o x _ l i s t = [ g r e e n _ b o x , b l u e _ b o x ] bbox\_list=[green\_box,blue\_box] bbox_list=[green_box,blue_box]
这一步操作后的结果图如下所示:

3、根据IOU过滤

由于框的置信度按降序排列,我们知道列表中的第一个框的置信度最高。我们从列表中删除第一个框,并将其添加到新列表中。在我们的例子中,我们将删除绿色框,并将其放入一个新列表中,比如bbox_list_new。

在这个阶段,我们为IOU定义了一个额外的阈值。此阈值用于删除具有高重叠度的框。其原因如下:如果两个框有大量重叠,并且它们也属于同一类,则很可能两个框都覆盖了同一对象(我们可以从上图验证这一点)。由于真实情况是每个对象只有一个框,因此我们尝试删除置信度较低的框。

在上述示例中,假设我们的IOU阈值为0.5

我们现在开始计算绿框的IOU,其中bbox_list中剩余的每个框也具有相同的类。在我们的例子中,我们将只使用蓝色框来计算绿色框的IOU。

如果绿框和蓝框的IOU大于我们定义的阈值0.5,我们将删除蓝框,因为它的置信度较低,并且有明显的重叠。

对图像中的每个框重复此过程,上述示例中最终只生成具有高置信度的唯一框。如下所示:

NMS算法

总结上述过程,我们可以得到NMS的计算过程如下:

  • 定义置信度阈值和IOU阈值取值。
  • 按置信度降序排列边界框bounding_box
  • 从bbox_list中删除置信度小于阈值的预测框
  • 循环遍历剩余框,首先挑选置信度最高的框作为候选框.
  • 接着计算其他和候选框属于同一类的所有预测框和当前候选框的IOU。
  • 如果上述任两个框的IOU的值大于IOU阈值,那么从box_list中移除置信度较低的预测框
  • 重复此操作,直到遍历完列表中的所有预测框。

代码实现

def nms(boxes, conf_threshold = 0.7, iou_threshold = 0.4):
    bbox_list_thresholded = [] 
    bbox_list_new = []  
    boxes_sorted = sorted(boxes, reverse = True, key = lambda x: x[5]) 
    for box in boxes_sorted:
        if box[5] > conf_threshold: 
            bbox_list_thresholded.append(box)  
        else:
            pass
        
    while len(bbox_list_thresholded) > 0:
        current_box = bbox_list_thresholded.pop(0)  
        bbox_list_new.append(current_box)  
        for box in bbox_list_thresholded:
            if current_box[4] == box[4]: 
                iou = IOU(current_box[:4], box[:4])  
                if iou > iou_threshold: 
                    bbox_list_thresholded.remove(box)  
    return bbox_list_new

相关解释如下:

def nms(boxes, conf_threshold=0.7, iou_threshold=0.4):

此函数将图像候选框列表、置信阈值和iou阈值作为输入。(这里将相应的默认值分别设置为0.7和0.4)

bbox_list_thresholded = []
bbox_list_new = []

接着我们创建了两个名为bbox_list_threshold和bbox_list_new的列表。

  • bbox_list_threshold:包含筛选低置信度框后的新框列表
  • bbox_list_new:包含执行NMS后的最终框列表
boxes_sorted = sorted(boxes, reverse=True, key = lambda x : x[5])

在上述术语定义中,按照置信度的降序对框列表进行排序,并将新列表存储在变量boxes_sorted中.

这里我们采用python的内置sorted函数对其进行排序,该函数根据key字段指定排序规则.

在我们的例子中,我们指定一个关键字reverse=True来按降序对列表进行排序,同时指定第二个关键字用于排序的约束。这里我们使用的lambda函数提供了一个映射,返回每个边界框的第5个元素(置信度)。

经过上述两个参数的设定,在遍历每个框时,排序函数将按照置信度对候选框按照降序排序。

for box in boxes_sorted:
    if box[5] > conf_threshold:
        bbox_list_thresholded.append(box)
    else:
        pass

我们遍历所有已排序的框,并移除置信度低于我们设置的阈值(conf_threshold=0.7)的框

while len(bbox_list_thresholded) > 0:
    current_box = bbox_list_thresholded.pop(0)
    bbox_list_new.append(current_box)

在上述根据置信度过滤候选框中,我们逐个循环遍历阈值框列表(bbox_list_threshold)中的所有框,直到列表清空。

我们首先从这个列表中删除(弹出)第一个框(当前框),因为它具有最高的可信度,然后将它附加到我们的最终列表中(bbox_list_new)。

for box in bbox_list_thresholded:
    if current_box[4] == box[4]:
        iou = IOU(current_box[:4], box[:4])
        if iou > iou_threshold:
            bbox_list_thresholded.remove(box)

然后,我们迭代列表bbox_list_threshold中所有剩余的框,并检查它们是否与当前框类别相同。(box[4]对应于类别)

如果两个框属于同一类,我们计算这些框之间的IOU, 如果IOU>IOU_threshold,我们将从列表bbox_list_thresholded中移除置信度较低的框。

return bbox_list_new

在非最大移植之后,我们返回更新后的框的列表bbox_list_new。

举报

相关推荐

0 条评论