為什麼SSD(Single Shot MultiBox Detector)對小目標的檢測效果不好?

最近在關注一些目標檢測的東西,SSD很快,但是在使用的時候發現對一些比較小的目標檢測效果不好,但是Faster RCNN能夠檢測出來,這是什麼原因造成的呢?


SSD is a class aware RPN with a lot of bells and whistles.

每一個feature map上面的pixel對應幾個anchor,這個網路對anchor進行訓練,以此驅動對feature進行訓練。

這是前言。

作為小物體,其所對應的anchor比較少 (gt overlap &> 0.5 的 anchor),也就是說對應feature map上的pixel難以得到充分訓練。讀者可以腦補每一個大的ROI可能覆蓋很多 anchor,那麼這些 anchor 均有機會得到訓練。然而一個小物體並不能覆蓋很多 anchor。

沒有得到充分訓練有什麼問題?在test的時候這個pixel的預測結果可能就是亂的,會極大幹擾正常結果。

為什麼SSD的data augmentation能漲這麼多點,就是因為通過randomly crop,讓每一個anchor都得到充分訓練(也就是說,crop出一個小物體,在新圖裡面就變成大物體了)

只能說這種without region propisal的結果 naturally 不擅長小物體。通過往上堆 hack 才能慢慢比上吧。


我試過SSD最前面的卷積為深度殘差網路,檢測小物體效果還不錯,比YOLO要好得多。

另外SSD原論文中,多級別的物體基本尺寸從0.1到0.8,實際上0.1的比例還是很大的,如1024*1024的輸入,0.1都到102了,其實不小。

可以根據需求調整級別,我使用的為1/64~1,即不同級別格子本身大小。

當然,級別從線性分割變成指數分割後,在基本大小之上的各個變形也需要調整一下(主要是變大),不然有可能覆蓋不到有些位於兩個格子中間的某些大小的物體。

YOLO比較坑的地方在於倒數第二層為全連接,後面的7*7格子不能擴張太大,不然前面的全連接要爆。格子大了,同一個格子可能會包括多個小物體,檢測就不好搞了。

而YOLO全連接的作用又是整合全局信息,要去掉全連接,就需要增加最後點的感受野,所以深度殘差就非常適合。

提到深度殘差,再說另外一點。

在深度殘差的作者kaiming大神另一篇文章R-FCN: Object Detection via Region-based Fully Convolutional Networks,中有使用空間pooling,發現深度殘差就是天然的自帶空間pooling效果的結構啊。

-------更新-------

補充一點,SSD前面的CNN結構,一定要是全對稱的,特別是pooling的時候,這樣最後輸出點的感受野中心才與每個格子的中心是重合的。

如果是非對稱的,CNN前面特徵提取的時候,它會糾結,造成大量的小物體不好學習。

而YOLO最後有全連接都還好,問題不大。

如下圖,一種不好的pooling方式:

一種相對較好的pooling方式:


SSD是一種基於全卷積的網路的檢測器,用不同層檢測不同大小的物體。這中間有個矛盾,前面的featmap大,但semantic不夠,後面的sematic夠了,但經過太多的pooling,featmap太小了。

要檢測小物體,既需要一張足夠大的featmap來提供更加精細的特徵和做更加密集的採樣,同時也需要足夠的semantic meaning來與背景區分開。

參會時問過SSD的作者,如果將最後的featmap放大接上前面的話,是不是能夠改善性能,作者說值得一試。

