object_detectionAPI源碼閱讀筆記(8-faster_rcnn_inception_resnet_v2_feature_extractor.py)

faster_rcnn_inception_resnet_v2_feature_extractor.py

object_detection\models\faster_rcnn_inception_resnet_v2_feature_extractor.py文件中只有一個類侥涵,那就是FasterRCNNInceptionResnetV2FeatureExtractor這是FasterRCNNFeatureExtractor的子類懦趋。

對于不同的CNN基礎模型object_detection\models\下面有對應的feature_extractor實現(xiàn)。

import tensorflow as tf

from object_detection.meta_architectures import faster_rcnn_meta_arch
from nets import inception_resnet_v2

slim = tf.contrib.slim

class FasterRCNNInceptionResnetV2FeatureExtractor(
    faster_rcnn_meta_arch.FasterRCNNFeatureExtractor):
  """Faster R-CNN with Inception Resnet v2 feature extractor implementation."""

介紹FasterRCNNInceptionResnetV2FeatureExtractor的方法

import tensorflow as tf

from object_detection.meta_architectures import faster_rcnn_meta_arch
from nets import inception_resnet_v2

slim = tf.contrib.slim

class FasterRCNNInceptionResnetV2FeatureExtractor(
    faster_rcnn_meta_arch.FasterRCNNFeatureExtractor):
  """Faster R-CNN with Inception Resnet v2 feature extractor implementation."""

  def __init__(self,
               is_training,
               first_stage_features_stride,
               batch_norm_trainable=False,
               reuse_weights=None,
               weight_decay=0.0):
 
    if first_stage_features_stride != 8 and first_stage_features_stride != 16:
      raise ValueError('`first_stage_features_stride` must be 8 or 16.')
    super(FasterRCNNInceptionResnetV2FeatureExtractor, self).__init__(
        is_training, first_stage_features_stride, batch_norm_trainable,
        reuse_weights, weight_decay)

  def preprocess(self, resized_inputs):
    return (2.0 / 255.0) * resized_inputs - 1.0

  def _extract_proposal_features(self, preprocessed_inputs, scope):
    
   .........
    return rpn_feature_map

  def _extract_box_classifier_features(self, proposal_feature_maps, scope):
      ......
        return proposal_classifier_features

  def restore_from_classification_checkpoint_fn(
      self,
      first_stage_feature_extractor_scope,
      second_stage_feature_extractor_scope):
    .........
    return variables_to_restore

從上面可以看出FasterRCNNInceptionResnetV2FeatureExtractor有把四個抽象方法實現(xiàn)了虽缕,這些方法在object_detectionAPI源碼閱讀筆記(6-faster_rcnn_meta_arch.py) 中有提到锄弱。
下面就具體介紹。

  • init()
  def __init__(self,
               is_training,
               first_stage_features_stride,
               batch_norm_trainable=False,
               reuse_weights=None,
               weight_decay=0.0):
 """Constructor.

    Args:
      is_training: See base class.
      first_stage_features_stride: See base class.
      batch_norm_trainable: See base class.
      reuse_weights: See base class.
      weight_decay: See base class.

    Raises:
      ValueError: If `first_stage_features_stride` is not 8 or 16.
    """
    if first_stage_features_stride != 8 and first_stage_features_stride != 16:
      raise ValueError('`first_stage_features_stride` must be 8 or 16.')
    super(FasterRCNNInceptionResnetV2FeatureExtractor, self).__init__(
        is_training, first_stage_features_stride, batch_norm_trainable,
        reuse_weights, weight_decay)

初始化函數(shù)就是把FasterRCNNInceptionResnetV2FeatureExtractor和FasterRCNNInceptionResnetV2FeatureExtractor進行初始化并且first_stage_features_stride必須是第8和16的特征圖社证,其他層的特征圖會報錯油啤。

  • preprocess(self, resized_inputs):
def preprocess(self, resized_inputs):
  Args:
      resized_inputs: A [batch, height_in, width_in, channels] float32 tensor
        representing a batch of images with values between 0 and 255.0.

    Returns:
      preprocessed_inputs: A [batch, height_out, width_out, channels] float32
        tensor representing a batch of images.
    return (2.0 / 255.0) * resized_inputs - 1.0

這是Faster R-CNN with Inception Resnet v2 的預處理函數(shù).將像素值映射到[-1, 1]范圍(歸一化)。大概就是: resized_inputs = (resized_inputs / 255)*2 - 1這樣算的坯钦。這樣就到[-1,1]了预皇。

  • _extract_proposal_features()
