说说soft-nms和nms那些事

前言

今天来介绍下非极大抑制。
在这里插入图片描述

什么是非极大抑制?

目标检测算法会输出多个检测边框,尤其是在真实目标周围会有很多置信度高的检测边框。为了去除重复的检测边框,达到每个物体有且只有一个检测结果的目的。非极大值抑制(Non-maximum suppression,NMS)是一种获取局部最大值,抑制非极大值的算法,在计算机视觉中有着广泛的应用。其核心思想是一个迭代-遍历-消除的过程,重叠率大于固定阈值的低分框会被高分框抑制。
在这里插入图片描述
1、首先设置IOU阈值
2、对种类进行循环,
3、对同一种类类别而言对候选框依据类别得分进行排序,选中类别得分最高的候选框,遍历其余的候选框
4、如果和当前最类别得分最高的候选框的IOU大于IOU阈值,将其剔除
5、未处理的边框中继续选一个类别得分最高的,重复2-5上述过程,直到处理完所有的边框为止。保留下来的候选框即为检测结果。

  def detection_out(self, predictions, mbox_priorbox, background_label_id=0, keep_top_k=200,
                        confidence_threshold=0.4):
        
        # 网络预测的结果
        mbox_loc = predictions[0]
        # 置信度
        mbox_conf = predictions[1]
        # 先验框
        mbox_priorbox = mbox_priorbox
        
        results = []
        # 对每一个图片进行处理
        for i in range(len(mbox_loc)):

            decode_bbox = self.decode_boxes(mbox_loc[i], mbox_priorbox)

            bs_class_conf = mbox_conf[i]
            
            class_conf = np.expand_dims(np.max(bs_class_conf, 1),-1)
            class_pred = np.expand_dims(np.argmax(bs_class_conf, 1),-1)

            conf_mask = (class_conf >= confidence_threshold)[:,0]

            detections = np.concatenate((decode_bbox[conf_mask], class_conf[conf_mask], class_pred[conf_mask]), 1)
            unique_class = np.unique(detections[:,-1])

            best_box = []
            if len(unique_class) == 0:
                results.append(best_box)
                continue
            # 对种类进行循环,
            # 非极大抑制的作用是筛选出一定区域内属于同一种类得分最大的框,
            # 对种类进行循环可以帮助我们对每一个类分别进行非极大抑制。
            for c in unique_class:
                cls_mask = detections[:,-1] == c

                detection = detections[cls_mask]
                scores = detection[:,4]
                # 根据得分对该种类进行从大到小排序。
                arg_sort = np.argsort(scores)[::-1]
                detection = detection[arg_sort]
                while np.shape(detection)[0]>0:
                    # 每次取出得分最大的框,计算其与其它所有预测框的重合程度,重合程度过大的则剔除。
                    best_box.append(detection[0])
                    if len(detection) == 1:
                        break
                    ious = iou(best_box[-1],detection[1:])
                    detection = detection[1:][ious<self._nms_thresh]
            results.append(best_box)
        # 获得,在所有预测结果里面,置信度比较高的框
        # 还有,利用先验框和retinanet的预测结果,处理获得了真实框(预测框)的位置
        return results

传统的非极大抑制产生的问题?

如果一个物体在另一个物体重叠区域出现,即当两个目标框接近时,分数更低的框就会因为与之重叠面积过大而被删掉,从而导致对该物体的检测失败并降低了算法的平均检测率,如下图所示,检测算法本来应该输出两个检测框,但是传统的非极大值抑制算由于绿框的得分较低且绿框和红框的IOU大于设定的阈值,因此会被过滤掉,导致只检测出一匹马,显然这样的算法设计是不合理的。
在这里插入图片描述

soft-nms

NMS直接粗暴的将和得分最大的box的IOU大于阈值的box的得分置零,那么有没有缓和(soft)一点的方式,这就引出了soft-nms,简言之soft-nms是用一个稍微小一点的分数替代原有的分数,而非直接粗暴的置零。
传统的非极大值抑制算法,当前检测框和最高得分检测框的IOU大于阈值时,直接将该检测框的得分置零。
其中 Si 表示当前检测框的得分, Nt为IOU的阈值,M为得分最高的检测框。
在这里插入图片描述
将当前检测框得分乘以一个权重函数,该函数会衰减与最高得分检测框M有重叠的相邻检测框分数,越是与M框高度重叠的检测框,其得分衰减越严重,为此我们选择高斯函数为权重函数,从而修改其删除检测框的规则。高斯权重函数如下所示:
在这里插入图片描述
代码对比:
传统nms:

while np.shape(detection)[0]>0:
    # 6、每次取出得分最大的框,计算其与其它所有预测框的重合程度,重合程度过大的则剔除。
    best_box.append(detection[0])
    if len(detection) == 1:
        break
    ious = iou(best_box[-1],detection[1:])
    detection = detection[1:][ious<nms_thres]

sotf-nms:

while np.shape(detection)[0]>0:
    best_box.append(detection[0])
    if len(detection) == 1:
        break
    ious = iou(best_box[-1],detection[1:])
    detection[1:,4] = np.exp(-(ious * ious) / sigma)*detection[1:,4]
    detection = detection[1:]
    scores = detection[:,4]
    arg_sort = np.argsort(scores)[::-1]
    detection = detection[arg_sort]

猜你喜欢

转载自blog.csdn.net/qq_35914625/article/details/108412140