极市导读
本文主要介绍NMS的应用场合、基本原理、多类别NMS方法和实践代码、NMS的缺陷、改进思路和改进NMS的几种常用方法,同时提供其它不常用的方法的链接。 >>加入极市CV技术交流群,走在计算机视觉的最前沿
def NMS(boxes,scores, thresholds):
x1 = boxes[:,
0]
y1 = boxes[:,
1]
x2 = boxes[:,
2]
y2 = boxes[:,
3]
areas = (x2-x1)*(y2-y1)
_,order = scores.sort(
0,descending=
True)
keep = []
while order.numel() >
0:
i = order[
0]
keep.append(i)
if order.numel() ==
1:
break
xx1 = x1[order[
1:]].clamp(min=x1[i])
yy1 = y1[order[
1:]].clamp(min=y1[i])
xx2 = x2[order[
1:]].clamp(max=x2[i])
yy2 = y2[order[
1:]].clamp(max=y2[i])
w = (xx2-xx1).clamp(min=
0)
h = (yy2-yy1).clamp(min=
0)
inter = w*h
ovr = inter/(areas[i] + areas[order[
1:]] - inter)
ids = (ovr<=thresholds).nonzero().squeeze()
if ids.numel() ==
0:
break
order = order[ids+
1]
return torch.LongTensor(keep)
torchvision.ops.nms(boxes, scores, iou_threshold)
#实现源码
max_coordinate = boxes.max()
offsets = idxs.to(boxes) * (max_coordinate + torch.tensor(
1).to(boxes))
boxes_for_nms = boxes + offsets[:,
None]
keep = nms(boxes_for_nms, scores, iou_threshold)
return keep
#使用方法
torchvision.ops.boxes.batched_nms(boxes, scores, classes, nms_thresh)
c = x[:,
5:
6] * (
0
if agnostic
else max_wh)
# classes
boxes, scores = x[:, :
4] + c, x[:,
4]
# boxes (offset by class), score
si = torchvision.ops.nms(boxes, scores, iou_thres)
需要手动设置阈值,阈值的设置会直接影响重叠目标的检测,太大造成误检,太小达不到理想情况。
低于阈值的直接设置score为0,做法太hard。
只能在CPU上运行,成为影响速度的重要因素。
通过IoU来评估,IoU的做法对目标框尺度和距离的影响不同。
根据手动设置阈值的缺陷,通过自适应的方法在目标系数时使用小阈值,目标稠密时使用大阈值。例如Adaptive NMS。
将低于阈值的直接置为0的做法太hard,通过将其根据IoU大小来进行惩罚衰减,则变得更加soft。例如Soft NMS,Softer NMS。
只能在CPU上运行,速度太慢的改进思路有三个,一个是设计在GPU上的NMS,如CUDA NMS,一个是设计更快的NMS,如Fast NMS,最后一个是掀桌子,设计一个神经网络来实现NMS,如ConvNMS。
IoU的做法存在一定缺陷,改进思路是将目标尺度、距离引进IoU的考虑中。如DIoU。
公众号后台回复“项目实践”获取50+CV项目实践机会~
“
点击阅读原文进入CV社区
收获更多技术干货