NMS非极大值抑制:用擂台赛带你从原理到代码脑洞大开恍然大悟
来源:互联网 发布:科比巅峰数据 编辑:程序博客网 时间:2024/05/18 00:11
本博记录为卤煮理解,如有疏漏,请指正。转载请注明出处。
卤煮:非文艺小燕儿
本博地址:NMS非极大值抑制:带你从原理到代码脑洞大开
楼主是在人脸识别应用时,接触到NMS的。其余目标检测同理。
简单来说就是你喂给分类器一张图片,它会给你拉出,哦不,不太雅,吐出一堆可能是人脸的候选框,每个框框还有一个得分。高分意味着这个框框里是人脸的概率大。
用下面这个图简单表示一下:
有4个框,每个框都对应一个得分。
从图上可以看出,
(1)有些框得分很低(右下),意味着这种框是人脸的概率较小,我们可以通过阈值把这种框排除。
(2)另外有些框之间有较大的重叠,比如川普脸上有2个框,而且得分都比较高。很明显可以想到,留着这么多框太冗余了,可以精简一下。
上面提到的(2),就是nms要做的工作了,简单吧。
嗯,我上面说的你们都懂,可是怎么实施呢?
OK,我们把这些框框,都看成一个个的勇士,得分的高低代表勇士的实力强弱。
我们给这些勇士提供一个NMS擂台赛。我们每次邀请一个实力最强的勇士作为擂台主,剩余的勇士可以上擂台挑战他。
少年看你骨骼清奇,我给你透漏一个秘密,下赌注的时候一定要堵擂台主赢,因为我们有个潜规则,擂台主是绝对不会输的。
由于擂台比较高,那些实力较弱的勇士,爬擂台的时候就摔死了,ORZ。。。。
能够爬上擂台的勇士,部分身上自带克制擂台主的气息,大概是上场前萝卜吃多了,导致擂台主无法近其身(IOU小于阈值),侥幸拿下平局。
你说什么是IOU?稍等,看完这场,休息的时候给你讲。
其余勇士,只能与擂台主贴身肉搏了,由于我们的潜规则,勇士英勇牺牲了。
现在擂台上,只剩下擂台主和怪味勇士了。打不起来了,肿么办呢?
好吧,都下去,休息片刻,继续下一场比赛。刚才的擂台主光荣退休。擂台属于剩下的勇士们。
下一场,将由剩下的勇士中最有实力的做擂台主,重新其余勇士的接受挑战。
当所有比赛完结,上过擂台的勇士,要么战死了,要么就是做完擂台主退休了。也就是说,现在就剩下一批牛逼哄哄的退休擂台主了。
下面说一下IOU规则。其实就是两个框重叠率。IOU=重叠面积/基准面积
基准面积有三种计算规则,
(1)Union,也就是两个框的并集所圈定的面积。
(2)Min,面积较小的框所圈定的面积。
(3)Max,面积较大的框所圈定的面积。
比如下图中,红框和蓝框有交集,交集面积很大,所以IOU就大,如果红框是擂台主,那么蓝框就被和谐牺牲了。而绿框因为没有交集,IOU都小到没有,侥幸逃过一劫。
是不是恍然大悟了,可转念一想,这代码还是不会写啊。
像我这种保姆级的楼主,必须要周全啊,翠花,上代码~!
输入的boundingBox_记录了候选框的位置信息和得分信息,BboxScore_记录了候选框的得分信息以及ID。
overlap_threshold是IOU阈值,modelname指定基准面积的计算方式。
/**********************nms非极大值抑制****************************/void mtcnn::nms(std::vector<Bbox> &boundingBox_, std::vector<orderScore> &bboxScore_, const float overlap_threshold, string modelname){ if(boundingBox_.empty()){ return; } std::vector<int> heros; //sort the score sort(bboxScore_.begin(), bboxScore_.end(), cmpScore);//cmpScore指定升序排列 int order = 0; float IOU = 0; float maxX = 0; float maxY = 0; float minX = 0; float minY = 0;//规则,站上擂台的擂台主,永远都是胜利者。 while(bboxScore_.size()>0){ order = bboxScore_.back().oriOrder;//取得分最高勇士的编号ID。 bboxScore_.pop_back();//勇士出列 if(order<0)continue;//死的?下一个!(order在(*it).oriOrder = -1;改变) heros.push_back(order);//记录擂台主ID boundingBox_.at(order).exist = false;//当前这个Bbox为擂台主,签订生死簿。 for(int num=0;num<boundingBox_.size();num++){ if(boundingBox_.at(num).exist){//活着的勇士 //the iou maxX = (boundingBox_.at(num).x1>boundingBox_.at(order).x1)?boundingBox_.at(num).x1:boundingBox_.at(order).x1; maxY = (boundingBox_.at(num).y1>boundingBox_.at(order).y1)?boundingBox_.at(num).y1:boundingBox_.at(order).y1; minX = (boundingBox_.at(num).x2<boundingBox_.at(order).x2)?boundingBox_.at(num).x2:boundingBox_.at(order).x2; minY = (boundingBox_.at(num).y2<boundingBox_.at(order).y2)?boundingBox_.at(num).y2:boundingBox_.at(order).y2; //maxX1 and maxY1 reuse maxX = ((minX-maxX+1)>0)?(minX-maxX+1):0; maxY = ((minY-maxY+1)>0)?(minY-maxY+1):0; //IOU reuse for the area of two bbox IOU = maxX * maxY; if(!modelname.compare("Union")) IOU = IOU/(boundingBox_.at(num).area + boundingBox_.at(order).area - IOU); else if(!modelname.compare("Min")){ IOU = IOU/((boundingBox_.at(num).area<boundingBox_.at(order).area)?boundingBox_.at(num).area:boundingBox_.at(order).area); } if(IOU>overlap_threshold){ boundingBox_.at(num).exist=false;//如果该对比框与擂台主的IOU够大,挑战者勇士战死 for(vector<orderScore>::iterator it=bboxScore_.begin(); it!=bboxScore_.end();it++){ if((*it).oriOrder == num) { (*it).oriOrder = -1;//勇士战死标志 break; } } }//else 那些距离擂台主比较远迎战者幸免于难,将有机会作为擂台主出现 } } } for(int i=0;i<heros.size();i++) boundingBox_.at(heros.at(i)).exist = true;//从生死簿上剔除,擂台主活下来了}
齐活~
- NMS非极大值抑制:用擂台赛带你从原理到代码脑洞大开恍然大悟
- NMS非极大值抑制的原理与代码实现
- NMS非极大值抑制
- 非极大值抑制 NMS
- 非极大值抑制NMS
- 非极大值抑制(NMS)
- 非极大值抑制(NMS)
- NMS(非极大值抑制)
- 非极大值抑制(NMS)
- 非极大值抑制算法 NMS
- 非极大值抑制原理
- NMS——非极大值抑制
- NMS——非极大值抑制
- NMS——非极大值抑制
- 非极大值抑制算法 (NMS)
- 非极大值抑制(Non-maximum suppression, NMS)
- 非极大值抑制(Non-maximum suppression, NMS)
- NMS——非极大值抑制
- [Leetcode] 374. Guess Number Higher or Lower 解题报告
- Python virtualenv虚环境的安装
- Linux网络编程——tcp并发服务器(多线程)
- 图片上传Controller代码
- 一个圆圈两个边框怎么写?
- NMS非极大值抑制:用擂台赛带你从原理到代码脑洞大开恍然大悟
- 1003. 我要通过!(20)
- Windows下Nginx的基本使用
- stm32 ADXL345传感器
- Java 访问Hbase数据库
- 接口学习
- mysql 行转列
- Bigint 重载了'='和‘+’和‘-’和‘×’和‘<<’和‘>>’
- 线上操作与线上问题排查实战