題圖無關

。接上篇感受野相關,介紹Anchor相關:

目標檢測之anchor

anchor字面意思是錨,指固定船的東東,anchor在計算機視覺中有錨點或錨框,目標檢測中常出現的anchor box是錨框,表示固定的參考框。

目標檢測是

"在哪裡有什麼"

的任務,在這個任務中,目標的類別不確定、數量不確定、位置不確定、尺度不確定,傳統非深度學習方法如VJ和DPM,和早期深度學習方法如OverFeat,都要金字塔多尺度+遍歷滑窗的方式,逐尺度逐位置判斷

"這個尺度的這個位置處有沒有認識的目標"

,非常笨重耗時。

近期頂尖(SOTA)的目標檢測方法幾乎都用了anchor技術。首先預設一組不同尺度不同位置的固定參考框,覆蓋幾乎所有位置和尺度,每個參考框負責檢測與其交併比大於閾值 (

訓練預設值,常用0。5或0。7

) 的目標,anchor技術將問題轉換為

"這個固定參考框中有沒有認識的目標,目標框偏離參考框多遠"

,不再需要多尺度遍歷滑窗,真正實現了又好又快,如在Faster R-CNN和SSD兩大主流目標檢測框架及擴充套件演算法中anchor都是重要部分。

當然也有不用anchor的檢測演算法:2016 ECCV的YOLO是全域性迴歸,但很快在YOLOv2就替換為anchor方法;2018 ECCV的CornerNet是角點預測,但論文用了非常龐大的hourglass-104速度比較慢,關鍵點與anchor技術沒有明確的公平對比,孰優孰劣尚不清楚。

接下來以2015年NIPS的Faster R-CNN和2016年ECCV的SSD兩個代表性框架分析anchor技術,並延伸到最新的FPN/Mask R-CNN/RetinaNt框架中,學習anchor的設計方法,探討一些問題。

Faster R-CNN中的Anchor

目標檢測中的Anchor

Faster R-CNN這裡僅分析與anchor有關的VGG16+RPN部分(後面簡稱RPN):主幹輸出stride16的feature map,RPN是一個conv3x3+兩個並列的conv1x1,一邊預測anchor中是否包含目標,一邊預測目標框偏離固定anchor多遠。

設定

:RPN用stride 16的單feature map進行預測,anchor為三尺度{128, 256, 512}三比例{1:1, 1:2, 2:1},feature map上每個位置設定9個參考anchor,這些大約能覆蓋邊長70~768的目標。下圖是Faster R-CNN論文中個anchor形狀訓練後學習到的平均proposal大小。

目標檢測中的Anchor

感受野

:典型1000x600輸入影象,經過conv5-3 + RPN,用於預測的feature map層解析度是63x38,計算這一層的感受野:

r

=

1

+

2

+

2

x3

x2

+

2

x3

x2

+

2

x3

x2

+

2

x2

x2

+

2

x2

=

228

<

512

分析

:Faster R-CNN最早提出了anchor概念,首先,backbone+RPN實質上是一個FCN,上一篇分析過FCN本質上是密集滑窗,所以就沒必要顯式密集滑窗了;其次,anchor的設定是多尺度的,這樣就沒必要顯式影象金字塔;最後,RPN與檢測網路共享backbone部分的計算量,能大幅提升速度;注意,輸入影象大小相比後面的SSD(512x512)更大,相當於小目標放大去檢測,效能會有提升,但這是犧牲速度換來的。

Anchor設定方面有三個問題(

從今天的演算法水平往回看,事後諸葛角度

):

最小的anchor是128x128尺度,而COCO小目標很多,且小目標很小,遠小於這個尺度,為了能檢測這些小目標,Faster R-CNN不得不放大輸入影象(~1000x600),

導致

計算速度成倍增加,而同時被放大的大目標可能超過最大anchor尺度,又不得不加入多尺度測試保證從大到小anchor全覆蓋,進一步影響速度;

最大的anchor是512x512尺度,而預測層的感受野僅228,上一篇討論過,一般來說感受野一定要大於anchor大小,而且越大越好,這裡感受野明顯不足以支撐最大尺度的anchor,

導致

大尺度目標檢測效能不夠好;

三尺度按照檢測目標的大小,我們簡稱為大、中、小錨框,那麼三個尺度的anchor分別有63x38x3=

7182

個,共計7182x3=

21546

個anchor。通常anchor需要覆蓋訓練集的所有目標,即每個groundtruth box都能匹配到一個anchor,因此理想情況下目標越小anchor應該越多越密集,才能覆蓋所有的候選區域,目標越大anchor應該越少越稀疏,否則互相高度重疊造成冗餘計算量,反觀RPN這裡的單一feature map三尺度三比例設定,

導致

檢測小目標的anchor太少太疏,而檢測大目標的anchor太多太密。論文提到Faster R-CNN訓練中忽略了所有跨邊界的anchor否則訓練無法收斂,尺度越大跨邊界越多,所以訓練中忽略掉的很多都是大錨框。

SSD中的Anchor

目標檢測中的Anchor

SSD是VGG16+conv3x3進行檢測,輸出目標分類和邊框迴歸結果,從6個stride遞增的feature map進行預測,網路結構從conv7之前是標準的VGG16結構,之後每一組conv1x1 + conv3x3s2輸出一個stride的feature map。

設定

:feature map從stride8開始共6層,每層4或6個形狀的anchor,anchor共6個尺度(0。2~0。9)x300,6個形狀是{1, 2, 3, 1/2, 1/3}比例框,外加較大的{1}比例框,依然按照大、中、小錨框進行劃分,典型300x300輸入影象:

小錨框:

從{conv4_3} feature map檢測單一小尺度{60}目標,4個anchor形狀,共38x38x4=

5776

個anchor;

中錨框:

從{conv7, conv8_2, conv9_2} feature map檢測三個中尺度{102, 144, 186}目標,6形狀anchor,共19x19x6 + 10x10x6 + 5x5x6=

2916

個anchor;

大錨框:

從{conv10_2, conv11_2}檢測兩個大尺度{228, 270}目標,4形狀anchor,共3x3x4 + 1x1x4=

40

個anchor;

目標檢測中的Anchor

感受野

:計算conv4-3+conv3x3 ~ conv11_2+conv3x3的感受野

r1 = 1 + 2 + 2x3 )x2 + 2x3 )x2 + 2x2 )x2 + 2x2 = 108 > 60

r2 = 1 + 2 + 2 + 2x3 )x2 + 2x3 )x2 + 2x3 )x2 + 2x2 )x2 + 2x2 = 260 > 102

r3 = 1 + 2 )x2+1 + 2 + 2x3 )x2 + 2x3 )x2 + 2x3 )x2 + 2x2 )x2 + 2x2 = 324 > 144

r3 = 1 + 2 )x2+1 )x2+1 + 2 + 2x3 )x2 + 2x3 )x2 + 2x3 )x2 + 2x2 )x2 + 2x2 = 452 > 186

。。。

可以看到各層的感受野都是大於anchor大小的。

分析

:6個feature map共計5776 + 2916 + 40=

8732

個anchor,總數量比RPN少了很多,而且小尺度錨框多且密,大尺度錨框少且疏,更合理;anchor的尺度範圍從60到284,輸入影象不用故意放大去檢測小目標,計算速度更快;大尺度分佈合理,不忽略跨邊界anchor訓練結果更好。

Anchor設定方面有三個問題(

繼續馬後炮角度

):

論文中提到的anchor設定沒有

對齊感受野

,通常幾個畫素的中心位置偏移,對大目標來說IOU變化不會很大,但對小目標IOU變化劇烈,尤其感受野不夠大的時候,anchor很可能偏移出感受野區域,影響效能。

目標檢測中的Anchor

2。 還是論文中提到的,anchor尺度和比例都是人工給定的,

尺度和比例必須要覆蓋相應任務的可能出現的所有目標

,如PASCAL VOC評價每圖目標數較少、目標較大,所以SSD中最小60x60的anchor或許夠用,但MS COCO中目標密集且小、數量多,對anchor的密度和最小尺度都有嚴格要求,60x60的最小框完全不夠看,只能放大輸入影象。

