關註上方「深度學習技術前沿」,選擇「星標公眾號」,
技術乾貨,第一時間送達!
【導讀】本篇博文我們一起來討論總結一下目標檢測任務中用來處理目標多尺度的一些算法。視覺任務中處理目標多尺度主要分為兩大類:圖像金字塔:經典的基於簡單矩形特徵(Haar)+級聯Adaboost與Hog特徵+SVM的DPM目標識別框架,均使用圖像金字塔的方式處理多尺度目標,早期的CNN目標識別框架同樣採用該方式,在image pyramid中,我們直接對圖像進行不同尺度的縮放,然後將這些圖像直接輸入到detector中去進行檢測。雖然這樣的方法十分簡單,但其效果仍然是最佳。特別地,隨著圖像金字塔尺度歸一化(SNIP)的出現,解決了小目標和大目標在小尺度和大尺度下難以識別的問題。而且SNIP在COCO數據集上,AP最高可以達到48.3%,並且贏得了COCO2017挑戰賽的「Best Student Entry」。基於SNIP後續便衍生出了一系列基於圖像金字塔的多尺度處理。
特徵金字塔:最具代表性的工作便是經典的FPN了,FPN網絡通過將不同層的優勢結合,使得每一層相比原來都有更豐富的語義特徵和解析度信息。這一類方法的思想是直接在feature層面上來近似image pyramid。
目標檢測中存在不同目標實例之間的尺度跨度非常大,在多尺度的物體中,大尺度的物體由於面積大、特徵豐富,通常來講較為容易檢測。難度較大的主要是小尺度的物體,而這部分小物體在實際工程中卻佔據了較大的比例。通常認為絕對尺寸小於32×32的物體,可以視為小物體或者物體寬高是原圖寬高的1/10以下,可以視為小物體。
小物體由於其尺寸較小,可利用的特徵有限,這使得其檢測較為困難。當前的檢測算法對於小物體並不友好,體現在以下4個方面:
多尺度的檢測能力實際上體現了尺度的不變性,當前的卷積網絡能夠檢測多種尺度的物體,很大程度上是由於其本身具有超強的擬合能力。
較為通用的提升多尺度檢測的經典方法有:
降低下採樣率與空洞卷積可以顯著提升小物體的檢測性能;
設計更好的Anchor可以有效提升Proposal的質量;
多尺度的訓練可以近似構建出圖像金字塔,增加樣本的多樣性;
特徵融合可以構建出特徵金字塔,將淺層與深層特徵的優勢互補。
接下來,我們主要將主要介紹U-shape/V-shape型多尺度處理、SNIP、TridentNet、FPN這四大多尺度解決方法。
這種方式有點類似U-Net的結構,通過採用對稱的encoder-decoder結構,將高層特徵逐漸與低層特徵融合,這樣的操作類似於將多個感受野進行混合,使得輸出的多尺度信息更為豐富;Face++團隊在2018年COCO比賽上,在backbone最後加入gpooling操作,獲得理論上最大的感受野,類似於V-shape結構,結果證明確實有效。該方法雖然比SSD的單層輸出多尺度信息相比更好,但其也存在問題:
該論文的主要貢獻在於:
(1)通過實驗驗證了upsampling對提高小目標檢測的效果
(2)提出了一種Scale Normalization for Image Pyramids的方法
(3)提出一個思想:即要讓輸入的分布接近預訓練模型的分布
SNIP的網絡結構如下圖所示:
具體的設計和實現細節:
(1)3個尺度分別擁有各自的RPN模塊,並且各自預測指定範圍內的物體。最後不同分支的proposal進行匯總。
(2)由於圖像金字塔的應用,對於大尺度(高解析度)的feature map,對應的RPN只負責預測被放大的小目標;對於小尺度(低解析度)的feature map,對應的RPN只負責預測被縮小的大目標。這樣真實的物體尺度分布在較小的區間內,避免了極大或者極小的物體。
(3)在RPN階段,如果真實物體不在該RPN預測範圍內,會被判定為無效,並且與該無效物體的IoU大於0.3的Anchor也被判定為無效的Anchor。
(4)在訓練時,只對有效的Proposal進行反向傳播。在測試階段,對有效的預測Boxes先縮放到原圖尺度,利用Soft NMS將不同解析度的預測結果合併。
(5)實現時SNIP採用了可變形卷積的卷積方式,並且為了降低對於GPU的佔用,將原圖隨機裁剪為1000×1000大小的圖像。
總體來說,SNIP是多尺度訓練(Multi-Scale Training)的改進版本。SNIP讓模型更專注於物體本身的檢測,剝離了多尺度的學習難題。在網絡搭建時,SNIP也使用了類似於MST的多尺度訓練方法,構建了3個尺度的圖像金字塔。MST的思想是使用隨機採樣的多解析度圖像使檢測器具有尺度不變特性。然而作者通過實驗發現,在MST中,對於極大目標和過小目標的檢測效果並不好,但是MST也有一些優點,比如對一張圖片會有幾種不同解析度,每個目標在訓練時都會有幾個不同的尺寸,那麼總有一個尺寸在指定的尺寸範圍內。SNIP的做法是只對size在指定範圍內的目標回傳損失,即訓練過程實際上只是針對某些特定目標進行,這樣就能減少domain-shift帶來的影響。
總結一下,TridentNet主要在原始的backbone上做了以下三點變化:
論文中還做了非常詳盡的ablation analyses,包括有幾個branch性能最好;trident block應該加在網絡的哪個stage;trident block加多少個性能會飽和。這些就不展開在這裡介紹了,有興趣的讀者可以參照原文。
FPN將深層信息上採樣,與淺層信息逐元素地相加,從而構建了尺寸不同的特徵金字塔結構,性能優越,FPN如今已成為Detecton算法的標準組件,不管是one-stage(RetinaNet、DSSD)、two-stage(Faster R-CNN、Mask R-CNN)還是four-stage(Cascade R-CNN)都可用;
如下圖所示,FPN把低解析度、高語義信息的高層特徵和高解析度、低語義信息的低層特徵進行自上而下的側邊連接,使得所有尺度下的特徵都有豐富的語義信息。
算法結構可以分為三個部分:自下而上的卷積神經網絡(上圖左),自上而下過程(上圖右)和特徵與特徵之間的側邊連接。
自下而上:最左側為卷積神經網絡的前向過程,這裡默認使用ResNet結構,用作提取語義信息。在前向過程中,特徵圖的大小在經過某些層後會改變,而在經過其他一些層的時候不會改變,作者將不改變特徵圖大小的層歸為一個階段,因此每次抽取的特徵都是每個階段的最後一個層的輸出,這樣就能構成特徵金字塔。具體來說,對於ResNets,作者使用了每個階段的最後一個殘差結構的特徵激活輸出。將這些殘差模塊輸出表示為{C2, C3, C4, C5},對應於conv2,conv3,conv4和conv5的輸出。
FPN對於不同大小的RoI,使用不同的特徵圖,大尺度的RoI在深層的特徵圖上進行提取,小尺度的RoI在淺層的特徵圖上進行提取。FPN的代碼實現如下:
# Build the shared convolutional layers.
# Bottom-up Layers
# Returns a list of the last layers of each stage, 5 in total.
# 扔掉了C1
_, C2, C3, C4, C5 = resnet_graph(input_image, "resnet101", stage5=True)
# Top-down Layers
# TODO: add assert to varify feature map sizes match what's in config
P5 = KL.Conv2D(256, (1, 1), name='fpn_c5p5')(C5) # C5卷積一下就當做P5
P4 = KL.Add(name="fpn_p4add")([ # P4 開始有了對應元素add操作
KL.UpSampling2D(size=(2, 2), name="fpn_p5upsampled")(P5),
KL.Conv2D(256, (1, 1), name='fpn_c4p4')(C4)])
P3 = KL.Add(name="fpn_p3add")([
KL.UpSampling2D(size=(2, 2), name="fpn_p4upsampled")(P4),
KL.Conv2D(256, (1, 1), name='fpn_c3p3')(C3)])
P2 = KL.Add(name="fpn_p2add")([
KL.UpSampling2D(size=(2, 2), name="fpn_p3upsampled")(P3),
KL.Conv2D(256, (1, 1), name='fpn_c2p2')(C2)])
# Attach 3x3 conv to all P layers to get the final feature maps.
P2 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p2")(P2)
P3 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p3")(P3)
P4 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p4")(P4)
P5 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p5")(P5)
# P6 is used for the 5th anchor scale in RPN. Generated by
# subsampling from P5 with stride of 2.
# P6是P5的極大值池化
P6 = KL.MaxPooling2D(pool_size=(1, 1), strides=2, name="fpn_p6")(P5)
# Note that P6 is used in RPN, but not in the classifier heads.
rpn_feature_maps = [P2, P3, P4, P5, P6]
mrcnn_feature_maps = [P2, P3, P4, P5]
優缺點分析:
底層feature map位置信息多但語義信息少,FPN為其增強了語義信息,提升了對小物體的檢測效果;
提升檢測精度,包括加強對小物體的檢測效果和對大物體的檢測效果。一般來說,頂層feature map是檢測大物體的關鍵,因為容易框出大物體;底層feature map是檢測小物體的關鍵,因為容易框出小物體;
FPN只是給底層featue map提供了福利,所以僅僅提升了對小物體的檢測效果;
頂層feature map語義信息多但位置信息少,還是對檢測大物體不利。後來者PAN在FPN的基礎上再加了一個bottom-up方向的增強,使得頂層feature map也可以享受到底層帶來的豐富的位置信息,從而把大物體的檢測效果也提上去了。
參考連結:
https://zhuanlan.zhihu.com/p/70523190
https://zhuanlan.zhihu.com/p/54334986
https://zhuanlan.zhihu.com/p/74415602
https://zhuanlan.zhihu.com/p/61536443
https://blog.csdn.net/weixin_40683960/article/details/79055537
重磅!DLer-目標檢測交流群已成立!
為了能給大家提供一個更好的交流學習平臺!針對特定研究方向,我建立了目標檢測微信交流群,目前群裡已有百餘人!本群旨在交流目標檢測、密集人群檢測、關鍵點檢測、人臉檢測、人體姿態估計等內容。
進群請備註:研究方向+地點+學校/公司+暱稱(如目標檢測+上海+上交+小明)
👆 長按識別添加,邀請您進群!
原創不易,在看鼓勵!比心喲!