1. 程式人生 > >YOLO原始碼詳解(五)- YOLO中的7*7個grid和RPN中的9個anchors

YOLO原始碼詳解(五)- YOLO中的7*7個grid和RPN中的9個anchors

一直不知道7×7的網格到底是幹什麼的,不就是結果預測7×7×2個框嗎,這跟把原圖分成7×7有什麼關係?不分成7×7就不能預測7×7×2個框嗎?

之前跟一個朋友討論,他說7×7的網格是作為迴歸框的初始位置,我後來的很長一段時間一直這麼認為,後來想想不對啊,bbox的初始位置不是根據各層的權重得到的嗎?各層權重是隨機初始化的,7×7的grid怎麼能作為bbox的初始位置?我腦子被驢踢了麼,竟然一直這麼認為。

看了原始碼之後又看了faster-rcnn的論文中關於rpn的介紹,又看了rpn的程式碼,然後豁然開朗,我們來分析一下

一、YOLO

首先你應該看完YOLO原始碼詳解(三)- 前向傳播(forward)

,之後問題就簡單了,只有一句話:grid和anchor的唯一作用就是為了計算IOU,從而來確定正負樣本。在YOLO中,計算完IOU後確定loss function中的1obji,1objij,λcoord,λnocoord的值。

二、PRN的anchors

YOLO中的理解了,我們再來看一下PRN中的anchors,如下圖所示:

這裡寫圖片描述

假設原始影象尺寸是1000×600,最左邊的一層就是VGG的第5層卷積層,下一層是rpn_conv/3*3層,千萬不要被他迷惑了,說是rpn_conv/3×3其實還是普通的卷積層,也就是說這裡跟普通的卷積層沒有任何區別,這裡的輸出是64×39×512,在這裡,每個feature map一共有64×39個點,這裡每個點對應到原始影象上是16×16的區域(注意這裡並不是感受野),16×16怎麼算出來的呢?ceil(1000/64)×ceil(600/39),為什麼向上取整呢?因為有padding啊~

假設每個點要搞到9個anchors,也就是原始影象上每隔16×16的區域就搞9個網格,因為這9個網格大小不一樣,就取名叫anchors,這裡是不是跟YOLO一樣了?只不過YOLO整副圖就搞了7×7個網格。到這裡是不是豁然開朗了,兩種演算法有異曲同工之妙。

繼續往下走,rpn_cls_score層,這裡輸出39×64×18,每個位置有9個anchors,預測每個anchor是否是物體,所以是2×9=18,繼續到了rpn-data層(就是AnchorTargetLayer層,層的結構如下prototxt),這一層就是要算IOU的,也就是體現了:grid和anchor的唯一作用就是為了計算IOU,從而來確定正負樣本。

你理解了嗎?

layer {
  name: 'rpn-data'
  type: 'Python'
  bottom: 'rpn_cls_score'
  bottom: 'gt_boxes'
  bottom: 'im_info'
  bottom: 'data'
  top: 'rpn_labels'
  top: 'rpn_bbox_targets'
  top: 'rpn_bbox_inside_weights'
  top: 'rpn_bbox_outside_weights'
  python_param {
    module: 'rpn.anchor_target_layer'
    layer: 'AnchorTargetLayer'
    param_str: "'feat_stride': 16"
  }
}

(END)