⾮极⼤值抑制(Non-Maximum Suppression)原理
⾮极⼤值抑制,顾名思义,找出极⼤值,抑制⾮极⼤值。这种思路和算法在各个领域中应⽤⼴泛,⽐如边缘检测算法canny算⼦中就使⽤了该⽅法。本⽂主要讨论nms在⽬标检测中的应⽤。⽬标检测过程中,模型在同⼀⽬标的位置上经常会产⽣⼤量的候选框,如下图是赫本的⼈脸检测结果。可以看出这些候选框之间的重叠度⾮常⾼,此时就需要利⽤nms找到最佳⽬标,消除冗余的边界框。
奥黛丽赫本-⼈脸检测示意图
nms的原理很简单,主要分为如下⼏步:
- 将候选框按照置信度进⾏排序
- 计算置信度最⾼的候选框与其它候选框的IoU(交并⽐)
- 删除IoU⼤于设定阈值的候选框
- 重复上述过程,直⾄候选框列表为空
这里的IoU指的是Intersection over Union,代表候选区域之间的交并比,计算如下图所示。
IOU计算示意图
python代码解析
nms的开源代码很多,初学者往往被各种复杂代码⾥花式的写法迷惑,但其实nms的代码很好写,完全不需要很复杂的数据结构及算法,这⾥笔者用numpy尽量写了⼀个最精简、最易读的版本,⼀共30⾏,供⼤家参考。
def nms_rect(box, iou): keep_ = [] if len(box) > 1: x1 = box[:, 0] y1 = box[:, 1] x2 = box[:, 2] y2 = box[:, 3] score = box[:, 4] area = (y2 - y1 + 1) * (x2 - x1 + 1) while len(score) > 1: order = score.argsort()[::-1] i = order[0] 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:]]) w = np.maximum(0., xx2 - xx1) h = np.maximum(0., yy2 - yy1) inter = w * h ovr = inter / (area[i] + area[order[1:]] - inter) inds = np.where(ovr > iou) + np.array([1]) inds = np.append(inds, 0) keep_.append([x1[i], y1[i], x2[i], y2[i], score[i]]) x1 = np.delete(x1, order[inds]) y1 = np.delete(y1, order[inds]) x2 = np.delete(x2, order[inds]) y2 = np.delete(y2, order[inds]) area = np.delete(area, order[inds]) score = np.delete(score, order[inds]) return keep_
结果展示
从左到右依次是原图、nms处理前、nms处理后,可以看出效果很明显。
nms效果图
写在最后
nms是算法研究⼈员⼗分常⽤的算法,笔者在⼯作⾯试中也经常会出这道题,因此还是很有必要掌握的,接下来的⽂章也会持续分享⼯作期间总结的论⽂、笔记和代码。欢迎关注与转发。

3174

被折叠的 条评论
为什么被折叠?



