詳解非極大值抑制算法之Python實(shí)現(xiàn)
這里不討論通用的NMS算法(參考論文《Efficient Non-Maximum Suppression》對(duì)1維和2維數(shù)據(jù)的NMS實(shí)現(xiàn)),而是用于目標(biāo)檢測(cè)中提取分?jǐn)?shù)最高的窗口的。例如在行人檢測(cè)中,滑動(dòng)窗口經(jīng)提取特征,經(jīng)分類(lèi)器分類(lèi)識(shí)別后,每個(gè)窗口都會(huì)得到一個(gè)分?jǐn)?shù)。但是滑動(dòng)窗口會(huì)導(dǎo)致很多窗口與其他窗口存在包含或者大部分交叉的情況。這時(shí)就需要用到NMS來(lái)選取那些鄰域里分?jǐn)?shù)最高(是行人的概率最大),并且抑制那些分?jǐn)?shù)低的窗口。
NMS在計(jì)算機(jī)視覺(jué)領(lǐng)域有著非常重要的應(yīng)用,如視頻目標(biāo)跟蹤、數(shù)據(jù)挖掘、3D重建、目標(biāo)識(shí)別以及紋理分析等。
二、NMS 在目標(biāo)檢測(cè)中的應(yīng)用2.1、人臉檢測(cè)框重疊例子我們的目的就是要去除冗余的檢測(cè)框,保留最好的一個(gè).
有多種方式可以解決這個(gè)問(wèn)題,Triggs et al. 建議使用Mean-Shift 算法,利用bbox的坐標(biāo)和當(dāng)前圖片尺度的對(duì)數(shù)來(lái)檢測(cè)bbox的多種模式.但效果可能并不如使用強(qiáng)分類(lèi)器結(jié)合NMS的效果好.
2.2、目標(biāo)檢測(cè) pipline產(chǎn)生proposal后使用分類(lèi)網(wǎng)絡(luò)給出每個(gè)框的每類(lèi)置信度,使用回歸網(wǎng)絡(luò)修正位置,最終應(yīng)用NMS.
三、NMS 原理對(duì)于Bounding Box的列表B及其對(duì)應(yīng)的置信度S,采用下面的計(jì)算方式.選擇具有最大score的檢測(cè)框M,將其從B集合中移除并加入到最終的檢測(cè)結(jié)果D中.通常將B中剩余檢測(cè)框中與M的IoU大于閾值Nt的框從B中移除.重復(fù)這個(gè)過(guò)程,直到B為空.
3.1、重疊率(重疊區(qū)域面積比例IOU)閾值常用的閾值是 0.3 ~ 0.5.
其中用到排序,可以按照右下角的坐標(biāo)排序或者面積排序,也可以是通過(guò)SVM等分類(lèi)器得到的得分或概率,R-CNN中就是按得分進(jìn)行的排序.
就像上面的圖片一樣,定位一個(gè)車(chē)輛,最后算法就找出了一堆的方框,我們需要判別哪些矩形框是沒(méi)用的。非極大值抑制的方法是:先假設(shè)有6個(gè)矩形框,根據(jù)分類(lèi)器的類(lèi)別分類(lèi)概率做排序,假設(shè)從小到大屬于車(chē)輛的概率 分別為A、B、C、D、E、F。
(1)從最大概率矩形框F開(kāi)始,分別判斷A~E與F的重疊度IOU是否大于某個(gè)設(shè)定的閾值;
(2)假設(shè)B、D與F的重疊度超過(guò)閾值,那么就扔掉B、D;并標(biāo)記第一個(gè)矩形框F,是我們保留下來(lái)的。
(3)從剩下的矩形框A、C、E中,選擇概率最大的E,然后判斷E與A、C的重疊度,重疊度大于一定的閾值,那么就扔掉;并標(biāo)記E是我們保留下來(lái)的第二個(gè)矩形框。
就這樣一直重復(fù),找到所有被保留下來(lái)的矩形框。
3.2、代碼示例在R-CNN中使用了NMS來(lái)確定最終的bbox,其對(duì)每個(gè)候選框送入分類(lèi)器,根據(jù)分類(lèi)器的類(lèi)別分類(lèi)概率做排序(論文中稱(chēng)為greedy-NMS).但其實(shí)也可以在分類(lèi)之前運(yùn)用簡(jiǎn)單版本的NMS來(lái)去除一些框.
python實(shí)現(xiàn)的單類(lèi)別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] #每一個(gè)檢測(cè)框的面積 areas = (x2 - x1 + 1) * (y2 - y1 + 1) #按照score置信度降序排序 order = scores.argsort()[::-1] keep = [] #保留的結(jié)果框集合 while order.size > 0: i = order[0] keep.append(i) #保留該類(lèi)剩余box中得分最高的一個(gè) #得到相交區(qū)域,左上及右下 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:]]) #計(jì)算相交的面積,不重疊時(shí)面積為0 w = np.maximum(0.0, xx2 - xx1 + 1) h = np.maximum(0.0, yy2 - yy1 + 1) inter = w * h #計(jì)算IoU:重疊面積 /(面積1+面積2-重疊面積) ovr = inter / (areas[i] + areas[order[1:]] - inter) #保留IoU小于閾值的box inds = np.where(ovr <= thresh)[0] order = order[inds + 1] #因?yàn)閛vr數(shù)組的長(zhǎng)度比order數(shù)組少一個(gè),所以這里要將所有下標(biāo)后移一位 return keep
Faster R-CNN的MATLAB實(shí)現(xiàn)與python版實(shí)現(xiàn)一致,代碼在這里:nms.m.另外,nms_multiclass.m是多類(lèi)別nms,加了一層for循環(huán)對(duì)每類(lèi)進(jìn)行nms而已.
四、NMS loss值的注意的是對(duì)多類(lèi)別檢測(cè)任務(wù),如果對(duì)每類(lèi)分別進(jìn)行NMS,那么當(dāng)檢測(cè)結(jié)果中包含兩個(gè)被分到不同類(lèi)別的目標(biāo)且其IoU較大時(shí),會(huì)得到不可接受的結(jié)果。如下圖所示:
一種改進(jìn)方式便是在損失函數(shù)中加入一部分NMS損失。NMS損失可以定義為與分類(lèi)損失相同:
即真實(shí)列別u對(duì)應(yīng)的log損失,p是C個(gè)類(lèi)別的預(yù)測(cè)概率。實(shí)際相當(dāng)于增加分類(lèi)誤差。參考論文《Rotated Region Based CNN for Ship Detection》(IEEE2017會(huì)議論文)的Multi-task for NMS部分。
五、Soft-NMS上述NMS算法的一個(gè)主要問(wèn)題是當(dāng)兩個(gè)ground truth的目標(biāo)的確重疊度很高時(shí),NMS會(huì)將具有較低置信度的框去掉(置信度改成0),參見(jiàn)下圖所示.
論文:《Improving Object Detection With One Line of Code》改進(jìn)之處:
改進(jìn)方法在于將置信度改為IoU的函數(shù):f(IoU),具有較低的值而不至于從排序列表中刪去.
1.線性函數(shù)
函數(shù)值不連續(xù),在某一點(diǎn)的值發(fā)生跳躍.
2.高斯函數(shù)
時(shí)間復(fù)雜度同傳統(tǒng)的greedy-NMS,為
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++ 版實(shí)現(xiàn)
makefile/frcnn
效果
在基于proposal方法的模型結(jié)果上應(yīng)用比較好,檢測(cè)效果提升:
在R-FCN以及Faster-RCNN模型中的測(cè)試階段運(yùn)用Soft-NMS,在MS-COCO數(shù)據(jù)集上mAP@[0.5:0.95]能夠獲得大約1%的提升(詳見(jiàn)這里). 如果應(yīng)用到訓(xùn)練階段的proposal選取過(guò)程理論上也能獲得提升. 在自己的實(shí)驗(yàn)中發(fā)現(xiàn)確實(shí)對(duì)易重疊的目標(biāo)類(lèi)型有提高(目標(biāo)不一定真的有像素上的重疊,切斜的目標(biāo)的矩形邊框會(huì)有較大的重疊).而在SSD,YOLO等非proposal方法中沒(méi)有提升.
六、其它應(yīng)用邊緣檢測(cè):Canny算子中的非極大值抑制是沿著梯度方向進(jìn)行的,即是否為梯度方向上的極值點(diǎn);
特征點(diǎn)檢測(cè):在角點(diǎn)檢測(cè)等場(chǎng)景下說(shuō)的非極大值抑制,則是檢測(cè)中心點(diǎn)處的值是否是某一個(gè)鄰域內(nèi)的最大值.
以上就是詳解非極大值抑制算法之Python實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于非極大值抑制 Python實(shí)現(xiàn)的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. 將properties文件的配置設(shè)置為整個(gè)Web應(yīng)用的全局變量實(shí)現(xiàn)方法2. html小技巧之td,div標(biāo)簽里內(nèi)容不換行3. nestjs實(shí)現(xiàn)圖形校驗(yàn)和單點(diǎn)登錄的示例代碼4. 以PHP代碼為實(shí)例詳解RabbitMQ消息隊(duì)列中間件的6種模式5. python實(shí)現(xiàn)自動(dòng)化辦公郵件合并功能6. python開(kāi)發(fā)飛機(jī)大戰(zhàn)游戲7. laravel ajax curd 搜索登錄判斷功能的實(shí)現(xiàn)8. css進(jìn)階學(xué)習(xí) 選擇符9. Echarts通過(guò)dataset數(shù)據(jù)集實(shí)現(xiàn)創(chuàng)建單軸散點(diǎn)圖10. Python 如何將integer轉(zhuǎn)化為羅馬數(shù)(3999以?xún)?nèi))
