1. NMS的基本原理
Anchor-based网络的输出:pred_box[N, 7],pred_score[N, 1],其中
N
=
H
∗
W
∗
1
N = H * W * 1
N=H∗W∗1(
H
∗
W
H*W
H∗W网络输出特征图的长和宽,1为每个位置的pred_box),这里以单个类别举例
- 首先根据设定的分类阈值进行pred的过滤(通常为0.1)
- 假定过滤之后得到7个预测框,将这7个框按照score从大到小排序得到A、B、C、D、E、F、G
- 从分类概率最大的预测框A开始,分别判断B~G与A的IOU是否大于某个设定的阈值,如果大于阈值,则将其看做是回归A预测框对应的物体;反之,将其看做是回归的其他物体
- 假定B、C、D高于阈值,E、F、G低于阈值,则将B、C、D扔掉,保留E、F、G。(A、B、C、D四个预测框回归的是同一个物体
o
b
j
e
c
t
1
object1
o
b
j
e
c
t
1
object1
- 接下来,继续对E、F、G做NMS。从当前分类概率最大的预测框E开始,分别判断F~G与E的IOU是否大于某个设定的阈值,如果大于阈值,则将其看做是回归E预测框对应的物体;反之,将其看做是回归的其他物体
- 假定F高于阈值,G低于阈值,则将F扔掉,保留G。(E、F四个预测框回归的是同一个物体
o
b
j
e
c
t
2
object2
o
b
j
e
c
t
2
object2
- 目前只剩最后一个预测框G,对应另一个物体
o
b
j
e
c
t
3
object3
【至此,通过NMS的方法,可以判断出网络预测出了3个物体,并在NMS方法中根据分类score最大的原则挑选出了这三个物体的预测框】
2. NMS的python代码实现
def py_cpu_nms(dets, thresh):
"""Pure Python NMS baseline."""
#x1、y1、x2、y2、以及score赋值
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
#每一个检测框的面积
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
#按照score置信度降序排序
order = scores.argsort()[::-1]
keep = [] #保留的结果框集合
while order.size > 0:
i = order[0]
keep.append(i) #保留该类剩余box中得分最高的一个
#得到相交区域,左上及右下
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:]])
#计算相交的面积,不重叠时面积为0
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
#计算IoU:重叠面积 /(面积1+面积2-重叠面积)
ovr = inter / (areas[i] + areas[order[1:]] - inter)
#保留IoU小于阈值的box
inds = np.where(ovr <= thresh)[0]
order = order[inds + 1] #因为ovr数组的长度比order数组少一个,所以这里要将所有下标后移一位
return keep
3. 多类别NMS
在但类别NMS的基础之后,增加一层
f
o
r
for
for循环对每个类别进行NMS即可
4. NMS Loss
参考文章:Rotated Region Based CNN for Ship Detection
5. Soft-NMS
参考文章:Improving Object Detection With One Line of Code
版权声明:本文为CSDN博主「Amoni_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46297585/article/details/121900946
暂无评论