def _extract_proposal_features(self, preprocessed_inputs, scope):
    '''
      Args:
      preprocessed_inputs: tensor的shape= [batch, height, width, channels]损敷,這里的preprocessed_inputs是歸一的tensor。
      scope: 變量的空間名
     Returns:
      rpn_feature_map: 輸出tensor shape = [batch, height, width, depth]深啤,將用于RPN網(wǎng)絡進行特征提取。
    '''
    if len(preprocessed_inputs.get_shape().as_list()) != 4:
      raise ValueError('`preprocessed_inputs` must be 4 dimensional, got a '
                       'tensor of shape %s' % preprocessed_inputs.get_shape())

    with slim.arg_scope(inception_resnet_v2.inception_resnet_v2_arg_scope(
        weight_decay=self._weight_decay)):
  
      # Forces is_training to False to disable batch norm update.
      with slim.arg_scope([slim.batch_norm],
                          is_training=self._train_batch_norm):
        with tf.variable_scope('InceptionResnetV2',
                               reuse=self._reuse_weights) as scope:
       # 通過 reuse=self._reuse_weights設置
        #variable_scope可以實現(xiàn)同一個name_scope中的變量的共享
          rpn_feature_map, _ = (
              inception_resnet_v2.inception_resnet_v2_base(
                  preprocessed_inputs, final_endpoint='PreAuxLogits',
                  scope=scope, output_stride=self._first_stage_features_stride,
                  align_feature_maps=True))
    return rpn_feature_map

這是提取第一階段將用于RPN的特征路星,返回feature map溯街。實現(xiàn)faster_rcnn_meta_arch中的抽象方法使用Inception Resnet v2網(wǎng)絡的前半部分提取特征[將用于RPN的特征]。
如果在align_feature_maps = True模式下構(gòu)建網(wǎng)絡洋丐,卷積的VALID變成SAME模式呈昔,以便特征映射對齊。

  • _extract_box_classifier_features():
  def _extract_box_classifier_features(self, proposal_feature_maps, scope):
    """
    提取將用于第二階段框分類器的特征友绝。
    這個方法重建了Inception ResNet v2的“后半部分”網(wǎng)絡——
    `_extract_proposal_features`中定義的就是那“后半部分”堤尾。相當于原論文中的ROIPooling及其之后的層。
    Args:
      proposal_feature_maps: 用于裁剪出各個proposal的特征圖
        [batch_size * self.max_num_proposals, crop_height, crop_width, depth]
      scope: A scope name.
    Returns:
      proposal_classifier_features: 分了類的proposal
        [batch_size * self.max_num_proposals, height, width, depth]
    """
    with tf.variable_scope('InceptionResnetV2', reuse=self._reuse_weights):
      with slim.arg_scope(inception_resnet_v2.inception_resnet_v2_arg_scope(
          weight_decay=self._weight_decay)):
        # Forces is_training to False to disable batch norm update.
        with slim.arg_scope([slim.batch_norm],
                            is_training=self._train_batch_norm):
          with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
                              stride=1, padding='SAME'):
            with tf.variable_scope('Mixed_7a'):
              with tf.variable_scope('Branch_0'):
                tower_conv = slim.conv2d(proposal_feature_maps,
                                         256, 1, scope='Conv2d_0a_1x1')
                tower_conv_1 = slim.conv2d(
                    tower_conv, 384, 3, stride=2,
                    padding='VALID', scope='Conv2d_1a_3x3')
              with tf.variable_scope('Branch_1'):
                tower_conv1 = slim.conv2d(
                    proposal_feature_maps, 256, 1, scope='Conv2d_0a_1x1')
                tower_conv1_1 = slim.conv2d(
                    tower_conv1, 288, 3, stride=2,
                    padding='VALID', scope='Conv2d_1a_3x3')
              with tf.variable_scope('Branch_2'):
                tower_conv2 = slim.conv2d(
                    proposal_feature_maps, 256, 1, scope='Conv2d_0a_1x1')
                tower_conv2_1 = slim.conv2d(tower_conv2, 288, 3,
                                            scope='Conv2d_0b_3x3')
                tower_conv2_2 = slim.conv2d(
                    tower_conv2_1, 320, 3, stride=2,
                    padding='VALID', scope='Conv2d_1a_3x3')
              with tf.variable_scope('Branch_3'):
                tower_pool = slim.max_pool2d(
                    proposal_feature_maps, 3, stride=2, padding='VALID',
                    scope='MaxPool_1a_3x3')
              net = tf.concat(
                  [tower_conv_1, tower_conv1_1, tower_conv2_2, tower_pool], 3)
            net = slim.repeat(net, 9, inception_resnet_v2.block8, scale=0.20)
            net = inception_resnet_v2.block8(net, activation_fn=None)
            proposal_classifier_features = slim.conv2d(
                net, 1536, 1, scope='Conv2d_7b_1x1')
        return proposal_classifier_features

