1. 程式人生 > >Faster R-CNN理解、討論

Faster R-CNN理解、討論

論文 : Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks[J]. PAMI2017.

GitHub :

    3. 補充程式Detectron : https://github.com/facebookresearch/Detectron (Detectron is Facebook AI Research's software system that implements state-of-the-art object detection algorithms, including 

Mask R-CNN. It is written in Python and powered by the Caffe2 deep learning framework.)

1. 前言

在Faster R-CNN出現之前,已經存在了R-CNN(無法實現End-to-End訓練)和Fast R-CNN(Selective Search耗時),Shaoqing Ren在2016年NIP上提出了Faster R-CNN. 從上面的結構上,我們能夠看出來,Faster R-CNN將特徵提取proposal提取Bounding Box RegressionClassification整合到一個網路中,目標檢測速度有了很大的提升。與R-CNN、Fast R-CNN相比,Faster R-CNN具體執行步驟如下:

  • 特徵提取(convolutional layer)。Faster R-CNN首先使用一組基礎的conv+relu+pooling層提取候選影象的特徵圖。該特徵圖被共享用於後續RPN(Region Proposal Network)層和全連線(fully connection)層。
  • 區域候選網路(Region Proposal Network)。RPN網路用於生成區域候選影象塊。該層通過softmax判斷錨點(anchors)屬於前景(foreground)或者背景(background),再利用邊界框迴歸(bounding box regression)修正anchors獲得精確的proposals
  • 目標區池化(Roi Pooling)。該層收集輸入的特徵圖候選的目標區域,綜合這些資訊後提取目標區域的特徵圖,送入後續全連線層判定目標類別。
  • 目標分類(Classification)。利用目標區域特徵圖計算目標區域的類別,同時再次邊界框迴歸獲得檢測框最終的精確位置。

由此,我們也能看出,Faster R-CNN最大的亮點在於提出了一種有效定位目標區域的方法,然後按區域在特徵圖上進行特徵索引,大大降低了卷積計算的時間消耗,所以速度上有了非常大的提升。

以如上GitHub中Python的專案為例,可以更加直接分析Faster R-CNN的設計思想。

  1. 對於任意PxQ的影象,首先裁剪到固定大小MxN。然後,利用VGG16全卷積模型計算該影象對應的特徵圖。
  2. 特徵圖的一個分支輸入RPN網路用於計算Region Proposal。RPN網路首先經過3x3卷積,再分別生成前景錨點(foreground anchors)邊界框迴歸(bounding box regression)偏移量,然後計算出候選的目標區域;
  3. Roi Pooling層則利用proposals從feature maps中提取proposal feature送入後續全連線和softmax網路作目標分類 和 邊界框精細迴歸。

2. 原理

2.1 卷積網路計算特徵圖

    提取影象特徵的卷積網路使用了最常見的模組,如卷積convolution、池化pooling、啟用函式ReLUctant。在使用Python實現的FasterR-CNN模型,直接採用了VGG16計算影象的特徵圖。所以卷積網路包括13個卷積層,13個啟用層,4個池化層。原文作者在進行卷子操作的時候進行了影象邊緣補充操作,並使用了3x3的卷積核。具體資訊為conv=3x3, padding=1, striide=1; Pooling=2x2, padding = 0, stride=2; 這樣做簡化了計算複雜性。也就是說3x3的卷積操作後,影象的尺寸不變; 2x2的池化操作後,影象的尺寸變為原圖的0.5x0.5。所以,一張MxN大小的影象經過VGG16計算後,特徵影象尺寸變為(M/16)x(N/16)。因此,特徵圖和原始影象就可以對應。

2.2 區域候選網路

經典的檢測方法生成檢測框都非常耗時,如OpenCV adaboost使用滑動視窗+影象金字塔生成檢測框;或如R-CNN使用SS(Selective Search)方法生成檢測框。而Faster RCNN則拋棄了傳統的滑動視窗和SS方法,直接使用RPN生成檢測框,這也是Faster R-CNN的巨大優勢,能極大提升檢測框的生成速度。

上圖就是原文作者提出的Region Proposal Network示意圖,這個網路實際分為2條線,上面的網路分支通過softmax分類anchors獲得前景和背景(實際應用過程中,我們將目標預設為前景);下面的網路分支用於計算對於anchors的邊界框迴歸的偏移量,以獲得精確的目標候選區。

跟隨的Proposal層綜合前景錨點和邊界框迴歸偏移量獲取目標的候選區,同時剔除太小和超出邊界的目標區域。所以,RPN實際就是實現了目標定位功能。

    2.2.1 anchors

    在Python實現的Faster R-CNN專案中,所謂anchors,實際上就是一組由rpn/generate_anchors.py生成的矩形。直接執行作者demo中的generate_anchors.py可以得到以下輸出:

