天天看點

one-stage-anchor-free CenterNet:Objects as Points

paper:https://arxiv.org/pdf/1904.07850.pdf

官方代碼:https://github.com/xingyizhou/CenterNet

我的代碼:https://github.com/panchengl/centernet_prune   

首先提一下我的代碼複現(torch),官方代碼支援包括2d目标檢測、3d檢測、姿态估計任務,我移除了其他的任務,并簡單的重構了代碼,使得代碼更加易讀,然後基于我改後的代碼完成了模型壓縮(剪枝方案),并添加使用了VOC的測試方法(ap50),然後在自己的資料集(複雜場景上)上完成了測試,模型壓縮力度還是比較大,而且精度損失很小,有興趣的同學可以基于我的代碼進行二次開發。

總體印象:

    我認為結構最優雅的anchor-free算法,沒有太多的tricks,效果卻很驚豔,可能也是由于模型的原理特點,在誤檢方面控制得很好,速度跑起來飛快,而且在結構上擴充性好,各種backbone、deformconv、其實都可以随便加,主要精髓就在于特征提取+points回歸,并且可以應用到其他任務,相當優秀了,就是落地有點麻煩(至晶片端),後處理不太好做,隻能将後處理重寫,将其封裝在onnx裡面,據我所知,有晶片廠商是已經支援該算法的了。

文章解決的問題:

    1、cornernet、extremenet檢測關鍵點,但是需要一個grouping的階段,降低速度,且會導緻一個比對錯誤等類型的誤檢

    作者依次提出了直接檢測每個目标的中心點來處理,避免grouping,端到端,速度快,不需要nms(但是作者源碼是使用了nms的(可選),多尺度檢測的時候必須要使用)。

文章思路(側重于2d檢測的分析):

    構模組化型時,使用backbone來擷取目标的熱力圖,找到目标的中心點(關鍵點),熱力圖峰值點即為關鍵點,并根據中心點,回歸出中心點到邊界的距離(寬高資訊),連fpn的多級預測都沒有使用,2d回歸的是中心點到兩個邊界的距離,3dbbox檢測回歸bbox尺寸和深度資訊、朝向,人體姿态估計回歸中心點到關節點的偏移量。

方法創新點:

    1、關鍵點-中心點可以看成是一個形狀未知的anchor,但沒有尺寸框,沒有手動設定的門檻值做分類,如下圖所示。

    2、每個目标僅有一個正的中心點,不會用到nms,直接提取關鍵點特征圖的局部峰值點,且訓練樣本可以認為positive examples多。

    3、使用更大的分辨率輸出特征圖,但總體而言隻下采樣了4倍,無需用到多級預測關鍵點

one-stage-anchor-free CenterNet:Objects as Points

文章思路-Preliminary-如何預測關鍵點:

    令

one-stage-anchor-free CenterNet:Objects as Points

為輸入圖像,目标是生成關鍵點熱力圖

one-stage-anchor-free CenterNet:Objects as Points

,其中W、H是輸入圖像的寬和高,R是輸出stride(尺寸縮放比例)

,C是關鍵點類型數(特征圖的通道數),其中,C根據任務不一緻定義不同,2d目标檢測為類别數,人體姿态估計為17-人體關節點數。預設下采樣為4,由于大分辨率,下采樣比例小,認為可以不需要多級預測,也不需要nms。

one-stage-anchor-free CenterNet:Objects as Points

表示檢測到的關鍵點,

one-stage-anchor-free CenterNet:Objects as Points

表示背景。使用了多個backbone來預測圖像的得到 

one-stage-anchor-free CenterNet:Objects as Points

,包括dla34、resnet+dcn、hourglass

    對于GT的關鍵點c,其位置為

one-stage-anchor-free CenterNet:Objects as Points

,計算得到低分辨率上對應的關鍵點

one-stage-anchor-free CenterNet:Objects as Points

,然後我們利用高斯核

one-stage-anchor-free CenterNet:Objects as Points

,将關鍵點離散到熱力圖

one-stage-anchor-free CenterNet:Objects as Points

