• NMS 和 Soft-NMS


    转自https://zhuanlan.zhihu.com/p/42018282

    一  NMS

    NMS算法的大致思想:对于有重叠的候选框:若大于规定阈值(某一提前设定的置信度)则删除,低于阈值的保留。对于无重叠的候选框:都保留。

    所谓非极大值抑制:先假设有6个输出的矩形框(即proposal_clip_box),根据分类器类别分类概率做排序,从小到大分别属于车辆的概率(scores)分别为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是我们保留下来的第二个矩形框。
    就这样一直重复,找到所有被保留下来的矩形框。

     

    如上图F与BD重合度较大,可以去除BD。AE重合度较大,我们删除A,保留scores较大的E。C和其他重叠都小保留C。最终留下了C、E、F三个。

    相关代码:

    # coding:utf-8
    import numpy as np
    def py_cpu_nms(dets, thresh):
        """Pure Python NMS baseline."""
        # 所有图片的坐标信息,字典形式储存??
        x1 = dets[:, 0]
        y1 = dets[:, 1]
        x2 = dets[:, 2]
        y2 = dets[:, 3]
        scores = dets[:, 4]
    
        areas = (x2 - x1 + 1) * (y2 - y1 + 1)  # 计算出所有图片的面积
        order = scores.argsort()[::-1]  # 图片评分按升序排序
    
        keep = []  # 用来存放最后保留的图片的相应评分
        while order.size > 0:
            i = order[0]  # i 是还未处理的图片中的最大评分
            keep.append(i)  # 保留改图片的值
            # 矩阵操作,下面计算的是图片i分别与其余图片相交的矩形的坐标
            tmp=x1[order[1:]]
            xxxx = x1[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:]])
    
            # 计算出各个相交矩形的面积
            w = np.maximum(0.0, xx2 - xx1 + 1)
            h = np.maximum(0.0, yy2 - yy1 + 1)
            inter = w * h
            # 计算重叠比例
            ovr = inter / (areas[i] + areas[order[1:]] - inter)
    
            # 只保留比例小于阙值的图片,然后继续处理
            inds = np.where(ovr <= thresh)[0]
            indsd= inds+1
            order = order[inds + 1]
    
        return keep
    boxes = np.array([[100, 100, 150, 168, 0.63],[166, 70, 312, 190, 0.55],[221, 250, 389, 500, 0.79],[12, 190, 300, 399, 0.9],[28, 130, 134, 302, 0.3]])
    thresh = 0.1
    keep = py_cpu_nms(boxes, thresh)
    print(keep)
     

    二 soft NMS

    论文链接:

    github:bharatsingh430/soft-nms

    soft NMS提出尤其对密集物体检测的检测效果有一定的提升作用.

    绝大部分目标检测方法,最后都要用到 NMS-非极大值抑制进行后处理。 通常的做法是将检测框按得分排序,然后保留得分最高的框,同时删除与该框重叠面积大于一定比例的其它框。

    这种贪心式方法存在如下图所示的问题: 红色框和绿色框是当前的检测结果,二者的得分分别是0.95和0.80。如果按照传统的NMS进行处理,首先选中得分最高的红色框,然后绿色框就会因为与之重叠面积过大而被删掉。

    另一方面,NMS的阈值也不太容易确定,设小了会出现下图的情况(绿色框因为和红色框重叠面积较大而被删掉),设置过高又容易增大误检。

    思路:不要粗鲁地删除所有IOU大于阈值的框,而是降低其置信度

    soft NMS算法的大致思路为:M为当前得分最高框,bi 为待处理框,bi 和M的IOU越大,bi 的得分si 就下降的越厉害。

    算法结构如图所示:

    NMS中:

    soft NMS中:

    (1)线性加权:

    (2)高斯加权:

    soft NMS仍然有问题:其阈值仍然需要手工设定

    soft NMS的相关代码如下:

    # coding:utf-8
    import numpy as np
    def soft_nms(boxes, sigma=0.5, Nt=0.1, threshold=0.001, method=1):
        N = boxes.shape[0]
        pos = 0
        maxscore = 0
        maxpos = 0
    
        for i in range(N):
            maxscore = boxes[i, 4]
            maxpos = i
    
            tx1 = boxes[i,0]
            ty1 = boxes[i,1]
            tx2 = boxes[i,2]
            ty2 = boxes[i,3]
            ts = boxes[i,4]
    
            pos = i + 1
        # get max box
            while pos < N:
                if maxscore < boxes[pos, 4]:
                    maxscore = boxes[pos, 4]
                    maxpos = pos
                pos = pos + 1
    
        # add max box as a detection
            boxes[i,0] = boxes[maxpos,0]
            boxes[i,1] = boxes[maxpos,1]
            boxes[i,2] = boxes[maxpos,2]
            boxes[i,3] = boxes[maxpos,3]
            boxes[i,4] = boxes[maxpos,4]
    
        # swap ith box with position of max box
            boxes[maxpos,0] = tx1
            boxes[maxpos,1] = ty1
            boxes[maxpos,2] = tx2
            boxes[maxpos,3] = ty2
            boxes[maxpos,4] = ts
    
            tx1 = boxes[i,0]
            ty1 = boxes[i,1]
            tx2 = boxes[i,2]
            ty2 = boxes[i,3]
            ts = boxes[i,4]
    
            pos = i + 1
        # NMS iterations, note that N changes if detection boxes fall below threshold
            while pos < N:
                x1 = boxes[pos, 0]
                y1 = boxes[pos, 1]
                x2 = boxes[pos, 2]
                y2 = boxes[pos, 3]
                s = boxes[pos, 4]
    
                area = (x2 - x1 + 1) * (y2 - y1 + 1)
                iw = (min(tx2, x2) - max(tx1, x1) + 1)
                if iw > 0:
                    ih = (min(ty2, y2) - max(ty1, y1) + 1)
                    if ih > 0:
                        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
    
                        boxes[pos, 4] = weight*boxes[pos, 4]
                        print(boxes[:, 4])
    
                # if box score falls below threshold, discard the box by swapping with last box
                # update N
                        if boxes[pos, 4] < threshold:
                            boxes[pos,0] = boxes[N-1, 0]
                            boxes[pos,1] = boxes[N-1, 1]
                            boxes[pos,2] = boxes[N-1, 2]
                            boxes[pos,3] = boxes[N-1, 3]
                            boxes[pos,4] = boxes[N-1, 4]
                            N = N - 1
                            pos = pos - 1
    
                pos = pos + 1
        keep = [i for i in range(N)]
        return keep
    boxes = np.array([[100, 100, 150, 168, 0.63],[166, 70, 312, 190, 0.55],[221, 250, 389, 500, 0.79],[12, 190, 300, 399, 0.9],[28, 130, 134, 302, 0.3]])
    keep = soft_nms(boxes)
    print(keep)
     
  • 相关阅读:
    SDWebImage源码解读之SDWebImageDownloader
    Swift 中函数使用指南
    SDWebImage源码解读之SDWebImageDownloaderOperation
    Swift enum(枚举)使用范例
    用C语言封装OC对象(耐心阅读,非常重要)
    终端mysql Operation not permitted错误解决方案
    SDWebImage源码解读之SDWebImageCache(下)
    SDWebImage源码解读之SDWebImageCache(上)
    SDWebImage源码解读_之SDWebImageDecoder
    递归的本质
  • 原文地址:https://www.cnblogs.com/hotsnow/p/11014904.html
Copyright © 2020-2023  润新知