NMS (非极大值抑制)算法
NMS算法经常用于目标检测等视觉任务,其可以抽象成图论中的算法,从图的节点中筛选比任何相邻节点的值大的节点。
NMS的入参通常是 scores 数组和 实体数组 items, 其中 items 可能时一些boundingbox。
- 首先,我们按照 scores 的降序 对所有的 item 进行排序。
- 将 score 最大的实体首先放入保存队列中。
- 遍历剩下的 item,将不和保存队列中 item 相邻的节点都放入保存队列中。
代码如下:
def adj(item1, item2):
"在目标检测应用中,通常我们会根据两个实体的IOU判断他们是否是相邻节点"
if iou(item1, item2)> threshold:
return True
return False
def nms(scores, items):
order = argsort(scores, descending=True)
scores = scores[order]
items = items[order]
keep = list()
for i in range(len(items)):
current_item = items[i]
reserve = True # 标记当前的实体是否应该保留
for pre_idx in keep:
pre_item = items[pre_idx]
if adj(pre_item, current_item):
reserve = False
# 和保存队列中的item有相邻,该实体被抑制
break
if reserve:
keep.append(i)
return scores[keep], items[keep]
Soft-NMS 算法 1
在解释Soft-NMS算法之前,需要观察NMS算法的劣势。以下图为例子。
可以看到,明显右边的结果更加符合我们预期,但是使用NMS只能得到左边的结果,也就是存在漏检。出现漏检的原因显然,两个boundingbox之间的IOU只要大于阈值其中就会被抑制掉。
因此Soft-NMS提出的算法是在两个实体IOU大于阈值时,不要直接抑制掉,而是给这个实体稍微低一些的分数。
那么如何降低分数呢?这个有不同的做法。比如文章1中提出的两种:
s
i
=
{
s
i
,
i
o
u
(
M
,
b
i
)
<
N
t
s
i
(
1
−
i
o
u
(
M
,
b
i
)
,
i
o
u
(
M
,
b
i
)
≥
N
t
(1)
s_i = \left\{ \begin{aligned} & s_i, & {\rm iou}(\mathcal{M}, b_i) \lt N_t \\ & s_i(1-{\rm iou}(\mathcal{M}, b_i), & {\rm iou}(\mathcal{M}, b_i) \ge N_t \end{aligned} \right. \tag1
si={si,si(1−iou(M,bi),iou(M,bi)<Ntiou(M,bi)≥Nt(1)
s i = s i exp ( − i o u ( M , b i ) 2 σ ) , b i ∉ D (2) s_i = s_i \exp(-\frac{{\rm iou}(\mathcal{M}, b_i)^2}{\sigma}), b_i \notin \mathcal{D} \tag2 si=siexp(−σiou(M,bi)2),bi∈/D(2)
其中, s i s_i si是每个实体的得分, b i b_i bi 表示每个实体, M \mathcal{M} M 表示保存队列中得分最小的实体。 D \mathcal{D} D 表示所有的实体减去保存队列中的实体。