上,其中

one-stage-anchor-free CenterNet:Objects as Points

是目标尺度自适應的标準方差。如果對于同類别c有兩個高斯函數發生重疊,我們選擇元素級最大的,訓練時的目标函數如下,使用像素級别的focal-loss:

one-stage-anchor-free CenterNet:Objects as Points

    由于圖像下采樣時,GT的關鍵點會因為資料是離散的而發生偏差,是以我們對每個中心點附加預測了局部偏移

one-stage-anchor-free CenterNet:Objects as Points

,所有類别c共享同一個局部偏移,這個偏移使用L1 loss來訓練,如下式:

one-stage-anchor-free CenterNet:Objects as Points

    隻在關鍵點

one-stage-anchor-free CenterNet:Objects as Points

做監督性學習。

    難點1:

     将關鍵點利用高斯核離散:code中考慮了3種情況對高斯核進行離散,具體可以參考github的issues,我記得有一個issues是作者回複的,親自提到了這個問題,其實主要内容如下。

     參考該博文:https://zhuanlan.zhihu.com/p/165313457

                           https://zhuanlan.zhihu.com/p/76378871 (該文章認為中心點直接離散成圓合适,應該離散成橢圓,我認為有一定的道理,但是據說效果反而沒那麼好。。。。。)                        

     簡單了解一下文章的意思(如果懶得看大佬的文章就直接看我這一段簡介就好):

        首先,centernet用了很多cornernet的祖傳代碼(這個詞有點秀啊), 是以如何計算高斯半徑也是用cornernet的方式。我們回頭看看cornernet的計算方式,如下圖左圖所示,紅色的是标注框,但綠色的其實也可以作為最終的檢測結果保留下來。那麼這個問題  可以轉化為綠框在紅框多大範圍以内可以被接受。使用IOU來衡量紅框和綠框的貼合程度,當兩者IOU>0.7的時候,認為綠框也可以被接受,反之則不被接受。