不過最近讀paper,發現已經有這樣的工作了。建議大家可以關注FPN(https://arxiv.org/abs/1612.03144)。非常非常非常豪華的作者列表+相當相當相當solid的實驗。


SSD中最小尺度的檢測是conv4_3的feature map再經過一層卷積輸出的,位於整個網路非常靠前的位置。


yolo和ssd確實對小物體很無力,而有些普通的圖像演算法對小物體檢測反而好的多,只是不太魯棒。

可以嘗試下R-FCN,我測試了幾張,好像對小物體還可以,但是速度慢些。在970下0.18s一張的樣子


1. CNN特徵的解析度較差,這點不比其它low-level的特徵;證據就是在pedestrian detection上, 一些hand-crafted特徵的效果還是不錯的.

2. Faster-rcnn和SSD本身的問題。原始的Faster-rnn在RPN中將input的最短邊固定resize到600&>SSD500&>SSD300,SSD使用300和500的原因是為了提高detection speed,所以SSD才這樣快;同時為保證精度,SSD才加上了multi-scale和data augmentation(尤其值得注意這個augmentation).

3. 其實說了這麼多,根本上還是特徵質量不行...

(截止2016.8.16)

既然樓主談到的是small sized objects,只需要看bottle這一列就好了。

上圖中,SSD512已經比Faster RCNN baseline還高了(我在這裡默認VOC=07++12);而leaderboard中的top3都已經超過了70%,雖然還不清楚PVANet的做法,但顯然其它兩個都使用了更優秀的特徵...而且本質上small sized objects對於人來說也很難,所以這一類物體比較低也是可以理解的吧

-----------------------------------------------------------

所以我的結論是:好的特徵能夠秒一切...


SSD使用的VGG16作為特徵抽取,在conv4_3feature map的解析度已經縮小了8倍,在conv5_3縮小了16倍.比如一個32*32大小的物體,在vgg16 的 conv5_3的feature map 對應僅為2*2. 位置信息有較大的損失.

目前大概有兩種方法可能決絕這個問題:

1. 使用不同層的特徵: 比如hyperNet, MultiPath.

2. 保證感受也不縮小的情況下feature map的解析度不至於縮小太多.這種思路可以考慮採用DeepLab中採用的Hole algorithm.在保證感受野的同時分辨變化較小.


我理解的SSD,每一個用於定位的卷積層都有 K*(C+4)個3x3的filters (其中k是anchor的個數,C是類型數目),我的理解是這個卷積操作相當於RPN中的sliding window,預測K種anchor在每個feature map cell上的loc和conf。然後卷積操作得到的feature拉成長向量,最後將所有層的特徵concatenate起來做回歸和分類。

如果是這樣的話,那麼小物體在低層次feature map ( e.g. conv_4-3)的響應更顯著,小物體的檢測主要靠低層的特徵(聯想:SSD訓練之前首先要做一個ground truth的匹配,比如樣本貓狗圖像,較小的貓的ground truth只是出現在底層,高層沒有貓的ground truth,而較大物體狗匹配到的ground truth在高層feature map上),其他層的信息只是簡單拼接(所以小物體檢測的語義信息,contex信息差一些)。

歡迎大家交流指正 :D

###

Dec.16,2016 Modified

針對評論提問每個預測分支中3x3卷積的作用,我用train模型的可視化圖來說明:例如從fc7(實際是一個卷積層)的feature map引出的loc分支,fc7_mbox_loc是一個卷積層,有6x4=24個3x3卷積核。其中,6是anchor的種類,4是回歸預測的4個坐標(的offset),即每個cell都分別給6種anchor box預測4個坐標。得到24個feature map後再flatten拉長,最後把所有層的特徵都拼接起來,求置信度conf的分支也類似,最後mbox_loc和mbox_conf送到整體損失層mbox_loss。


主要的原因是,SSD/YOLO 對原圖做了縮放,因為感受野的原因,導致「相對尺寸小」目標檢測困難。如果說RCNN系列,並沒有對原圖進行縮放,但是如果」絕對尺寸小「的話,也沒有辦法,因為到了一定深度的Feature map,小目標可能已經丟失response了。

因此小目標要看是絕對小目標(像素),和相對小目標(相對原圖的長寬來看的)。


SSD里負責檢測小目標的層為conv4_3(38*38)對應的尺度為0.2(可人為設置)。這就對應了SSD所能檢測的尺度大概為0.2上下。在這種情況下,如果物體過於小的話,甚至在訓練階段,GT都沒法找到相應的的default box與它匹配,效果怎麼可能會好。如果不介意整體檢測效果的話,可以把尺度調低,看看對於小目標的檢測效果是否有提升。另外,利用多尺度進行檢測也能提高小物體的檢測效果。


1 小目標往往更依賴淺層特徵,因為淺層特徵有更高的解析度,然而對語義區分較差。

2 ssd檢測和分類一起做,會把一些檢測到但是分類模糊,分數不高的結果過濾掉。而rpn不會,前200個候選繼續分類,都會有個結果。

3 為了速度,本來是全卷積網路,卻也固定了輸入尺寸。對大圖的小目標影響很大


SSD對於高解析度的底層特徵沒有再利用,而這些層對於檢測小目標很重要。 Feature Pyramid Networks for Object Detection,就很好的解決這個問題。


可以參考一篇「finding tiny faces」的思路, 為小物體添加更多context. 能夠提升對小物體的置信


最近剛好仔細看了一邊SSD的源代碼,說下我的理解。首先,小目標像素少特徵不明顯,因此和大目標相比,小目標的檢測率低,這個用任何演算法上都是無法避免的。那不同演算法之間的小目標檢測的區別呢?按照之前的答友所說的,SSD,YOLO等單階段多尺度演算法,小目標檢測需要較高的解析度,因此主要在底部的特徵層進行檢測,比如SSD中的conv4_3,但底部特徵層的語義信息不夠豐富,這是一個矛盾,但卷積層加足夠深的話影響其實沒這麼大。我覺得最重要的因素還是因為scale設置的不好導致的,SSD中默認最低一層的anchor為10%~20%,對於720p的圖像最小檢測尺寸就有72個像素,還是太大了。事實上SSD的源碼允許一個特徵層做多個尺度的滑窗,將參數min_sizes里的每個元素初始化為一個列表,就可以在相應特徵層中生成不同尺度的anchor,如果你設計的足夠仔細,基本就可以覆蓋足夠小的目標了,不過此時anchor的數量估計會漲不少,速度也會降下來。


PVANet論文已經出來了。。果然做了網路結構的改變 http://arxiv.org/pdf/1608.08021v1.pdf


faster rcnn,yolo,ssd對小目標檢測結果都不好,原因在於卷積網路結構的最後一層feature map太小,例如32*32的目標經過vgg後變成2*2,導致之後的檢測和回歸無法滿足要求


推薦閱讀:

自知視野不夠開闊,目前的平台也不高,如何確定擅長做什麼?找到什麼樣的目標?
如何評價Google最新的論文NASNet?
有圖像標註工具推薦或者分享嗎?
計算機視覺技術的車輛「檢測」與「識別」是怎麼做的?
谷歌開放的TensorFlow Object Detection API 效果如何?對業界有什麼影響?

TAG:計算機視覺 | 目標檢測 | 深度學習DeepLearning |