在這個方法的末尾使用一個1x1的卷積核進行卷積生成1536通道的特征圖迁客。

注意這里的輸入tensor的shape=[batch_size * self.max_num_proposals, crop_height, crop_width, depth] 郭宝,說明這里的輸入已經(jīng)是經(jīng)過區(qū)域提取的網(wǎng)絡,每個批次有batch_size * self.max_num_proposals張?zhí)卣鲌D掷漱。 輸出是tensor是proposal_classifier_features: 已經(jīng)分了類的分類特征的shape=[batch_size * self.max_num_proposals, height, width, depth]

  • restore_from_classification_checkpoint_fn()
def restore_from_classification_checkpoint_fn(
      self,
      first_stage_feature_extractor_scope,
      second_stage_feature_extractor_scope):
  
    variables_to_restore = {}
    for variable in tf.global_variables():
      if variable.op.name.startswith(
          first_stage_feature_extractor_scope):
        var_name = variable.op.name.replace(
            first_stage_feature_extractor_scope + '/', '')
        variables_to_restore[var_name] = variable
      if variable.op.name.startswith(
          second_stage_feature_extractor_scope):
        var_name = variable.op.name.replace(
            second_stage_feature_extractor_scope
            + '/InceptionResnetV2/Repeat', 'InceptionResnetV2/Repeat_2')
        var_name = var_name.replace(
            second_stage_feature_extractor_scope + '/', '')
        variables_to_restore[var_name] = variable
    return variables_to_restore

這個方法覆蓋了基類的方法粘室,同時復用了_extract_box_classifier_features()方法構(gòu)建的命名空間,這里所用到的參數(shù)權(quán)重均是_extract_box_classifier_features()構(gòu)建的卜范。
Args: first_stage_feature_extractor_scope: 第一階段的命名空間 second_stage_feature_extractor_scope: 第二階段的命名空間衔统。 Returns: 返回了一個權(quán)重參數(shù)字典。

這個文件里面就是對特征的提取海雪,所有提取的去處怎么用在object_detectionAPI源碼閱讀筆記(6-faster_rcnn_meta_arch.py)提到锦爵。
FasterRCNNInceptionResnetV2FeatureExtractor是提供材料的一個類,怎么進行預測奥裸,檢測险掀,預處理在FasterRCNNMetaArch這個類實現(xiàn)了。

參考:

Tensorflow開源的object detection API中的源碼解析(三)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湾宙,一起剝皮案震驚了整個濱河市迷郑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌创倔,老刑警劉巖嗡害,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異畦攘,居然都是意外死亡霸妹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門知押,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叹螟,“玉大人鹃骂,你說我怎么就攤上這事“照溃” “怎么了畏线?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長良价。 經(jīng)常有香客問我寝殴,道長,這世上最難降的妖魔是什么明垢? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任蚣常,我火速辦了婚禮,結(jié)果婚禮上痊银,老公的妹妹穿的比我還像新娘抵蚊。我一直安慰自己,他們只是感情好溯革,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布贞绳。 她就那樣靜靜地躺著,像睡著了一般致稀。 火紅的嫁衣襯著肌膚如雪熔酷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天豺裆,我揣著相機與錄音拒秘,去河邊找鬼。 笑死臭猜,一個胖子當著我的面吹牛躺酒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔑歌,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼羹应,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了次屠?” 一聲冷哼從身側(cè)響起园匹,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劫灶,沒想到半個月后裸违,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡本昏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年供汛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡怔昨,死狀恐怖雀久,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趁舀,我是刑警寧澤赖捌,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站矮烹,受9級特大地震影響越庇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜擂送,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唯欣。 院中可真熱鬧嘹吨,春花似錦、人聲如沸境氢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萍聊。三九已至问芬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寿桨,已是汗流浹背此衅。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亭螟,地道東北人挡鞍。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像预烙,于是被迫代替她去往敵國和親墨微。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容