one-stage-anchor-free CenterNet:Objects as Points
one-stage-anchor-free CenterNet:Objects as Points

    那如何确定半徑r, 讓紅框和綠框的IOU大于0.7?如上圖右圖所示,有三種情況,其中藍框代表标注框,橙色代表可能滿足要求的框。這個問題最終變為了一個一進制二次方程有解的問題,同時由于半徑必須為正數,是以r的取值就可以通過求根公式獲得。是以出現了gaussian_radius函數用來擷取高斯半徑(issue:https://github.com/princeton-vl/CornerNet/issues/110)。

     同樣,centernet也是用該函數擷取高斯半徑,也是求根公式,隻不過高斯點在中心,是以同樣适用,據我引用的大佬文章所說,cornernet和centernet還有bug,寫錯了公式,如果修改以後召回率還會提升一點。。。

    code中利用gaussian_radius(如何擷取高斯半徑)和draw_msra_gaussian(如何将高斯分布分散到heatmap上)兩個函數來create heatmap,簡單來說,就是根據目标尺寸算一個自适應的高斯核半徑,然後全圖構造heatmap。

文章思路-Objects as Points:

    1、如何利用關鍵點來做目标檢測

     令

one-stage-anchor-free CenterNet:Objects as Points

 是目标 k (其類别為 

one-stage-anchor-free CenterNet:Objects as Points

  )的bbox. 其中心位置為 

one-stage-anchor-free CenterNet:Objects as Points
one-stage-anchor-free CenterNet:Objects as Points

,我們用 關鍵點估計 

one-stage-anchor-free CenterNet:Objects as Points

來得到所有的中心點,此外,為每個目标 k 回歸出目标的尺寸 

one-stage-anchor-free CenterNet:Objects as Points

 。為了減少計算負擔,我們為每個目标種類使用單一的尺寸預測  

one-stage-anchor-free CenterNet:Objects as Points

 ,我們在中心點位置添加了 L1 loss:

one-stage-anchor-free CenterNet:Objects as Points

    我們不将scale進行歸一化,直接使用原始像素坐标。為了調節該loss的影響,将其乘了個系數,整個訓練的目标loss函數為:

one-stage-anchor-free CenterNet:Objects as Points

    整個網絡輸出C+4個值(即關鍵點類别C+偏移量x,y+尺寸w,h),所有輸出共享一個全卷積的backbone, 這裡提一點偏移損失的計算:作者code中使用的是原始目标中心點減去取整後的中心點,算得的值為off的gt(如果了解有錯歡迎指出),原始代碼如下:

one-stage-anchor-free CenterNet:Objects as Points

   但是這個偏移這一點是可選的,有沒有作者認為關系不大,精度損失一點點。

        2、 從點到bbox:

        在推理的時候,我們分别提取熱力圖上每個類别的峰值點。如何得到這些峰值點呢?做法是将熱力圖上的所有響應點與其連接配接的8個臨近點進行比較,如果該點響應值大于或等于其八個臨近點值則保留,最後我們保留所有滿足之前要求的前100個峰值點。令 

one-stage-anchor-free CenterNet:Objects as Points

 是檢測到的 c 類别的 n 個中心點的集合。

one-stage-anchor-free CenterNet:Objects as Points

 每個關鍵點以整型坐标 

one-stage-anchor-free CenterNet:Objects as Points

的形式給出。

one-stage-anchor-free CenterNet:Objects as Points

作為測量得到的檢測置信度, 産生如下的bbox:

one-stage-anchor-free CenterNet:Objects as Points

其中

one-stage-anchor-free CenterNet:Objects as Points

是偏移預測結果;

one-stage-anchor-free CenterNet:Objects as Points

是尺度預測結果;所有的輸出都直接從關鍵點估計得到,無需基于IOU的NMS或者其他後處理。

3D檢測和人體姿态估計(略)

實驗結果          結果如下表所示:

one-stage-anchor-free CenterNet:Objects as Points

    有個現象可能需要引起注意,我利用centernet在做自己的資料集訓練和測試時,出現了3點與文章有差異的地方:

    1、dla34的backbone與官方(paper:Deep Layer Aggregation )的dla34結構不一緻,做了進一步的特征融合,但源碼中也提供了官方結構的code,但paper沒有測試,我也沒有訓練和測試過,改進的dla34的結構效果很好。

    2、改進的dla34效果比resnet、houglass104效果更好?-在我自己的資料集上-這一點可能是超參數的問題,也有可能跟資料場景有關系,但我更懷疑是資料場景的差異

    3、文中dla34的速度号稱在2080Ti上可以做到超實時,我當時估算了一下在paper說的20ms左右,但實際測試差不多需要50ms,原因是複雜的後處理,paper極有可能說的是gpu端的前向推理時間(這個時間确實隻需要20ms左右),此點也有可能是我測試錯誤

    接下來給出paper官方提供的對網絡改動描述(适應于centernet隻輸出一層feature-map的熱圖)

    1、houglass

        堆疊的Hourglass網絡通過兩個連續的hourglass 子產品對輸入進行了4倍的下采樣,每個hourglass 子產品是個對稱的5層 下和上卷積網絡,且帶有skip連接配接。該網絡較大,但通常會生成最好的關鍵點估計。

    2、resnet

     對标準的ResNet做了3個up-convolutional網絡來得到更高的分辨率輸出(最終stride為4)。為了節省計算量,我們改變這3個up-convolutional的輸出通道數分别為256,128,64。up-convolutional核初始為雙線性插值。

    3、DLA

    即Deep Layer Aggregation (DLA),是帶多級跳躍連接配接的圖像分類網絡,我們采用全卷積上采樣版的DLA,用deformable卷積來跳躍連接配接低層和輸出層;将原來上采樣層的卷積都替換成3x3的deformable卷積。在每個輸出head前加了一個3x3x256的卷積,然後做1x1卷積得到期望輸出(與原始paper是不一緻的,這個地方我看了兩周的代碼,賊坑)。

參考:

https://zhuanlan.zhihu.com/p/66048276

繼續閱讀