前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >必考一题~

必考一题~

作者头像
灿视学长
发布2021-07-07 10:28:43
7790
发布2021-07-07 10:28:43
举报
文章被收录于专栏:灿视学长
面试必考—— NMS及优化

大家好,我是灿视。

目前有好几位粉丝,跟我反馈说考到了NMS。今天开始,我们好好把NMS这个点给lu过去。今天说的是针对传统NMS存在的问题而提出的优化。后面还会分享针对不同任务,推出的NMS,欢迎各位持续关注!

技术汇总

《百面计算机视觉汇总》

点击文末阅读原文,跳转到Github汇总地址!

1.

NMS

代码与实现

Non

-

Maximum

-

Suppression

(非极大值抑制): 当两个

box

空间位置非常接近,就以

score

更高的那个作为基准,看

IOU

即重合度如何,如果与其重合度超过阈值,就抑制

score

更小的

box

,只保留

score

大的就

Box

,其它的

Box

就都应该过滤掉。对于

NMS

而言,适合于水平框,针对各种不同形状的框,会有不同的

NMS

来进行处理。

具体的步骤如下

  1. 如图所示,我们有
6

个带置信率的

region
proposals

,我们先预设一个

IOU

的阈值如

0.7

  1. 按置信率大小对
6

个框排序,举例为

0.94, 0.91, 0.90, 0.83, 0.79, 0.77

  1. 设定置信率为
0.94

region
proposals

为一个物体框;

  1. 在剩下
5

region
proposals

中进行循环遍历,去掉与

0.94

物体框

IOU

大于

0.7

的。

  1. 重复
2

4

的步骤,直到没有

egion
proposals

为止。

  1. 每次获取到的最大置信率的
region
proposals

就是我们筛选出来的目标。

参考代码如下:

代码语言:javascript
复制
import numpy as np

def NMS(dets, thresh):
    """Pure Python NMS baseline."""
    # tl_x,tl_y,br_x,br_y及score
    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]
        keep.append(i)  #保留该类剩余box中得分最高的一个
        # 计算最高得分矩形框与剩余矩形框的相交区域
        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:]])

       #计算相交的面积,不重叠时面积为0
        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        
        #计算IoU:重叠面积 /(面积1+面积2-重叠面积)
        ovr = inter / (areas[i] + areas[order[1:]] - inter)

        #保留IoU小于阈值的box
        inds = np.where(ovr <= thresh)[0]
        order = order[inds + 1]   #注意这里索引加了1,因为ovr数组的长度比order数组的长度少一个

    return keep

运行后,则删除了多余的框,结果如图所示:

2.

Soft
NMS

的代码与实现

说到

Soft
NMS

,首先需要了解传统

NMS

有哪些缺点。其主要缺点包括如下:

  • 物体重叠:如下面第一张图,会有一个最高分数的框,如果使用
NMS

的话就会把其他置信度稍低,但是表示另一个物体的预测框删掉(由于和最高置信度的框

overlap

过大)

  • 所有的
bbox

都预测不准:不是所有的框都那么精准,有时甚至会出现某个物体周围的所有框都标出来了,但是都不准的情况,如下图所示。

  • 传统的
NMS

方法是基于分类分数的,只有最高分数的预测框能留下来,但是大多数情况下

IoU

和分类分数不是强相关,很多分类标签置信度高的框都位置都不是很准。

Soft
NMS

主要是针对

NMS

过度删除框的问题。

Soft-NMS

吸取了

NMS

的教训,在算法执行过程中不是简单的对

IoU

大于阈值的检测框删除,而是降低得分。算法流程同

NMS

相同,但是对原置信度得分使用函数运算,目标是降低置信度得分。其算法步骤如下:

红色的部分表示原始

NMS

算法,绿色部分表示

Soft

-

NMS

算法,区别在于,绿色的框只是把

s_{i}

降低了,而不是把

b_{i}

直接去掉,极端情况下,如果

f

只返回

0

,那么等同于普通的

NMS

b_{i}

为待处理

BBox

框,

B

为待处理

BBox

框集合,

s_{i}

b_{i}

框更新得分,

N_{t}

NMS

的阈值,

D

集合用来放最终的

BBox

f

是置信度得分的重置函数。

b_{i}

M

IOU

越大,

b_{i}

的得分

s_{i}

就下降的越厉害。

f

函数是为了降低目标框的置信度,满足条件,如果

b_{i}

M

IoU

越大,

f(iou(M, bi))

就应该越小,

Soft

-

NMS

提出了两种

f

函数:

经典的

NMS

算法将

IOU

大于阈值的窗口的得分全部置为

0

,可表述如下:

论文置信度重置函数有两种形式改进,一种是线性加权的

一种是高斯加权形式

s_{i}=s_{i} e^{-\frac{\mathrm{iou}\left(\mathcal{M}, b_{i}\right)^{2}}{\sigma}}, \forall b_{i} \notin \mathcal{D}
Soft
NMS

算法的优点如下:

  • 该方案可以很方便地引入到object detection算法中,不需要重新训练原有的模型;
  • soft-NMS在训练中采用传统的NMS方法,可以仅在推断代码中实现soft-NMS
NMS

Soft

-

NMS

特殊形式,当得分重置函数采用二值化函数时,

Soft

-

NMS

NMS

是相同的。

soft

-

NMS

算法是一种更加通用的非最大抑制算法。

