Faster R-CNN(RPN)


  最先進的目標檢測網絡依賴於區域生成算法來假設目標位置。先前的SPPnet和Fast R-CNN都已經減少了檢測網絡的運行時間,但也暴露出區域建議計算是個瓶頸。這篇文章,引出一個區域生成網絡(RPN)和檢測網絡共享全圖的卷積特征,因此使得區域建議幾乎沒有任何開銷。RPN是一個在每一個位置同時預測目標邊界和目標分數的全卷積網絡。通過端到端的訓練RPN來生成高質量的區域建議來提供給Fast R-CNN作檢測使用。通過簡單的交替優化,RPN和Fast R-CNN可以共享特征訓練。

區域建議網絡

  RPN輸入一個任意尺寸的圖像,並且輸出一組矩形目標建議,每一個都帶有一個目標分數。對這個過程使用全卷積網絡進行建模。因為最終的目標是和Fast R-CNN目標檢測網絡共享計算,所有假設兩個網絡都共享一組普通的卷積層。實驗中,調研了ZF(5層共享卷積)和VGG模型(13層共享卷積)。

  為了生成區域建議,在最后的共享卷積層的卷積特征圖輸出上滑動一個小網絡。這個網絡被完全連接(注意,不是全連接)到輸入卷積特征圖的$n×n$空間窗口上。每個滑動窗口映射成一個低維的向量(256-d for ZF and 512-d for VGG)(這里的意思是,使用256或512個卷積核生成與被卷積特征圖同樣大的特征圖,只不過深度為256或者512)。這個向量被送到兩個同胞全連接層——邊框回歸層(reg)和邊框分類層(cls)。這里使用$n=3$,注意到輸入圖像的有效接受域是很大的(對於ZF和VGG來說分別是171和228)。在單個位置上解釋迷你版的網絡(圖1左)。注意因為迷你網絡以一種滑窗的方式操作,所以跨越所有空間位置。這個結構自然而然地通過一個$n×n$的卷積層實現,其后還跟着兩個同胞般的1x1卷積層(分別用於回歸和分類)。$n×n$卷積層的輸出使用ReLU。

圖1:左:區域建議網絡(RPN)。右:在PASCAL VOC 2007測試上用RPN建議的樣本檢測。該方法可以在大范圍的尺度和縱橫比上檢測目標。

Translation-Invariant Anchors

  在每一個滑窗位置,同時預測$k$個區域建議,因此$reg$層有$4k$個輸出編碼$k$個邊框坐標。$cls$層輸出$2k$個分數來估計每個建議的目標/非目標的概率。$k$個建議相對於$k$個稱為錨點的參考框參數化。每個錨點在滑窗的中心,並且與尺度和縱橫比相關。這里使用3個尺度和3個縱橫比,在每個滑動位置上生成$k=9$個錨點。對於一個尺寸為$W×H$的卷積特征圖(約2400),總共有$W×H×k$個錨點。這個方法的一個重要屬性是,就錨點和與錨點相關的計算建議框函數而言,具有平移不變性。

  相比而言,MultiBox method使用k-means來生成800個錨點,那不具有平移不變性。如果在一張圖像中平移一個目標,則建議框也應該平移,並且同樣能在每個位置上預測建議框。此外,因為MultiBox錨點不具有平移不變性,所有它要求一個(4+1)×800維的輸出層,而這篇論文的方法是一個(4+2)×9維的輸出層。這里的建議層有一個數量級的參數減少(使用GoogLeNet 的MultiBox有27百萬,而使用VGG-16的RPN有2.4百萬),因此在想PASCAL VOC這樣的小數據集上有更少擬合的風險。

A Loss Function for Learning Region Proposals

  對於訓練RPN來說,為每一個錨點分配一個二元類標簽(是目標或不是)。為兩種錨點分配一個正標簽:(i)與真值框有最高IoU的錨點,(ii)與任何真值框有超過0.7的IoU。注意一個真值框可以將正標簽分配給多個錨點。如果錨點與所有真值框的IoU比例小於0.3,則賦給它一個負標簽。既不是正或也不是負的錨點沒有給訓練目標做任何貢獻。

  根據這些定義,參照Fast R-CNN中的多任務損失最小化目標函數。一張圖像的損失函數定義為:

$L(\{p_{i}\},\{t_{i}\})=\frac{1}{N_{cls}}\sum_{i}L_{cls}(p_{i},p_{i}^*)+λ\frac{1}{N_{reg}}\sum_{i}p_{i}^*L_{reg}(t_{i},t_{i}^*)$.  (1)

  這里的$i$在一個批量中一個錨點的索引,$p_{i}$是錨點$i$是一個目標的概率。如果錨點是正的,標簽$p_{i}^{*}$是1,如果是負的則為0。$t_{i}$是代表邊框坐標4個參數的向量,$t_{i}^{*}$是與正錨點相關的真值。$p_{i}^{*}$用於只計算正錨點框損失,不計算負的。

 RPN代碼示例

def rpn_graph(feature_map, anchors_per_location, anchor_stride):
    """Builds the computation graph of Region Proposal Network.

    feature_map: backbone features [batch, height, width, depth]
    anchors_per_location: number of anchors per pixel in the feature map
    anchor_stride: Controls the density of anchors. Typically 1 (anchors for
                   every pixel in the feature map), or 2 (every other pixel).

    Returns:
        rpn_logits: [batch, H, W, 2] Anchor classifier logits (before softmax)
        rpn_probs: [batch, H, W, 2] Anchor classifier probabilities.
        rpn_bbox: [batch, H, W, (dy, dx, log(dh), log(dw))] Deltas to be
                  applied to anchors.
    """
    # TODO: check if stride of 2 causes alignment issues if the feature map
    # is not even.
    # Shared convolutional base of the RPN
    shared = KL.Conv2D(512, (3, 3), padding='same', activation='relu',
                       strides=anchor_stride,
                       name='rpn_conv_shared')(feature_map)

    # Anchor Score. [batch, height, width, anchors per location * 2].
    x = KL.Conv2D(2 * anchors_per_location, (1, 1), padding='valid',
                  activation='linear', name='rpn_class_raw')(shared)

    # Reshape to [batch, anchors, 2]
    rpn_class_logits = KL.Lambda(
        lambda t: tf.reshape(t, [tf.shape(t)[0], -1, 2]))(x)

    # Softmax on last dimension of BG/FG.
    rpn_probs = KL.Activation(
        "softmax", name="rpn_class_xxx")(rpn_class_logits)

    # Bounding box refinement. [batch, H, W, anchors per location, depth]
    # where depth is [x, y, log(w), log(h)]
    x = KL.Conv2D(anchors_per_location * 4, (1, 1), padding="valid",
                  activation='linear', name='rpn_bbox_pred')(shared)

    # Reshape to [batch, anchors, 4]
    rpn_bbox = KL.Lambda(lambda t: tf.reshape(t, [tf.shape(t)[0], -1, 4]))(x)

    return [rpn_class_logits, rpn_probs, rpn_bbox]

參考文獻:2015 PAMI Faster R-CNN


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM