YOLOV3非极大抑制(NMS)和Threshold实践

本文介绍了YOLOV3中非极大抑制(NMS)的实践,探讨了NMS参数如何影响目标检测结果。通过调整NMS阈值和Threshold,观察其对检测框数量和精度的影响,指出在Threshold过低时会导致错误框过多,而NMS为0则失去去重作用。同时,文章提到了YOLO层的简单分析,解释了YOLO1输出层的设计思路。

关于NMS的理论分析介绍请参考文章:

非极大值抑制(Non-Maximum Suppression,NMS)_tugouxp的专栏-CSDN博客结束https://blog.csdn.net/tugouxp/article/details/121725807这里主要针对YOLOV3后处理的实践,结合一份白嫖来的YOLOV3后处理代码,来感性的了解NMS是做什么的,怎么用。

首先看一下这份代码,在后处理参数的初始化过程中, 可以看到有对NMS参数的初始化,NMS一般设置在0.3-0.5之间,他是对IOU的一种计量,这里设置为0.45。

输入图片是416*416的,经过后处理后,得到的画框图像如下图所示:

接下来,我们将其值设置为0,最大化的关闭NMS的功能:

 重新测试:

可以看到很明显的区别。

放在一起对比:

通过这里的例子,可以比较明显的看出NMS参数的影响方式。

问题:

关于每个框的选择范围,最终的范围是几个被选框的并集么?比如最后留下三个框,每个框框了物体的一个部分,最终的范围是三个框并了的范围?

不是,从中选个最优的。

所以最后的框一开始就在候选框集合中是吧,不是几个框并成的?

是的。

以C语言实现版本为例,NMS的实现如下:

我的问题是,比如说NMS前有A,B,C,D,E,F,G几个匡,最终显示出来的,NMS后的框,是A,B,C,D,E,F,G这其中的某些个,还是A,B,C,D,E,F,G这些框的处理后的结果?
说白了,就是显示出来的框,是NMS之前的集合中的某个么?还是NMS前的匡,经过某些运算得到的?
回答:一般是这几个框中置信度最高的那个.
一般是这几个框中置信度最高的那个,像yolo的是这么做的,其他网络除非设计网络的时候是需要做类似合并处理,不然一般不会做合并,像yolo的是这么做的,其他网络除非设计网络的时候是需要做类似合并处理,不然一般不会做合并
我刚刚找到一份代码,确实想你说的那样,输出的匡是其中一个置信度比较高的直接输出,这里的判断IOU大就忽略这个匡的逻辑是什么,是不是因为如果IOU过大,就表示这可能是同一个object?IOU大,算法认为是同一个Object,保留置信度高的那个就可以了,再接着找下一个
回答:这里的nms-comparater应该出来是置信度从大到小排列的,然后从置信度大的开始跟其他比较,发展iou较大就把小的那个删掉,对,就是说iou大于阈值,就判断为同一个obj,一通循环下来,就把iou大的(太近的)框删掉只剩一个,iou小的(较远的)框保留.
OK,所以不同类别的Object也排在一起,感觉同类别的一起排是不是好一点?

回答:类别应该分开的,看下它里面每次只比较第k类,删也是删掉第k类的prob,应该说每个类别比较的时候,也没真的删det,只是把当前类别的筛选出重叠的去掉,我记得是这样,然后代码看起来也是这个逻辑,可以跟一下。

80类的YOLOV3.

Threshold修改:

修改496行和534行,得到如下检测结果,对比两幅图,threshold和NMS设置不合理的表现是不同的。

上例中,我们将threshold设置为0.001,得到了更多的错误匡,如果设置为0,该是什么样子的呢?

结果如下,已经看不出啥是啥了。

如上的改动运行了个把小时,调试发现,绝大部分时间都运行在NMS处理的过程中,出框太多了,在NMS门限不为0的情况下,需要调用NMS算法去重,大部分时间都消耗在去重上。

如果把NMS设置为0,按照如下图修改:

执行很快结束,查看后处理后的图像如下图所示,错误框太多,已经布满整个图像的像素分布了。

 原因是虽然框变多了,但是因为NMS为0,也就是即便跑NMS算法也没有去重的作用了,白白跑一遍,没有必要,所以流程上直接不走NMS去重了。

值得注意的是,nms sort判断目标同一的前提是必须是同一类物体的IOU大于阈值,不同同类的物体,即便阈值很大,也不会被抑制,比如下图,一眼就可以看出,狗和人的范围几乎相同,但是两个框还是都化了出来,因为人和狗是两类物体。

YOLO层简单分析:

首先看YOLO1,输出前它没有经过全连接层,而是直接卷积层输出,并且最后一层是1X1卷积,目的是进行通道合并,因为有255个卷积核,将前级的1024个通道变为输出的255个输出通道。

其它两个输出通道同理:

结束!

以下是使用Python实现的YOLOv1极大抑制代码: ``` def non_max_suppression(boxes, scores, threshold): """ 极大抑制NMS)算法 :param boxes: 边界框坐标,(N, 4)的numpy数组,N表示边界框数量,每个边界框用(xmin, ymin, xmax, ymax)表示 :param scores: 每个边界框的得分,(N,)的numpy数组 :param threshold: 重叠度阈值,float类型 :return: 保留的边界框的索引 """ # 获取边界框的面积 areas = (boxes[:, 2] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 1] + 1) # 根据得分降序排列 order = scores.argsort()[::-1] keep = [] # 保留的边界框索引 while order.size > 0: i = order[0] # 得分最高的边界框 keep.append(i) # 计算当前边界框与其他边界框的重叠度 xx1 = np.maximum(boxes[i, 0], boxes[order[1:], 0]) yy1 = np.maximum(boxes[i, 1], boxes[order[1:], 1]) xx2 = np.minimum(boxes[i, 2], boxes[order[1:], 2]) yy2 = np.minimum(boxes[i, 3], boxes[order[1:], 3]) w = np.maximum(0.0, xx2 - xx1 + 1) h = np.maximum(0.0, yy2 - yy1 + 1) inter = w * h overlap = inter / (areas[i] + areas[order[1:]] - inter) # 保留重叠度小于阈值的边界框 inds = np.where(overlap <= threshold)[0] order = order[inds + 1] return keep ``` 该代码接受三个参数: - boxes: 边界框坐标,(N, 4)的numpy数组,N表示边界框数量,每个边界框用(xmin, ymin, xmax, ymax)表示。 - scores: 每个边界框的得分,(N,)的numpy数组。 - threshold: 重叠度阈值,float类型。 返回值为保留的边界框的索引。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值