[[ -84.  -40.   99.   55.]
 [-176.  -88.  191.  103.]
 [-360. -184.  375.  199.]
 [ -56.  -56.   71.   71.]
 [-120. -120.  135.  135.]
 [-248. -248.  263.  263.]
 [ -36.  -80.   51.   95.]
 [ -80. -168.   95.  183.]
 [-168. -344.  183.  359.]]

其中每行的4個值(x1, y1, x2, y2) 表矩形左上和右下角點座標。9個矩形共有3種形狀,長寬比為大約為with:height∈{1:1, 1:2, 2:1}三種,如下圖所示。實際上通過anchors就引入了檢測中常用到的多尺度方法

注:關於上面的anchors size,其實是根據檢測影象設定的。在python demo中,會把任意大小的輸入影象reshape成800x600。anchors中長寬1:2中最大為352x704,長寬2:1中最大736x384,基本是覆蓋了800x600的各個尺度和形狀。 那麼這9個anchors是做什麼的呢?借用Faster RCNN論文中的原圖,如下所示,遍歷卷積網路計算獲得的特徵圖,為每一個點都配備這9種anchors作為初始的檢測框。這樣做獲得檢測框很不準確,不用擔心,後面還有2次bounding box regression可以修正檢測框位置

解釋一下上面這張圖的數字。

  1. 原文中使用的是ZF model中,其Conv Layers中最後的conv5層num_output=256,對應生成256張特徵圖,所以相當於feature map每個點都是256-dimensions
  2. 在conv5之後,做了rpn_conv/3x3卷積且num_output=256,相當於每個點又融合了周圍3x3的空間資訊,同時256-d不變
  3. 假設在conv5 feature map中每個點上有k個anchor(預設k=9),而每個anhcor要分foreground和background,所以每個點由256d feature轉化為cls=2k scores;而每個anchor都有[x, y, w, h]對應4個偏移量,所以reg=4k coordinates
  4. 補充一點,全部anchors拿去訓練太多了,訓練程式會在合適的anchors中隨機選取128個postive anchors+128個negative anchors進行訓練

Comment:其實RPN最終就是在原圖尺度上,設定了密密麻麻的候選Anchor。然後用cnn去判斷哪些Anchor是裡面有目標的foreground anchor,哪些是沒目標的backgroud。所以,僅僅是個二分類而已!

那麼Anchor一共有多少個?原圖800x600,VGG下采樣16倍,feature map每個點設定9個Anchor,所以:ceil(800/16) * ceil(600/16) * 6=17100個候選框。

    2.2.2 前景錨點背景錨點分類

    一副MxN大小的矩陣送入Faster RCNN網路後,到RPN網路變為(M/16)x(N/16),不妨設 W=M/16,H=N/16。在進入reshape與softmax之前,先做了1x1卷積,如上圖所示。可以看到其num_output=18,也就是經過該卷積的輸出影象為WxHx18大小。這也就剛好對應了feature maps每一個點都有9個anchors,同時每個anchors又有可能是foreground和background,所有這些資訊都儲存WxHx(9*2)大小的矩陣。為何這樣做?後面接softmax分類獲得foreground anchors,也就相當於初步提取了檢測目標候選區域box(一般認為目標在foreground anchors中)。

    2.3 邊界框迴歸原理與實現方法

如圖所示綠色框為飛機的Ground Truth(GT),紅色為提取的foreground anchors,即便紅色的框被分類器識別為飛機,但是由於紅色的框定位不準,這張圖相當於沒有正確的檢測出飛機。所以我們希望採用一種方法對紅色的框進行微調,使得foreground anchors和GT更加接近

對於視窗一般使用四維向量 (x, y, w, h)表示,分別表示視窗的中心點座標和寬高。對於圖 11,紅色的框A代表原始的Foreground Anchors,綠色的框G代表目標的GT,我們的目標是尋找一種關係,使得輸入原始的anchor A經過對映得到一個跟真實視窗G更接近的迴歸視窗G',即:

  • 給定:anchor A=(A_{x}, A_{y}, A_{w}, A_{h}) 和 GT=[G_{x}, G_{y}, G_{w}, G_{h}]
  • 尋找一種變換F,使得:F(A_{x}, A_{y}, A_{w}, A_{h})=(G_{x}^{'}, G_{y}^{'}, G_{w}^{'}, G_{h}^{'}),其中(G_{x}^{'}, G_{y}^{'}, G_{w}^{'}, G_{h}^{'})≈(G_{x}, G_{y}, G_{w}, G_{h})

