详解非极大值抑制算法之Python实现


Posted in Python onJune 28, 2021

一、概述

这里不讨论通用的NMS算法(参考论文《Efficient Non-Maximum Suppression》对1维和2维数据的NMS实现),而是用于目标检测中提取分数最高的窗口的。例如在行人检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到NMS来选取那些邻域里分数最高(是行人的概率最大),并且抑制那些分数低的窗口。

NMS在计算机视觉领域有着非常重要的应用,如视频目标跟踪、数据挖掘、3D重建、目标识别以及纹理分析等。

二、NMS 在目标检测中的应用

2.1、人脸检测框重叠例子

详解非极大值抑制算法之Python实现

我们的目的就是要去除冗余的检测框,保留最好的一个.

有多种方式可以解决这个问题,Triggs et al. 建议使用Mean-Shift 算法,利用bbox的坐标和当前图片尺度的对数来检测bbox的多种模式.但效果可能并不如使用强分类器结合NMS的效果好.

2.2、目标检测 pipline

详解非极大值抑制算法之Python实现

产生proposal后使用分类网络给出每个框的每类置信度,使用回归网络修正位置,最终应用NMS.

三、NMS 原理

对于Bounding Box的列表B及其对应的置信度S,采用下面的计算方式.选择具有最大score的检测框M,将其从B集合中移除并加入到最终的检测结果D中.通常将B中剩余检测框中与M的IoU大于阈值Nt的框从B中移除.重复这个过程,直到B为空.

3.1、重叠率(重叠区域面积比例IOU)阈值

常用的阈值是 0.3 ~ 0.5.

其中用到排序,可以按照右下角的坐标排序或者面积排序,也可以是通过SVM等分类器得到的得分或概率,R-CNN中就是按得分进行的排序.

详解非极大值抑制算法之Python实现

就像上面的图片一样,定位一个车辆,最后算法就找出了一堆的方框,我们需要判别哪些矩形框是没用的。非极大值抑制的方法是:先假设有6个矩形框,根据分类器的类别分类概率做排序,假设从小到大属于车辆的概率 分别为A、B、C、D、E、F。

(1)从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;

(2)假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。

(3)从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。

就这样一直重复,找到所有被保留下来的矩形框。

3.2、代码示例

在R-CNN中使用了NMS来确定最终的bbox,其对每个候选框送入分类器,根据分类器的类别分类概率做排序(论文中称为greedy-NMS).但其实也可以在分类之前运用简单版本的NMS来去除一些框.

python实现的单类别nms:py_cpu_nms.py.

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

Faster R-CNN的MATLAB实现与python版实现一致,代码在这里:nms.m.另外,nms_multiclass.m是多类别nms,加了一层for循环对每类进行nms而已.

四、NMS loss

值的注意的是对多类别检测任务,如果对每类分别进行NMS,那么当检测结果中包含两个被分到不同类别的目标且其IoU较大时,会得到不可接受的结果。如下图所示:

详解非极大值抑制算法之Python实现

一种改进方式便是在损失函数中加入一部分NMS损失。NMS损失可以定义为与分类损失相同:

详解非极大值抑制算法之Python实现

即真实列别u对应的log损失,p是C个类别的预测概率。实际相当于增加分类误差。
参考论文《Rotated Region Based CNN for Ship Detection》(IEEE2017会议论文)的Multi-task for NMS部分。

五、Soft-NMS

上述NMS算法的一个主要问题是当两个ground truth的目标的确重叠度很高时,NMS会将具有较低置信度的框去掉(置信度改成0),参见下图所示.

详解非极大值抑制算法之Python实现

论文:《Improving Object Detection With One Line of Code
改进之处:

详解非极大值抑制算法之Python实现

改进方法在于将置信度改为IoU的函数:f(IoU),具有较低的值而不至于从排序列表中删去.

1.线性函数

详解非极大值抑制算法之Python实现

函数值不连续,在某一点的值发生跳跃.

2.高斯函数

详解非极大值抑制算法之Python实现

时间复杂度同传统的greedy-NMS,为

详解非极大值抑制算法之Python实现

5.1、python代码实现

ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih) 
ov = iw * ih / ua #iou between max box and detection box 
if method == 1: # linear 
	if ov > Nt: 
		weight = 1 - ov 
	else: 
		weight = 1 
elif method == 2: # gaussian 
	weight = np.exp(-(ov * ov)/sigma) 
else: # original NMS 
	if ov > Nt: 
		weight = 0 
	else: 
		weight = 1 
# re-scoring 修改置信度 
# boxes[pos, 4] = weight*boxes[pos, 4]

5.2、Caffe C++ 版实现

makefile/frcnn

效果

详解非极大值抑制算法之Python实现

在基于proposal方法的模型结果上应用比较好,检测效果提升:

详解非极大值抑制算法之Python实现

