NMS
NMS
是目标检测中常用的算法,最终网络的输出可能包括了很多预测框,其中一个目标周围会有许多候选框,如下图所示,而该算法目的是找出最佳的目标位置。
主要有两种实现方式,一种是将一张图片中的所有的预测框聚在一起进行NMS
,一种是将一张图片中所有预测框按所预测的类别分别进行NMS
(也就是以类别为外循环),但主要的思想还是不变,假设给定预测框bboxes
和scores
,维度分别为[N,4]、[N,]
,其中N为预测框的个数,该算法步骤如下:
- 先将预测框按
scores
大小降序排列,这样保证了留下的框置信度最大。 - 从第一个预测框开始,分别计算该预测框(代号为i)与剩下的预测框之间的交并比
IoU
,排除掉IoU
大于阈值(一般是0.5)的其他框,因为这些大于阈值的框就说明与当前预测框i太接近了,同时置信度也没有i大,所以需要排除掉,依次循环直至处理完所有框。
代码如下所示:
def nms(self, bboxes, scores, threshold=0.5):
x1 = bboxes[:,0]
y1 = bboxes[:,1]
x2 = bboxes[:,2]
y2 = bboxes[:,3]
areas = (x2-x1)*(y2-y1) # [N,]
_, order = scores.sort(0, descending=True) # 降序
keep = []
while order.numel() > 0: # torch.numel()返回张量元素个数
if order.numel() == 1: # 保留框只剩一个
i = order.item()
keep.append(i)
break
else:
i = order[0].item() # 保留scores最大的那个框box[i]
keep.append(i)
# 计算box[i]与其余各框的IOU
xx1 = x1[order[1:]].clamp(min=x1[i]) # [N-1,]
yy1 = y1[order[1:]].clamp