NMS
非最大值抑制算法,誕生至少50年了。
在經典的兩階段目標檢測算法中,為了提高對于目標的召回率,在anchor階段會生成密密麻麻的anchor框。
所以在后處理的時候,會存在著很多冗余框對應著同一個目標。
因此NMS就是后處理中去除冗余框的必不可少的步驟。
NMS算法的具體流程: 輸入 boxes,scores, iou_threshold
step-1:將所有檢出的output_bbox按cls score劃分(如pascal voc分20個類,也即將output_bbox按照其對應的cls score劃分為21個集合,1個bg類,背景類直接剔除);
step-2:在每個類集合內根據各個bbox的cls score做降序排列,得到一個降序的list_k;
step-3:對所有的list_k進行遍歷,如有20個類,就得對這20個list都進行遍歷。從list_k中top1 cls score開始,計算該bbox_x與list中其他bbox_y的IoU,若IoU大于閾值T ,則剔除該bbox_y,最終保留bbox_x,從list_k中取出,保存在output_k中最后作為結果輸出;
step-4:繼續選擇list_k中top1 cls score,重復step-3中的迭代操作,直至list_k中所有bbox都完成篩選;
step-5:對每個集合的list_k,重復step-3、4中的迭代操作,直至所有list_k都完成篩選;
import torch
from torch
import Tensor
from typing
import Tuple
from . _box_convert
import _box_cxcywh_to_xyxy
, _box_xyxy_to_cxcywh
, _box_xywh_to_xyxy
, _box_xyxy_to_xywh
import torchvision
from torchvision
. extension
import _assert_has_ops
[ docs
] def nms
( boxes
: Tensor
, scores
: Tensor
, iou_threshold
: float ) - > Tensor
: """Performs non-maximum suppression (NMS) on the boxes accordingto their intersection-over-union (IoU).NMS iteratively removes lower scoring boxes which have anIoU greater than iou_threshold with another (higher scoring)box.If multiple boxes have the exact same score and satisfy the IoUcriterion with respect to a reference box, the selected box isnot guaranteed to be the same between CPU and GPU. This is similarto the behavior of argsort in PyTorch when repeated values are present.Args:boxes (Tensor[N, 4])): boxes to perform NMS on. Theyare expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and``0 <= y1 < y2``.scores (Tensor[N]): scores for each one of the boxesiou_threshold (float): discards all overlapping boxes with IoU > iou_thresholdReturns:keep (Tensor): int64 tensor with the indicesof the elements that have been keptby NMS, sorted in decreasing order of scores""" _assert_has_ops
( ) return torch
. ops
. torchvision
. nms
( boxes
, scores
, iou_threshold
)
NMS存在的一些問題
物體重疊:如下面第一張圖,會有一個最高分數的框,如果使用nms的話就會把其他置信度稍低,但是表示另一個物體的預測框刪掉(由于和最高置信度的框overlap過大)
存在一些,所有的bbox都預測不準,不是所有的框都那么精準,有時甚至會出現某個物體周圍的所有框都標出來了,但是都不準的情況
傳統的NMS方法是基于分類分數的,只有最高分數的預測框能留下來,但是大多數情況下IoU和分類分數不是強相關,很多分類標簽置信度高的框都位置都不是很準
Soft NMS
Improving Object Detection With One Line of Code
論文發表于 ICCV 2017
http://arxiv.org/abs/1704.04503
傳統NMS的不足之處:
為了盡可能較小的增加假陽性率,臨近檢測的分數應該被抑制,同時要保證其得分在所有檢測結果中明顯高于假陽性樣本; 在使用較低的NMS閾值來去除臨近檢測冗余的時候效果是sub-optimal,當使用高閾值的時候又會產生漏檢率; 當使用比較高的NMS閾值的時候,在測量有重疊閾值范圍內的mAP效果會下降;
引入soft NMS的核心就是不會直接通過一個NMS閾值去去除冗余檢測,而是對于高度冗余的檢測結果通過懲罰函數進行抑制,使得其得分下降;
IOU冗余的越厲害,其得分下降的越厲害;
論文中描述了兩種懲罰函數,一種線性函數,一種高斯函數
線性函數,最簡單的 就是 f = 1- iou() 高斯函數
懲罰函數的自變量是冗余樣本與最大得分樣本之間的IOU。
Soft-NMS也是一種貪婪算法,沒有找到檢測盒的全局最優重新評分。 檢測盒的重新評分是以貪婪的方式進行的,因此那些具有較高局部評分的檢測不會被抑制。
在soft NMS流程的最后也是有一個閾值,對于列表中所有檢測結果的置信度低于閾值的檢測結果 進行淘汰;
它僅需要對傳統的NMS算法進行簡單的改動且不增額外的參數。該Soft-NMS算法在標準數據集PASCAL VOC2007(較R-FCN和Faster-RCNN提升1.7%)和MS-COCO(較R-FCN提升1.3%,較Faster-RCNN提升1.1%)上均有提升。 Soft-NMS具有與傳統NMS相同的算法復雜度,使用高效。 Soft-NMS不需要額外的訓練,并易于實現,它可以輕松的被集成到任何物體檢測流程中。
優點:
1、Soft-NMS可以很方便地引入到object detection算法中,不需要重新訓練原有的模型、代碼容易實現,不增加計算量(計算量相比整個object detection算法可忽略)。并且很容易集成到目前所有使用NMS的目標檢測算法。
2、soft-NMS在訓練中采用傳統的NMS方法,僅在推斷代碼中實現soft-NMS。 作者應該做過對比試驗,在訓練過程中采用soft-NMS沒有顯著提高。
3、NMS是Soft-NMS特殊形式,當得分重置函數采用二值化函數時,Soft-NMS和NMS是相同的。soft-NMS算法是一種更加通用的非最大抑制算法。
缺點:
soft-NMS也是一種貪心算法,并不能保證找到全局最優的檢測框分數重置。除了以上這兩種分數重置函數,我們也可以考慮開發其他包含更多參數的分數重置函數,比如Gompertz函數等。但是它們在完成分數重置的過程中增加了額外的參數。
soft NMS的pytorch代碼實現
在Pytorch版本的Faster RCNN當中,roi_head.py文件中執行了nms處理,
所以我要做的是基于pytorch官方實現的nms函數的參數構建復現soft_nms函數。
def area_of ( left_top
, right_bottom
) : """Compute the areas of rectangles given two corners.Args:left_top (N, 2): left top corner.right_bottom (N, 2): right bottom corner.Returns:area (N): return the area.return types: torch.Tensor""" hw
= torch
. clamp
( right_bottom
- left_top
, min = 0.0 ) return hw
[ . . . , 0 ] * hw
[ . . . , 1 ]
def iou_of ( boxes0
, boxes1
, eps
= 1e - 5 ) : """Return intersection-over-union (Jaccard index) of boxes.Args:boxes0 (N, 4): ground truth boxes.boxes1 (N or 1, 4): predicted boxes.eps: a small number to avoid 0 as denominator.Returns:iou (N): IoU values.""" overlap_left_top
= torch
. max ( boxes0
[ . . . , : 2 ] , boxes1
[ . . . , : 2 ] ) overlap_right_bottom
= torch
. min ( boxes0
[ . . . , 2 : ] , boxes1
[ . . . , 2 : ] ) overlap_area
= area_of
( overlap_left_top
, overlap_right_bottom
) area0
= area_of
( boxes0
[ . . . , : 2 ] , boxes0
[ . . . , 2 : ] ) area1
= area_of
( boxes1
[ . . . , : 2 ] , boxes1
[ . . . , 2 : ] ) return overlap_area
/ ( area0
+ area1
- overlap_area
)
def soft_nms ( boxes
, scores
, score_threshold
= 0.001 , sigma
= 0.5 , top_k
= - 1 ) : """Soft NMS implementation.References:https://arxiv.org/abs/1704.04503https://github.com/facebookresearch/Detectron/blob/master/detectron/utils/cython_nms.pyxArgs:pytorch 官方實現的nms當中傳入的是boxes:Tensor[N,4] scores:Tensor[N], N表示的是每張圖片所有檢測框的數量box_scores (N, 5): boxes in corner-form and probabilities.score_threshold: boxes with scores less than value are not considered.sigma: the parameter in score re-computation.scores[i] = scores[i] * exp(-(iou_i)^2 / simga)top_k: keep top_k results. If k <= 0, keep all the results.Returns:keep : Tensor 1維的tensor 保存的是boxes中保留下來的框的序號 比如 [2,1,0]int64 tensor with the indicesof the elements that have been keptby NMS, sorted in decreasing order of scores#picked_box_scores (K, 5): results of NMS.sc""" scores
= scores
. unsqueeze
( 1 ) box_scores
= torch
. cat
( ( boxes
, scores
) , dim
= 1 ) picked_box_scores
= [ ] while box_scores
. size
( 0 ) > 0 : max_score_index
= torch
. argmax
( box_scores
[ : , 4 ] ) cur_box_prob
= box_scores
[ max_score_index
, : ] . clone
( ) picked_box_scores
. append
( cur_box_prob
) if len ( picked_box_scores
) == top_k
> 0 or box_scores
. size
( 0 ) == 1 : break cur_box
= cur_box_prob
[ : - 1 ] box_scores
[ max_score_index
, : ] = box_scores
[ - 1 , : ] box_scores
= box_scores
[ : - 1 , : ] ious
= iou_of
( cur_box
. unsqueeze
( 0 ) , box_scores
[ : , : - 1 ] ) box_scores
[ : , - 1 ] = box_scores
[ : , - 1 ] * torch
. exp
( - ( ious
* ious
) / sigma
) box_scores
= box_scores
[ box_scores
[ : , - 1 ] > score_threshold
, : ] if len ( picked_box_scores
) > 0 : end_socre
= torch
. stack
( picked_box_scores
) [ : , - 1 ] keep
= end_socre
. sort
( descending
= True ) . indices
return keep
else : return torch
. tensor
( [ ] )
softer NMS
論文:Bounding Box Regression with Uncertainty for Accurate Object Detection
地址:https://arxiv.org/abs/1809.08545
Comments: CVPR 2019
WBF
論文:Weighted Boxes Fusion: ensembling boxes for object detection models
論文 :Weighted boxes fusion: Ensembling boxes from different object detection models
地址:https://arxiv.org/abs/1910.13302
Comments: CVPR 2019、CVPR2021
NMS和Soft-NMS都排除了一些框,而WBF則使用了所有框。因此,它可以修復所有模型都預測不準確的情況。本案例如下圖所示。NMS/Soft-NMS將只留下一個不準確的框,而WBF將使用所有預測的框來融合它。
代碼已開源:https://github.com/ZFTurbo/Weighted-Boxes-Fusion
在這里插入代碼片
總結
以上是生活随笔 為你收集整理的目标检测中的NMS,soft NMS,softer NMS,Weighted Boxes Fusion 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。