您的位置:首页 > 移动开发 > Objective-C

目标检测:Improving Object Detection With One Line of Code

2017-11-27 15:27 519 查看
一篇讲通过改进NMS来提高检测效果的论文。论 文 地 址: 《Improving Object Detection With One Line of Code》Github地址: https://github.com/bharatsingh430/soft-nms同时这篇知乎的文章总结的也相当到位: https://zhuanlan.zhihu.com/p/28129034 NMS:Non-Maximum Suppression对于检测任务,NMS是一个必需的部件,其为对检测结果进行冗余去除操作的后处理算法。标准的NMS为手工设计的,基于一个固定的距离阈值进行贪婪聚类,(greedily accepting local maxima and discarding their neighbours)即贪婪地选取得分高的检测结果并删除那些超过阈值的相邻结果,使得在recall和precision之间取得权衡。之前的相关工作大多都是利用NMS作为后处理操作。Soft-NMS:Improving Object Detection With One Line of Code不同于在NMS中采用单一阈值,对与最大得分检测结果M超过阈值的结果进行抑制,其主要考虑Soft-NMS,对所有目标的检测得分以相应overlap with M的连续函数进行衰减。其伪代码如下:ConvNMS:A Convnet for Non-maximum Suppression其主要考虑IoU阈值设定得高一些,则可能抑制得不够充分,而将IoU阈值设定得低一些,又可能多个ture positive被merge到一起。其设计一个卷积网络组合具有不同overlap阈值的greedyNMS结果,通过学习的方法来获得最佳的输出。基础框架如下:Pure NMS Network:Learning non-maximum suppression考虑目标间具有高遮挡的密集场景,其提出一个新的网络架构来执行NMS。经分析,检测器对于每个目标仅产生一个检测结果有两个关键点是必要的,一是一个loss惩罚double detections以告诉检测器我们对于每个目标仅需一个检测结果,二是相邻检测结果的joint processing以使得检测器具有必要的信息来分辨一个目标是否被多次检测。论文提出Gnet,其为第一个“pure”NMS网络。Gnet图示如下:Yes-Net: An effective Detector Based on Global Information不同于NMS,其主要有两个缺点,一是阈值必须人工设定,而在固定阈值下选择所有目标的输出边框是很难的,二是当检测器利用NMS时其假设输出边框都是独立的,但这些边框很可能是共享一些逻辑关系的。因此考虑利用RNN作为滤波器以得到最好的检测边框,其能提升检测器泛化能力。

动机:

绝大部分目标检测方法,最后都要用到 NMS-非极大值抑制进行后处理。 通常的做法是将检测框按得分排序,然后保留得分最高的框,同时删除与该框重叠面积大于一定比例的其它框。这种贪心式方法存在如下图所示的问题: 红色框和绿色框是当前的检测结果,二者的得分分别是0.95和0.80。如果按照传统的NMS进行处理,首先选中得分最高的红色框,然后绿色框就会因为与之重叠面积过大而被删掉。另一方面,NMS的阈值也不太容易确定,设小了会出现下图的情况(绿色框因为和红色框重叠面积较大而被删掉),设置过高又容易增大误检。思路:不要粗鲁地删除所有IOU大于阈值的框,而是降低其置信度。

方法:

先直接上伪代码,如下图:如文章题目而言,就是用一行代码来替换掉原来的NMS。按照下图整个处理一遍之后,指定一个置信度阈值,然后最后得分大于该阈值的检测框得以保留原来的NMS可以描述如下:将IOU大于阈值的窗口的得分全部置为0。文章的改进有两种形式,一种是线性加权的:一种是高斯加权的:分析上面的两种改进形式,思想都是:M为当前得分最高框,bi 为待处理框,bi 和M的IOU越大,bi 的得分si 就下降的越厉害。具体地,下面是作者给出的代码:(当然不止一行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

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