天天看點

Faster Rcnn 代碼解讀之 proposal_top_layer.py

# --------------------------------------------------------
# Faster R-CNN
# Licensed under The MIT License [see LICENSE for details]
# Written by Xinlei Chen
# --------------------------------------------------------
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from model.config import cfg
from model.bbox_transform import bbox_transform_inv, clip_boxes, bbox_transform_inv_tf, clip_boxes_tf

import tensorflow as tf
import numpy as np
import numpy.random as npr


# 對rpn計算結果roi proposals的優選
# 這個和proposal_layer是對應的
# 當TEST.MODE = 'top'使用proposal_top_layer,
# 當TEST.MODE = 'nms'使用proposal_layer,
# 上面是自認為的.....
def proposal_top_layer(rpn_cls_prob, rpn_bbox_pred, im_info, _feat_stride, anchors, num_anchors):
    """A layer that just selects the top region proposals
       without using non-maximal suppression,
       For details please see the technical report
    """
    # __C.TEST.RPN_TOP_N = 5000 僅TEST.MODE = 'top' 的時候使用
    # __C.TEST.MODE = 'nms'
    rpn_top_n = cfg.TEST.RPN_TOP_N
    # 提取機率分數
    scores = rpn_cls_prob[:, :, :, num_anchors:]

    # 對提取的預測狂reshape # rpn_bbox_pred:RPN層輸出的box的取值,即:tx,ty,tw,th
    rpn_bbox_pred = rpn_bbox_pred.reshape((-1, 4))

    scores = scores.reshape((-1, 1))
    # 統計有多少個框
    length = scores.shape[0]
    if length < rpn_top_n:  # 如果框小于5000個,需要随即重複采樣,讓他變成5000個
        # Random selection, maybe unnecessary and loses good proposals
        # But such case rarely happens
        top_inds = npr.choice(length, size=rpn_top_n, replace=True)
    else:
        # 從大到小排序,取列索引
        top_inds = scores.argsort(0)[::-1]
        # 取前大的5000個
        top_inds = top_inds[:rpn_top_n]
        top_inds = top_inds.reshape(rpn_top_n, )

    # Do the selection here
    # 選擇/重排
    # 按照索引提取anchor資料
    anchors = anchors[top_inds, :]
    rpn_bbox_pred = rpn_bbox_pred[top_inds, :]
    scores = scores[top_inds]

    # Convert anchors into proposals via bbox transformations
    # bbox_transform_inv : 根據anchor和偏移量計算proposals
    proposals = bbox_transform_inv(anchors, rpn_bbox_pred)

    # Clip predicted boxes to image
    # clip_boxes : proposals的邊界限制在圖檔内
    proposals = clip_boxes(proposals, im_info[:2])

    # Output rois blob
    # Our RPN implementation only supports a single input image, so all
    # batch inds are 0
    # 和 proposal_layer 一樣,多出來一列0,然後拼接
    batch_inds = np.zeros((proposals.shape[0], 1), dtype=np.float32)
    blob = np.hstack((batch_inds, proposals.astype(np.float32, copy=False)))
    return blob, scores


def proposal_top_layer_tf(rpn_cls_prob, rpn_bbox_pred, im_info, _feat_stride, anchors, num_anchors):
    """A layer that just selects the top region proposals
       without using non-maximal suppression,
       For details please see the technical report
    """
    rpn_top_n = cfg.TEST.RPN_TOP_N

    scores = rpn_cls_prob[:, :, :, num_anchors:]
    rpn_bbox_pred = tf.reshape(rpn_bbox_pred, shape=(-1, 4))
    scores = tf.reshape(scores, shape=(-1,))

    # Do the selection here
    top_scores, top_inds = tf.nn.top_k(scores, k=rpn_top_n)
    top_scores = tf.reshape(top_scores, shape=(-1, 1))
    top_anchors = tf.gather(anchors, top_inds)
    top_rpn_bbox = tf.gather(rpn_bbox_pred, top_inds)
    proposals = bbox_transform_inv_tf(top_anchors, top_rpn_bbox)

    # Clip predicted boxes to image
    proposals = clip_boxes_tf(proposals, im_info[:2])

    # Output rois blob
    # Our RPN implementation only supports a single input image, so all
    # batch inds are 0
    proposals = tf.to_float(proposals)
    batch_inds = tf.zeros((rpn_top_n, 1))
    blob = tf.concat([batch_inds, proposals], 1)
    return blob, top_scores
           

繼續閱讀