非极大值抑制NMS
NMS(Non Maximum Suppression),即中文翻译为非极大值抑制,是目标检测算法中的后处理模块,其主要作用是删除高冗余度的bounding box。
NMS的工作机制如下图所示:
对于目标检测任务,每个目标(object)在detect时会产生很多bounding boxes,通过NMS会过滤很多冗余的boxes,得到最后与ground truth box重合度最大的唯一的bounding box。
以下为NMS实现的基本不步骤:
- 将所有检出的output bounding box按每个类别(class)的得分(score)划分,将每个类别的score作为一个集合
- 遍历每个集合,对每个集合进行如下计算
(1)在每个集合内根据各个bounding box的score做降序排列,得到一个降序的列表list
(2)选取list中第一个元素l_0,计算l_0与list中其他的元素l_i之间的IoU,若IoU大于阈值,则剔除元素l_i,否则,暂时保留。这是因为多个bounding box表示的是同一个目标,所以保留score高的那个
(3)针对列表中的每个元素,都进行上述步骤,直到所有list元素都完成筛选
NMS的python代码实现
Fast R-CNN的NMS实现
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
import numpy as np
def py_cpu_nms(dets, thresh):
"""Pure Python NMS baseline."""
x1 = dets[:, 0] # pred bbox top_x(box的左上角x坐标)
y1 = dets[:, 1] # pred bbox top_y(box的左上角y坐标)
x2 = dets[:, 2] # pred bbox bottom_x(box的右上角x坐标)
y2 = dets[:, 3] # pred bbox bottom_y(box的右上角y坐标)
scores = dets[:, 4] # pred bbox cls score(获取预测box的类别score)
areas = (x2 - x1 + 1) * (y2 - y1 + 1) # 计算预测box的面积
order = scores.argsort()[::-1] # 返回检测目标预测box的index数组,[::-1]-->按类别分数从小到大的逆序排列,即降序排列
keep = []
while order.size > 0:
i = order[0] # 获取第0个最大类别分数预测框对应的index
keep.append(i)
# 获取与类别分数对应框重合的框的位置坐标,以便计算iou
xx1 = np.maximum(x1[i], x1[order[1:]]) # 重合部分的框的左上角x坐标
yy1 = np.maximum(y1[i], y1[order[1:]]) # 重合部分的框的左上角y坐标
xx2 = np.minimum(x2[i], x2[order[1:]]) # 重合部分的框的右下角x坐标
yy2 = np.minimum(y2[i], y2[order[1:]]) # 重合部分的框的右下角y坐标
w = np.maximum(0.0, xx2 - xx1 + 1) # 获取重合部分矩形的宽
h = np.maximum(0.0, yy2 - yy1 + 1) # 获取重合部分矩形的高
inter = w * h # 计算相交部分的面积
iou = inter / (areas[i] + areas[order[1:]] - inter) # 计算iou
# 获取iou小于阈值的框的index,iou越小,重合度越大
inds = np.where(iou <= thresh)[0]
order = order[inds + 1]
return keep
``