那麼經過何種變換F才能從圖10中的anchor A變為G'呢? 比較簡單的思路就是:

  • 先做平移

  • 再做縮放

    觀察上面4個公式發現,需要學習的是 d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A) 這四個變換。當輸入的anchor A與GT相差較小時,可以認為這種變換是一種線性變換, 那麼就可以用線性迴歸來建模對視窗進行微調(注意,只有當anchors A和GT比較接近時,才能使用線性迴歸模型,否則就是複雜的非線性問題了)。     接下來的問題就是如何通過線性迴歸獲得 d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A) 了。線性迴歸就是給定輸入的特徵向量X, 學習一組引數W, 使得經過線性迴歸後的值跟真實值Y非常接近,即Y=WX。對於該問題,輸入X是cnn feature map,定義為Φ;同時還有訓練傳入A與GT之間的變換量,即(t_{x}, t_{y}, t_{w}, t_{h})。輸出是d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)四個變換。那麼目標函式可以表示為:

    其中Φ(A)是對應anchor的feature map組成的特徵向量,w是需要學習的引數,d(A)是得到的預測值(*表示 x,y,w,h,也就是每一個變換對應一個上述目標函式)。為了讓預測值(t_{x}, t_{y}, t_{w}, t_{h})與真實值差距最小,設計損失函式:

函式優化目標為:

    需要說明,只有在GT與需要回歸框位置比較接近時,才可近似認為上述線性變換成立。     說完原理,對應於Faster RCNN原文,foreground anchor與ground truth之間的平移量 (t_x, t_y) 與尺度因子 (t_w, t_h) 如下:

    對於訓練bouding box regression網路迴歸分支,輸入是cnn feature Φ,監督訊號是Anchor與GT的差距 (t_x, t_y, t_w, t_h),即訓練目標是:輸入 Φ的情況下使網路輸出與監督訊號儘可能接近。 那麼當bouding box regression工作時,再輸入Φ時,迴歸網路分支的輸出就是每個Anchor的平移量和變換尺度 (t_x, t_y, t_w, t_h),顯然即可用來修正Anchor位置了。

    在瞭解bounding box regression後,再回頭來看RPN網路的邊界框迴歸部分,如上圖所示。

   2.2.3 Proposal Layer

    Proposal Layer負責綜合所有 [d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)] 變換量和foreground anchors,計算出精準的proposal,送入後續RoI Pooling Layer。

    Proposal Layer有3個輸入:fg/bg anchors分類器結果rpn_cls_prob_reshape,對應的bbox reg的變換量rpn_bbox_pred,以及im_info;另外還有引數feat_stride=16。     對於一副任意大小PxQ影象,傳入Faster RCNN前首先reshape到固定MxN,im_info=[M, N, scale_factor]則儲存了此次縮放的所有資訊。然後經過Conv Layers,經過4次pooling變為WxH=(M/16)x(N/16)大小,其中feature_stride=16則儲存了該資訊,用於計算anchor偏移量。整個流程可以解釋為:生成anchors -> softmax分類器提取fg anchors -> bbox reg迴歸fg anchors -> Proposal Layer生成proposals。

2.3. RoI pooling

    RoI Pooling層負責收集proposal,並計算出proposal feature maps,送入後續網路。Rol pooling層有2個輸入:

  1. 原始的feature maps
  2. RPN輸出的proposal boxes(大小各不相同)

2.4 分類

    分類部分利用已經獲得的proposal feature maps,通過full connection層與softmax計算每個proposal具體屬於那個類別(如人,車,電視等),輸出cls_prob概率向量;同時再次利用bounding box regression獲得每個proposal的位置偏移量bbox_pred,用於迴歸更加精確的目標檢測框。Classification部分網路結構如下圖所示。

2.5 Faster R-CNN訓練

Faster R-CNN的訓練,是在已經訓練好的model(如VGG_CNN_M_1024,VGG,ZF)的基礎上繼續進行訓練。實際中訓練過程分為6個步驟:

  1. 在已經訓練好的model上,訓練RPN網路,對應stage1_rpn_train.pt
  2. 利用步驟1中訓練好的RPN網路,收集proposals,對應rpn_test.pt
  3. 第一次訓練Fast RCNN網路,對應stage1_fast_rcnn_train.pt
  4. 第二訓練RPN網路,對應stage2_rpn_train.pt
  5. 再次利用步驟4中訓練好的RPN網路,收集proposals,對應rpn_test.pt
  6. 第二次訓練Fast RCNN網路,對應stage2_fast_rcnn_train.pt

可以看到訓練過程類似於一種“迭代”的過程,不過只迴圈了2次。至於只迴圈了2次的原因是應為作者提到:"A similar alternating training can be run for more iterations, but we have observed negligible improvements",即迴圈更多次沒有提升了。接下來本章以上述6個步驟講解訓練過程。

下面是一張訓練過程流程圖,應該更加清晰。

3. 參考資源