而,在一些场景的实验中,可以看到

Soft
NMS

的效果也是优于

NMS

的。

img

这里提供一个

github

中的

Cython

代码展示:

代码语言:javascript
复制
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):
        
        # 在i之后找到confidence最高的框,标记为max_pos
        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
     # 找到max的框
        while pos < N:
            if maxscore < boxes[pos, 4]:
                maxscore = boxes[pos, 4]
                maxpos = pos
            pos = pos + 1
        
        # 交换max_pos位置和i位置的数据
     # 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
        
        while pos < N:
            # 先记录内层循环的数据bi
            x1 = boxes[pos, 0]
            y1 = boxes[pos, 1]
            x2 = boxes[pos, 2]
            y2 = boxes[pos, 3]
            s = boxes[pos, 4]
            
            # 计算iou
            area = (x2 - x1 + 1) * (y2 - y1 + 1)
            iw = (min(tx2, x2) - max(tx1, x1) + 1) # 计算两个框交叉矩形的宽度,如果宽度小于等于0,即没有相交,因此不需要判断
            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) #计算union面积
                    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

Softer
NMS

的代码与实现

针对剩余的两个问题,

Softer
NMS

做出了自己的努力。

  • 针对分类置信度和框的
IoU

不是强相关的问题,构建一种

IoU

的置信度,来建模有多大把握认为当前框和

GT

是重合的。

  • 针对所有的框单独拿出来都不准的问题,文章中提出一种方法,根据
IoU

置信度加权合并多个框优化最终生成框。

Softer

-

NMS

文章对预测框建模,以下公式中

x

表示偏移前的预测框,

x_{e}

表示偏移后的预测框,输出的

x_{g}

表示

GT

框,使用高斯函数对预测框建模:

P_{\Theta}(x)=\frac{1}{2 \pi \sigma^{2}}e^{-\frac{(x-x_{e})^2}{2 \sigma^{2}}}

对于

GT

框建模:使用

delta

分布(即标准方差为

0

的高斯分布极限)。

P_{D}(x)=\delta\left(x-x_{g}\right)

对于

delta

分布,当

\sigma

越小,其函数图像就会越瘦高,同时,当

\sigma

越小,表示网络越确定,可以使用

1-\sigma

就可以作为网络的置信度。

同时,论文使用

KL

散度来最小化

Bounding
box
regression
loss

。既

Bounding
box

的高斯分布和

ground
truth

的狄拉克

delta

分布的

KL

散度。直观上解释,

KL
Loss

使得

Bounding
box

预测呈高斯分布,且与

ground
truth

相近。而将包围框预测的标准差看作置信度。

faster
rcnn

中添加了

softer
nms

之后的示意图如图所示:

多加了一个

\sigma

预测,也就是

box
std

,而

Box

的预测其实就是上面公式中的

x_{e}

因此,整个计算过程如下:

  1. 计算
x_{e}

x

的2范数距离和

\sigma

计算出

P_{\theta}(x)

.

  1. 通过
x_{g}

x

的2范数距离算出

P_{D}

.

  1. 使用
P_{D}

P_{\theta}

计算

KLs

散度作为

loss

,最小化

KLLoss

关于坐标回归的损失函数:

\begin{array}{l} L_{r e g}=D_{K L}\left(P_{D}(x) \| P_{\Theta}(x)\right) \\ =\int P_{D}(x) \log \frac{P_{D}(x)}{P_{\Theta}(x)} d x \\ =-\int P_{D}(x) \log P_{\Theta}(x) d x+\int P_{D}(x) \log P_{D}(x) d x \\ =-\int P_{D}(x) \log P_{\Theta}(x) d x+H\left(P_{D}(x)\right) \\ =-\log P_{\Theta}\left(x_{g}\right)+H\left(P_{D}(x)\right) \\ =\frac{\left(x_{g}-x_{e}\right)^{2}}{2 \sigma^{2}}+\frac{1}{2} \log \left(\sigma^{2}\right)+\frac{1}{2} \log (2 \pi)+H\left(P_{D}(x)\right) \end{array}

而后面两项是与

x_{e}

无关,可以去掉~

L_{\text {reg }}=\alpha\left(\left|x_{g}-x_{e}\right|-\frac{1}{2}\right)-\frac{1}{2} \log (\alpha+\epsilon)

因此,计算过程如下图所示:

网络预测出来的结果是

x1_{i}, y1_{i}, x2_{i}, y2_{i}, \sigma{x1_{i}}, \sigma{x2_{i}}, \sigma{x3_{i}}, \sigma{x4_{i}}

。前面四个为坐标,而后面四个是坐标的

\sigma

上表中的蓝色的是

soft

-

nms

,只是降低了

S

的权值。重点看绿色的,绿字第一行表示拿出所有与

B

IoU

大于

N_{t}

的框(用

idx

表示),然后将所有这些框做一个加权,

B[idx]/C[idx]

其实是

B[idx] * 1/C[idx]

,后者是置信度

\frac{1}{\sigma^{2}}

,并使用

sum

做了归一化。需要注意的是,

Softer

-

NMS

算法中,

B

是不变的,

softer

-

nms

只调整每个框的位置,而不筛选框。

贴一张效果图:

参考

  1. http://blog.prince2015.club/2018/12/01/Soft-NMS/
  2. https://zhuanlan.zhihu.com/p/89426063
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 灿视学长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.
  • 2.
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档