目標檢測中的Anchor

一種方法是針對特定資料集設計anchor,如YOLOv2中的聚類,和近期有論文CNN訓練anchor的設定,這些方法或許更適合某一資料集,但也可能影響模型的泛化能力,換一個庫是否依然夠用。另一種方法就是多尺度測試,尺度不夠,縮放來湊,常用multi-test,和SNIP等等方法,都犧牲了速度,實用性打折。

3。

深度悖論

杜撰

):SSD檢測

小目標

是從conv4-3拉出來的,共經過11個conv3x3,檢測

中目標

是從{conv7, conv8_2, conv9_2}拉出來的,分別經過{15, 16, 17}個conv3x3,檢測大目標經過的卷積層就更多了,一般經過的conv3x3越多,深度越深,感受野越大,特徵越強 (

這一說法有否正確?

)。

一般來說,目標越小,畫素數量少,清晰度低,細節丟失嚴重,檢測難度越大,反之目標越大,檢測難度越小。RPN框架檢測各尺度的特徵深度相同,但SSD框架目標越小越難的,特徵深度反而越淺,特徵越弱。

4。 繼續來看最小anchor不夠小的問題:我們能否將stride4的feature map拉出來,設定更小anchor檢測比60更小的目標呢?實際操作當然可行,我們將conv3_3的feature map上加一個檢測頭,假設anchor設定為{30},計算這一層感受野,看看能支援多小目標:

r0 = 1 + 2 + 2x3 )x2 + 2x2 )x2 + 2x2 = 48 > 30

直觀來看conv3_3可以支援這一anchor,但小目標更需要大感受野來提供上下文資訊,如果感受野太小誤檢率會非常高。

FPN中的Anchor

目標檢測中的Anchor

設定

:FPN + ResNet標配後,Faster R-CNN和SSD分別進化為Faster R-CNN+FPN/Mask R-CNN(簡寫FPN)和RetinaNet,Pn表示對應feature map的stride是

2^{n}

,尺度都是 {32, 64, 128, 256, 512}:不同點是:

FPN從 {P2, P3, P4, P5, P6} 拉出5個feature map進行檢測,每個位置預測三比例,不同尺度不同形狀的anchor共15個

RetinaNet從 {P3, P4, P5, P6, P7} 拉出5個feature map進行檢測,每個位置預測三尺度三比例,每個尺度預測9個形狀anchor

感受野

:首先忽略FPN的top-down pathway,考慮RPN中的conv3x3卷積層,直接計算ResNet-50各個feature map的感受野,{P2, P3, P4, P5}分別對應{conv2_3, conv3_4, conv4_6, conv5_3}:

P2 = 1 +2 +2x3 )x2+1 )x2+5 = 43

P3 = 1 +2 +2x3 )x2+1 +2x3 )x2+1 )x2+5 = 107

P4 = 1 +2 +2x5 )x2+1 +2x3 )x2+1 +2x3 )x2+1 )x2+5 = 299

P5 = 1 +2 +2x2 )x2+1 +2x5 )x2+1 +2x3 )x2+1 +2x3 )x2+1 )x2+5 = 491

隨著block增加,感受野也對應越多,如果考慮檢測需要上下文,stride32的感受野足夠大,但stride4的感受野不夠大。FPN中的bottom-up pathway將深度層特徵上取樣後與當前層相加,相加時感受野取最大,即相加後感受野等於深度層的感受野,FPN僅用微小計算量,實現了淺層feature map的感受野大幅提升,高效解決了“深度悖論”,目前是目標檢測的標配。

分析

:同樣尺度為32的anchor,FPN用P2進行檢測,而RetinaNet用P3進行檢測,這是因為FPN的前景閾值是0。7需要anchor更密集,RetinaNet前景閾值是0。5 anchor相對稀疏,FPN技術繼承了前面SSD的所有優點,還以極低計算量克服了淺層感受野不足的問題。

Anchor設定方面的問題(

這麼完美還有問題? 後面全是瞎說

):

小框的問題:MS COCO上資料庫上小目標的AP(S)遠低於大目標的AP(L),如下表,從anchor角度來看可能是兩方面的問題:

