一行代码改进NMS

一篇讲通过改进NMS来提高检测效果的论文。

文章链接: 《Improving Object Detection With One Line of Code》

Github链接: https://github.com/bharatsingh430/soft-nms

Motivation

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

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

另一方面,NMS的阈值也不太容易确定,设小了会出现下图的情况,设置过高又容易增大误检。

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

Method

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

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

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

一种是高斯加权的:

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

具体地,下面是作者给出的代码:(当然不止一行T_T)

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%的提升,且不增加额外的训练和计算负担。

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

时间: 2024-10-29 19:09:04

一行代码改进NMS的相关文章

根据生日的月份和日期,一行代码计算星座的js小函数(转)

看到了别人写的一个计算星座的js,冗长的有点儿看不过去,就自己写个了.我想,这个函数应该足够精简了:)什么 if 啊 switch 啊 for 啊 通通滚蛋了--传入参数:month [int] 1-12;  day [int] 1-31. // 根据生日的月份和日期,计算星座. http://blog.csdn.net/cuixiping/ function getAstro(month,day){        var s="魔羯水瓶双鱼牡羊金牛双子巨蟹狮子处女天秤天蝎射手魔羯";

一行代码解决IE兼容性问题

在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实IE给出了解决方案Google也给出了解决方案百度也应用了这种方案去解决IE的兼容问题 百度源代码如下 <!Doctype html><html xmlns=http://www.w3.org/1999/xhtml xmlns:bd=http://www.baidu.com/2010/xbdml>;<head><meta http-equiv=Content-Type content="text/h

一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10 http://www.jb51.net/css/383986.html

在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实IE给出了解决方案Google也给出了解决方案百度也应用了这种方案去解决IE的兼容问题 百度源代码如下 复制代码 代码如下: <!Doctype html> <html xmlns=http://www.w3.org/1999/xhtml xmlns:bd=http://www.baidu.com/2010/xbdml>; <head> <meta http-equiv=Content-Type conten

怎么用一行代码解决CSS各种IE各种兼容问题

用一行代码来解决CSS在,IE6,IE7,IE8,IE9,IE10 中的各种兼容性问题. 在网站前端写代码的过程中,很多时间IE各个版本的兼容问题很难整.现在百度与谷歌都有了一行解决这种兼容性的代码了.如下面的. 办法一 百度也应用了这种方案去解决IE的兼容问题 百度源代码如下 1 <!Doctype html> 2 <htmlxmlns=http://www.w3.org/1999/xhtmlxmlns:bd=http://www.baidu.com/2010/xbdml> 3 

有一个NSStirng类型,retain方式声明的name属性的setter方法内部每一行代码的作用?

- (void)setName:(NSString *)name { 判断原有对象和新对象是否是同一个对象,如果是同一个,就没有必要再重新赋值,否则会先release 再retain,就会变成野指针 if (_name != name) { 释放保有之前对象的所有权 [_name release]; 让实例变量 _name保有新的对象的所有权 _name = [name retain]; } } 有一个NSStirng类型,retain方式声明的name属性的setter方法内部每一行代码的作用

C++ - 删除文本的最后一行 代码(C++)

删除文本的最后一行 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 读取文本的每行("\n"), 存储入数组vector<string>, 输出时, 少输出最后一行, 即可. 代码: /* * main.cpp * * Created on: 2014.06.08 * Author: Spike */ /*vs 2012*/ #include <windows.h> #include <fstream&g

一行代码的快速排序

1.一维高斯函数: a表示得到曲线的高度,b是指曲线在x轴的中心,c指width(与半峰全宽有关),图形如下: . 2.根据一维高斯函数,可以推导得到二维高斯函数: 在图形上,正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小. 计算平均值的时候,我们只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值.常用作图像平滑操作. 例如:通常,图像处理软件会提供"模糊"(blur)滤镜,使图片产生模糊的效果. &q

一行代码提取url中querystring的某个key的值

var itemdata = "OrderFilter=0&ProjectTag=15&DateType=0"; var projectTag = itemdata.replace(/.*projecttag=([\d]+).*/gi, "$1"); 重点就是第二行,用匹配到的括号里的值替换整个文本. 如果用传统方法,肯定要先split"&"符号,再split"="符号,然后再取值. 这样多好,就一行代

Core Graphics快速入门——从一行代码说起

Core Graphics入门 想必每个第一次接触Core Graphics的开发者都被无数的API.混乱的代码逻辑折腾得头疼不已,甚至望而却步.即使是绘制一个简单的矩形也看上去非常繁琐.本文换一个角度,整理一下有关Core Graphics的知识,也算作是这段时间学习的总结. Core Graphics和UIKit的区别 首先从概念上了解一下: 根据苹果的描述,UIKit是我们最容易也是最常接触到的框架.绝大多数图形界面都由UIKit完成.但是UIKit依赖于Core Graphics框架,也