nms、softnms、softernms
softnms:https://arxiv.org/abs/1704.04503 代碼:http://bit.ly/2nJLNMu
softernms:https://arxiv.org/abs/1809.08545 代碼:https://github.com/yihui-he/KL-Loss
1 NMS
目標檢測的pipeline中,通過神經網絡的處理,輸出了一系列的預測框,為了保證檢測的召回率,這些預測框一般都相互重疊(多個檢測框對應同一個目標)。為了提升檢測效果,一般會使用置信度過濾+NMS進行檢測結果的后處理。
置信度過濾即人為設定置信度閾值,只保留超過閾值的檢測框。
NMS用于消除同一目標上的多個重復框,一般是針對各類目標單獨應用NMS,NMS的實現思路為:
NMS的計算復雜度為O(n2)O(n^2)O(n2),n為起始階段B中檢測框的數量。
實現代碼部分,摘抄自:https://blog.csdn.net/weixin_41665360/article/details/99818073
import numpy as npdef nms(dets, Nt):x1 = dets[:,0]y1 = dets[:,1]x2 = dets[:,2]y2 = dets[:,3]scores = dets[:,4]order = scores.argsort()[::-1]#計算面積areas = (x2 - x1 + 1)*(y2 - y1 + 1)#保留最后需要保留的邊框的索引keep = []while order.size > 0:# order[0]是目前置信度最大的,肯定保留i = order[0]keep.append(i)#計算窗口i與其他窗口的交疊的面積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:相交的面積/相并的面積ovr = inter / (areas[i] + areas[order[1:]] - inter)#inds為保留的檢測框的索引inds = np.where(ovr < thresh)[0]#+1是為了跳過當前保留的檢測框(索引0),因為計算重疊面積時的索引起點為1,x1[order[1:]]order = order[inds + 1]return keep# test if __name__ == "__main__":dets = np.array([[30, 20, 230, 200, 1],[50, 50, 260, 220, 0.9],[210, 30, 420, 5, 0.8],[430, 280, 460, 360, 0.7]])thresh = 0.35keep_dets = nms(dets, thresh)print(keep_dets)print(dets[keep_dets])NMS簡單有效,是目標檢測的標準后處理過程。但在更高的目標檢測需求下,也存在四方面的缺陷:
2 SoftNMS
softnms適合于解決密集檢測場景下因nms過程中直接刪除高度重疊目標而造成的目標漏檢的問題。如下圖所示場景:
兩匹馬的檢測框高度重疊,使用NMS時,在IOU閾值較低時,置信度更低的那匹馬身上的檢測框會被直接刪除,造成漏檢。
下面的式子中,M表示當前置信度最高的檢測框,bib_ibi?表示某個候選檢測框,NtN_tNt?表示nms的閾值。
nms的計算公式可以描述為:
因此,作者提出的解決方案是,在nms過程中,對于和高置信度目標高IOU重疊的檢測目標,不是直接刪除而是降低其置信度得分,這樣做使得這些目標在后面有機會被當作正確的檢測框得以保留,這樣就避免了目標的誤檢。
在設計目標得分降低策略時,一個指導原則是,一個檢測框和高置信度檢測框的IOU越大,其置信度的下降幅值應該越大。
所以作者首先提出了線性的置信度降低策略,即:
這樣的策略的確達到了預想目的,但缺點是在NtN_tNt?處函數不連續,會造成檢測框的置信度跳變,對檢測結果產生了較大的波動。
因此,作者又提出了連續版本的高斯置信度降低策略,即:
高斯版本的置信度下降策略,即為作者提出的soft nms。
softnms的計算復雜度和nms相同,都為O(n2)O(n^2)O(n2),可以看作是nms的泛化,而nms也可以稱作hard nms,是soft nms的二值化特例。
代碼摘抄自:https://blog.csdn.net/weixin_41665360/article/details/99818073
def py_cpu_softnms(dets, Nt=0.3, sigma=0.5, thresh=0.5, method=2):"""py_cpu_softnms:param dets: boexs 坐標矩陣 format [x1, y1, x2, y2, score]:param Nt: iou 交疊閾值:param sigma: 使用 gaussian 函數的方差:param thresh: 最后的分數閾值:param method: 使用的方法,1:線性懲罰;2:高斯懲罰;3:原始 NMS:return: 留下的 boxes 的 index"""N = dets.shape[0]# the order of boxes coordinate is [x1,y1,x2,y2]x1 = dets[:, 0]y1 = dets[:, 1]x2 = dets[:, 2]y2 = dets[:, 3]areas = (x2 - x1 + 1) * (y2 - y1 + 1)for i in range(N):# intermediate parameters for later parameters exchangetB = dets[i, :4]ts = dets[i, 4]ta = areas[i]pos = i + 1if i != N-1:maxscore = np.max(dets[:, 4][pos:])maxpos = np.argmax(dets[:, 4][pos:])else:maxscore = dets[:, 4][-1]maxpos = -1if ts < maxscore:dets[i, :] = dets[maxpos + i + 1, :]dets[maxpos + i + 1, :4] = tBdets[:, 4][i] = dets[:, 4][maxpos + i + 1]dets[:, 4][maxpos + i + 1] = tsareas[i] = areas[maxpos + i + 1]areas[maxpos + i + 1] = ta# IoU calculatexx1 = np.maximum(dets[i, 0], dets[pos:, 0])yy1 = np.maximum(dets[i, 1], dets[pos:, 1])xx2 = np.minimum(dets[i, 2], dets[pos:, 2])yy2 = np.minimum(dets[i, 3], dets[pos:, 3])w = np.maximum(0.0, xx2 - xx1 + 1)h = np.maximum(0.0, yy2 - yy1 + 1)inter = w * hovr = inter / (areas[i] + areas[pos:] - inter)# Three methods: 1.linear 2.gaussian 3.original NMSif method == 1: # linearweight = np.ones(ovr.shape)weight[ovr > Nt] = weight[ovr > Nt] - ovr[ovr > Nt]elif method == 2: # gaussianweight = np.exp(-(ovr * ovr) / sigma)else: # original NMSweight = np.ones(ovr.shape)weight[ovr > Nt] = 0dets[:, 4][pos:] = weight * dets[:, 4][pos:]# select the boxes and keep the corresponding indexesinds = np.argwhere(dets[:, 4] > thresh)keep = inds.astype(int).T[0]return keepsoftnms適合于減少密集檢測場景下因為nms造成的漏檢,但也會增加在同一個目標上有多個檢測框時的誤檢,如下圖所示:
左側是nms的結果,右側是softnms的結果。到底要不要用softnms代替nms,要根據自己的檢測場景和使用nms進行過濾的效果來決定,如果是密集檢測場景,nms過濾的結果存在很多的被遮擋目標的漏檢,那么使用softnms可以改善檢測效果。如果是非密集的檢測場景,nms的檢測效果是以誤檢為主,那么換成softnms之后的效果可能不會有提升。但終究softnms提供了一個新的思路,并且在某些特定情況下可以改善效果,其思想值得學習。
3 SofterNMS
論文《Bounding Box Regression with Uncertainty for Accurate Object Detection》,從名字中可以看出是基于bounding box回歸的方差來得到更加精確的檢測結果。之所以叫做softer nms這個名字,是因為作者在arxiv上提交的第一版論文名字叫做《Softer-NMS: Rethinking Bounding Box Regression for Accurate Object Detection》,而最新的第三個版本改為了現在的名字。
1 核心思想
在檢測的后處理過程nms中,是根據各檢測框的置信度進行排序,保留置信度較大的檢測框,抑制掉和保留框IOU較大但置信度較小的框,達到消除重復檢測的目的。這里是有一個前提,置信度較大的框定位也更加準確,實際情況真的是這樣嗎,作者認為不是的,如下圖所示:
因此,作者就提出了在模型學習的過程中,還應該學習檢測框各位置處的定位置信度,這樣才能結合檢測結果得到更加精確的檢測結果。以faster rcnn為例,如下圖所示,作者在模型訓練過程中,輸出了box std:
上圖中可以看出,模型預測了各點的定位方差之后,損失函數發生了變化,那么可以預見在模型預測過程中,推理過程也會發生變化。下面分別介紹這兩部分內容。
1.1 模型預測值及理論基礎
作者以Faster RCNN和Mask RCNN這樣的兩階段檢測網絡為例,模型的預測值不再是anchor box相對于真實框的中心點偏移及寬高變換系數,而是改成直接預測anchor box與真實框四個頂點位置(x1,y1,x2,y2)(x_1,y_1,x_2,y_2)(x1?,y1?,x2?,y2?)直接的偏差值。如下圖所示:
為了估計每個點的定位的準確度,作者認為每個預測框的坐標滿足高斯分布:
xex_exe?表示估計的點的位置,σ\sigmaσ表示估計值的標準差(確定程度),σ?>0\sigma -> 0σ?>0時,表示模型特別確信自己的預測結果。
作者認為每個真實框的分布符合狄拉克delta分布,及標準差為0的高斯分布的極限:
xgx_gxg?為真實框的位置。
狄拉克delta分布:
下面內容來自于:https://blog.csdn.net/lanchunhui/article/details/54293415
也就是說狄拉克delta分布在真實位置處概率值為無窮大,其余位置處概率為0。
本文主要是應用狄拉克delta分布為標準差為0的高斯分布的極限這一性質,因為預測框的位置符合高斯分布,所以如果預測框的分布和真實框的分布越接近,表示模型對目標的定位越準確。但如何衡量兩個分布的接近程度呢,答案就是KL散度。
1.2 KL loss
結合上面的分析,可以看到,模型訓練的目的是在訓練集上最小化PΘ(x)P_{\Theta}(x)PΘ?(x)和PD(x)P_D(x)PD?(x)之間的KL散度。最優參數為:
保持模型的分類損失不變,修改回歸損失為兩個分布的KL散度,即:
模型訓練的目的是,如果位置xex_exe?估計的不準確,我們期望的是此時網絡預測的定位標準差σ2\sigma^2σ2比較大,那么LregL_{reg}Lreg?應該比較大(論文中說LregL_{reg}Lreg?應該比較小,這是我自己理解錯誤嗎?預測值和真實值差距大的時候,兩個分布的差異比較大,KL散度不是應該更大嗎?)由于log?(2π)2\frac{\log(2 \pi)}{2}2log(2π)?和H(PD(x))H(P_D(x))H(PD?(x))和估計的參數Θ\ThetaΘ無關,因此有:
當σ=1\sigma = 1σ=1時,KL損失變為標準的歐式損失:
KL損失對于定位的估計值xex_exe?和定位標準差σ\sigmaσ都是可微分的,有:
由于σ\sigmaσ位于分母上,因此可能會在訓練的早期發生梯度爆炸。為了避免發生梯度爆炸,作者定義網絡的預測值為α=log?(σ2)\alpha = \log(\sigma^2)α=log(σ2),因此有:
此時有:
?Lreg?α=?12(xg?xe)2e?α+12=12(1?(xg?xe)2e?α)\frac{\partial L_{reg}}{\partial \alpha} = -\frac{1}{2}(x_g -x_e)^2e^{- \alpha}+\frac{1}{2} \\= \frac{1}{2}(1 - (x_g - x_e)^2e^{- \alpha})?α?Lreg??=?21?(xg??xe?)2e?α+21?=21?(1?(xg??xe?)2e?α)
改變預測值為α\alphaα之后,只要模型對于α\alphaα的預測值不為無窮大,就不會造成梯度爆炸。
由于在公式9所示的損失函數中,定義的是二階函數,因此作者模擬L1、L2和smoothL1的關系,定義了smooth版本的KL loss:
{e?α2(xg?xe)2+12α,∣xg?xe∣<1e?α(∣xg?xe∣?12)+12α,∣xg?xe∣≥1\begin{cases} \frac{e^{- \alpha}}{2}(x_g - x_e)^2 + \frac{1}{2} \alpha ,& |x_g - x_e| < 1 \\ e^{- \alpha}(|x_g - x_e| - \frac{1}{2})+ \frac{1}{2} \alpha,& |x_g - x_e| \geq 1 \end{cases}{2e?α?(xg??xe?)2+21?α,e?α(∣xg??xe?∣?21?)+21?α,?∣xg??xe?∣<1∣xg??xe?∣≥1?
作者對進行α\alphaα預測的FC層使用高斯初始化,均值為0,標準差為0.0001,所以在訓練的初期,KL損失等價于標準的smooth L1損失。
1.3 variance vote
在使用作者定義的網絡完成預測后,可以使用相鄰預測框學習的標準差進行加強來得到精確的目標位置,這就是本節所述的variance vote。
如下圖所示,可以把variance vote添加到NMS或soft-NMS的迭代過程中。
加權過程中,也是首先選取score值最大的檢測框b,得到其預測信息{x1,y1,x2,y2,s,σx1,σy1,σx2,σy2}\{x_1,y_1,x_2,y_2,s,\sigma_{x_1},\sigma_{y_1},\sigma_{x_2},\sigma_{y_2}\}{x1?,y1?,x2?,y2?,s,σx1??,σy1??,σx2??,σy2??},目標的預測框的位置是通過該框及其相鄰框的加權得到的。加權系數的計算受到了soft nms的啟發,某個預測框和置信度最大的框之間的IOU越大或該預測框各點處的預測不確定度越小,該預測框對于最終目標位置的貢獻越大。即定義公式如下:
σt\sigma_tσt?是自定義的超參數。
作者設計的加權規則,沒有使用分類的置信度,而是使用IOU和預測的不確定度,下圖給出了variance voting的結果。
2 實驗
消融研究證明了KL loss和var voting的效果,并且softer nms可以和soft nms結合進一步改善檢測效果。
推理時間的增加很少。
σt\sigma_tσt?和AP的映射關系,作者在實驗中設置σt=0.02\sigma_t = 0.02σt?=0.02。
對比其他nms變種,證明了本文的KL loss + variance voting + soft nms的優越性。
總結
以上是生活随笔為你收集整理的nms、softnms、softernms的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS开发工具
- 下一篇: Unity游戏开发中ECS思想介绍