來自高層的feature map上取樣用了最簡單的最近鄰插值,太過於粗糙,而且高層特徵訓練用於檢測大目標,可能已經丟失了小目標相關的語義

低層自己的feature map感受野本來比較小,缺乏上下文資訊

目標檢測中的Anchor

實驗

:某直筒型檢測網路,用stride4的feature map層設定16x16的anchor檢測小目標,為了提高小目標的檢測效能,採用兩種不同方法增加感受野

stride4加深度(加2個conv3x3卷積層)

加入FPN技術,用P2層進行檢測

實現發現第一種方法對小目標檢測的提升更大,但第一種方法由於解析度較大引入了很多額外計算量,模型大小和訓練所需內測都大幅上升,相反第二種方法額外計算量非常少,在速度方面優勢非常大。

2。 大框的問題:用大stride層的feature map檢測大目標,步進等於stride,anchor數量少且疏,造成邊框迴歸的難度增加,而且感官上更容易看到大目標的檢測偏差。

為了提高高層feature map的解析度,近期很多論文都在stride16之後用空洞卷積代替下采樣block,在提高感受野的同時保持空間解析度不下降,以獲得更密集的大目標anchor,提升大目標的檢測效能。空洞卷積的理論計算量與標準卷積相同但更難最佳化,如果採用空洞卷積則通道數不用翻倍,否則速度無法接受。

Anchor設計總結

總結以上幾篇論文,設計目標檢測演算法時,anchor設定應該考慮一下幾個方面 (

以RetinaNet為例

):

anchor的密度:由檢測所用feature map的stride決定,這個值與前景閾值密切相關,如同樣檢測{32}尺度,FPN閾值0。7用P2,RetinaNet前景閾值0。5用P3。

anchor的範圍:RetinaNet中是anchor範圍是32~512,這裡應根據任務檢測目標的範圍確定,按需調整anchor範圍,或目標變化範圍太大如MS COCO,這時候應採用多尺度測試,當然,實際應用中需考慮多尺度測試的複雜度問題。

anchor的形狀數量:RetinaNet每個位置預測三尺度三比例共9個形狀的anchor,這樣可以增加anchor的密度,但stride決定這些形狀都是同樣的滑窗步進,需考慮步進會不會太大,如RetinaNet框架前景閾值是0。5時,一般anchor大小是stride的4倍左右。

檢測層Pn的數量:RetinaNet中是P3~P7共5個檢測層,如需檢測更小的目標,可以考慮加入P2檢測層。

檢測層Pn的感受野:前面計算了RetinaNet中是ResNet+FPN的感受野在檢測中、大目標時都是夠用的,檢測小目標時略顯疲乏,kaiming最新論文《Rethinking ImageNet Pre-training》既然告訴我們預訓練模型沒那麼重要時,那檢測任務就可以著重考慮按照感受野的需求設計ConvNet。

總之,要做到anchor以足夠密度實現全覆蓋。

Anchor在高效人臉檢測中的應用

對人臉檢測不熟的同學可以先看這個:

綜合近期目標檢測和人臉檢測演算法的進展,用最新高效小網路作為backbone,用ncnn進行部署,最最最重要的是前面所說的anchor相關技術,用RetinaNet框架設計的高效人臉檢測演算法,資料如下:

模型大小不到

850k

(模型引數量850k/4),在1。2G單核ARM上用ncnn部署僅用CPU資源,VGA影象檢測40x40人臉速度接近

15fps

在WIDERFACE上五尺度測試(WIDERFACE人臉範圍7~1000+,都用多尺度測試)easy/medium/hard上召回率分別是

0.91/0.89/0.82

在FDDB上單尺度測試(原始影象尺度)在100/200/500/1000/2000誤檢時的召回率分別是

0.90/0.92/0.94/0.96/0.97

RetinaNet框架的人臉檢測效能遠超MTCNN,檢測框更準確,單人臉時速度雖然比fastMTCNN略差一點點,但one-shot型別最大的優點是速度恆定,不受目標數量的影響,不像MTCNN耗時會隨著人臉數量成倍增加,證明Anchor技術可以做到又好又快。