在R-FCN以及Faster-RCNN模型中的测试阶段运用Soft-NMS,在MS-COCO数据集上mAP@[0.5:0.95]能够获得大约1%的提升(详见这里). 如果应用到训练阶段的proposal选取过程理论上也能获得提升. 在自己的实验中发现确实对易重叠的目标类型有提高(目标不一定真的有像素上的重叠,切斜的目标的矩形边框会有较大的重叠).
而在SSD,YOLO等非proposal方法中没有提升.

六、其它应用

边缘检测:Canny算子中的非极大值抑制是沿着梯度方向进行的,即是否为梯度方向上的极值点;

特征点检测:在角点检测等场景下说的非极大值抑制,则是检测中心点处的值是否是某一个邻域内的最大值.

以上就是详解非极大值抑制算法之Python实现的详细内容,更多关于非极大值抑制 Python实现的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python查找相似单词的方法
Mar 05 Python
使用Python脚本来获取Cisco设备信息的示例
May 04 Python
python3 与python2 异常处理的区别与联系
Jun 19 Python
python利用urllib和urllib2访问http的GET/POST详解
Sep 27 Python
Django学习笔记之ORM基础教程
Mar 27 Python
Sanic框架请求与响应实例分析
Jul 16 Python
对Python中class和instance以及self的用法详解
Jun 26 Python
django 消息框架 message使用详解
Jul 22 Python
sklearn-SVC实现与类参数详解
Dec 10 Python
tensorflow 固定部分参数训练,只训练部分参数的实例
Jan 20 Python
keras-siamese用自己的数据集实现详解
Jun 10 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
Aug 07 Python
Python实现生活常识解答机器人
Python办公自动化之教你如何用Python将任意文件转为PDF格式
Python移位密码、仿射变换解密实例代码
Pytest中conftest.py的用法
Python实现8种常用抽样方法
Python基于百度API识别并提取图片中文字
Python基于百度AI实现抓取表情包
You might like
ThinkPHP写数组插入与获取最新插入数据ID实例
2014/11/03 PHP
php管理nginx虚拟主机shell脚本实例
2014/11/19 PHP
thinkPHP多域名情况下使用memcache方式共享session数据的实现方法
2016/07/21 PHP
PHP+MySql实现一个简单的留言板
2020/07/19 PHP
jquery表单验证框架提供的身份证验证方法(示例代码)
2013/12/27 Javascript
javascript中验证大写字母、数字和中文
2014/01/15 Javascript
JS判断文本框内容改变事件的简单实例
2014/03/07 Javascript
js匿名函数的调用示例(形式多种多样)
2014/08/20 Javascript
Nodejs为什么选择javascript为载体语言
2015/01/13 NodeJs
JS实现跟随鼠标立体翻转图片的方法
2015/05/04 Javascript
jQuery实现在列表的首行添加数据
2015/05/19 Javascript
jQuery获取页面元素绝对与相对位置的方法
2015/06/10 Javascript
Nodejs初级阶段之express
2015/11/23 NodeJs
基于javascript实现句子翻牌网页版小游戏
2016/03/23 Javascript
jQuery树形插件jquery.simpleTree.js用法分析
2016/09/05 Javascript
jQuery实现自动调用和触发某个事件的方法
2016/11/18 Javascript
利用jQuery实现滑动开关按钮效果(附demo源码下载)
2017/02/07 Javascript
Vue常用的几个指令附完整案例
2018/11/06 Javascript
JQuery模拟实现网页中自定义鼠标右键菜单功能
2018/11/14 jQuery
详解Python map函数及Python map()函数的用法
2017/11/16 Python
Python 处理图片像素点的实例
2019/01/08 Python
解决Tensorflow占用GPU显存问题
2020/02/03 Python
深入浅析Python 函数注解与匿名函数
2020/02/24 Python
浅谈Python中threading join和setDaemon用法及区别说明
2020/05/02 Python
使用Python实现微信拍一拍功能的思路代码
2020/07/09 Python
利用python对mysql表做全局模糊搜索并分页实例
2020/07/12 Python
HTML利用九宫格原理进行网页布局
2020/03/13 HTML / CSS
Stylenanda中文站:韩国一线网络服装品牌
2016/12/22 全球购物
美国著名的家居用品购物网站:Bed Bath & Beyond
2018/01/05 全球购物
精神文明建设标语
2014/06/16 职场文书
中层领导干部群众路线对照检查材料思想汇报
2014/10/02 职场文书
工作岗位职责范本
2015/02/15 职场文书
2015年八一建军节活动总结
2015/03/20 职场文书
2015企业年终工作总结范文
2015/05/27 职场文书
2016年主题党日活动总结
2016/04/05 职场文书
Debian11 Xfce终端光标的颜色怎么设置?
2022/08/14 数码科技