Improving Object Detection With One Line of Code

论文地址:https://arxiv.org/pdf/1704.04503.pdf

Github项目:https://github.com/bharatsingh430/soft-nms

论文摘要

非最大抑制(Non-maximum suppression, NMS)是物体检测流程中重要的组成部分。它首先基于物体检测分数产生检测框,分数最高的检测框M被选中,其他与被选中检测框有明显重叠的检测框被抑制。该过程被不断递归的应用于其余检测框。根据算法的设计,如果一个物体处于预设的重叠阈值之内,可能会导致检测不到该待检测物体。因此,我们提出了Soft-NMS算法,该连续函数对非最大检测框的检测分数进行衰减而非彻底移除。它仅需要对传统的NMS算法进行简单的改动且不增额外的参数。该Soft-NMS算法在标准数据集PASCAL VOC2007(较R-FCN和Faster-RCNN提升1.7%)和MS-COCO(较R-FCN提升1.3%,较Faster-RCNN提升1.1%)上均有提升。此外,Soft-NMS具有与传统NMS相同的算法复杂度,使用高效。Soft-NMS也不需要额外的训练,并易于实现,它可以轻松的被集成到任何物体检测流程中。

NMS处理流程

传统的NMS处理方法可以通过以下的分数重置函数(Rescoring Function)来表达:

在这个公式中, NMS采用了硬阈值来判断相邻检测框是否保留。但是,换一种方法,假设我们对一个与M高度重叠的检测框bi的检测分数进行衰减,而非全部抑制。如果检测框bi中包含不同于M中的物体,那么在检测阈值比较低的情况下,该物体并不会错过检测。但是,如果bi中并不包含任何物体,即使在衰减过后,bi的分数仍然较高,它还是会产生一个假阳性的结果。因此,在使用NMS做物体检测处理的时候,需要注意以下几点:

  • 相邻检测框的检测分数应该被降低,从而减少假阳性结果,但是,衰减后的分数仍然应该比明显的假阳性结果要高。
  • 通过较低的NMS重叠阈值来移除所有相邻检测框并不是最优解,并且很容易导致错过被检测物体,特别是在物体高度重叠的地方
  • 当NMS采用一个较高的重叠阈值时,平均准确率可能会相应降低。

Motivation

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

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

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

float

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

Method

如下图:如文章题目而言,就是用一行代码来替换掉原来的NMS。按照下图整个处理一遍之后,指定一个置信度阈值,然后最后得分大于该阈值的检测框得以保留


原来的NMS可以描述如下:将IOU大于阈值的窗口的得分全部置为0。


文章的改进有两种形式,一种是线性加权的:


一种是高斯加权的:

float

分析上面的两种改进形式,思想都是:M为当前得分最高框,bi为待处理框,bi和M的IOU越大,bi的得分si就下降的越厉害。

值得注意的是,soft-NMS也是一种贪心算法,并不能保证找到全局最优的检测框分数重置。但是,soft-NMS算法是一种更加通用的非最大抑制算法,传统的NMS算法可以看做是它的一个采用不连续二值权重函数的特例。除了以上这两种分数重置函数,我们也可以考虑开发其他包含更多参数的分数重置函数,比如Gompertz函数等。但是它们在完成分数重置的过程中增加了额外的参数。

NMS代码:

%% NMS:non maximum suppression
function pick = nms(boxes,threshold,type)
% boxes: m x 5,表示有m个框,5列分别是[x1 y1 x2 y2 score]
% threshold: IOU阈值
% type:IOU阈值的定义类型

    % 输入为空,则直接返回
    if isempty(boxes)
      pick = [];
      return;
    end

    % 依次取出左上角和右下角坐标以及分类器得分(置信度)
    x1 = boxes(:,1);
    y1 = boxes(:,2);
    x2 = boxes(:,3);
    y2 = boxes(:,4);
    s = boxes(:,5);

    % 计算每一个框的面积
    area = (x2-x1+1) .* (y2-y1+1);

    %将得分升序排列
    [vals, I] = sort(s);

    %初始化
    pick = s*0;
    counter = 1;

    % 循环直至所有框处理完成
    while ~isempty(I)
        last = length(I); %当前剩余框的数量
        i = I(last);%选中最后一个,即得分最高的框
        pick(counter) = i;
        counter = counter + 1;  

        %计算相交面积
        xx1 = max(x1(i), x1(I(1:last-1)));
        yy1 = max(y1(i), y1(I(1:last-1)));
        xx2 = min(x2(i), x2(I(1:last-1)));
        yy2 = min(y2(i), y2(I(1:last-1)));  
        w = max(0.0, xx2-xx1+1);
        h = max(0.0, yy2-yy1+1); 
        inter = w.*h;

        %不同定义下的IOU
        if strcmp(type,'Min')
            %重叠面积与最小框面积的比值
            o = inter ./ min(area(i),area(I(1:last-1)));
        else
            %交集/并集
            o = inter ./ (area(i) + area(I(1:last-1)) - inter);
        end

        %保留所有重叠面积小于阈值的框,留作下次处理
        I = I(find(o<=threshold));
    end
    pick = pick(1:(counter-1));
end

Soft-NMS代码:

def cpu_soft_nms(np.ndarray[float, ndim=2] boxes, float sigma=0.5, float Nt=0.3, float threshold=0.001, unsigned int method=0):
    cdef unsigned int N = boxes.shape[0]
    cdef float iw, ih, box_area
    cdef float ua
    cdef int pos = 0
    cdef float maxscore = 0
    cdef int maxpos = 0
    cdef float x1,x2,y1,y2,tx1,tx2,ty1,ty2,ts,area,weight,ov

    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]

            # 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

Experiments

下图可以看出,基本可以获得平均1%的提升,且不增加额外的训练和计算负担。

float

高斯方差以及NMS的IOU阈值的敏感性测试:

float

猜你喜欢

转载自blog.csdn.net/julialove102123/article/details/80486767
今日推荐