tensorflow faster rcnn 代码分析一 demo.py

时间:2021-08-12 04:07:22

os.environ["CUDA_VISIBLE_DEVICES"]=2 # 设置使用的GPU

tfconfig=tf.ConfigProto(allow_soft_placement=True) # 如果分类的GPU没有,允许tf自动分配设备

tfconfig=tf.gpu_options.allow_growth=True # Gpu 按需增加

sess=tf.Session(config=tfconfig)

定义resnet 类

class resnetv1(Network):# 继承net 类
def __init__(self, num_layers=50):
Network.__init__(self)
self._feat_stride = [16, ]
self._feat_compress = [1. / float(self._feat_stride[0]), ]
self._num_layers = num_layers
self._scope = 'resnet_v1_%d' % num_layers
self._decide_blocks()

net=resnetv1(num_layers=101)

调用Network的create_architecture 函数,得到网络的输出rois 和其prediction

def create_architecture(self, mode, num_classes, tag=None,  anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)):

# 在demo 中mode 为“test” num_classes 分类个数,
# 输入图像的占位
self._image = tf.placeholder(tf.float32, shape=[1, None, None, 3]) self._im_info = tf.placeholder(tf.float32, shape=[3])
self._gt_boxes = tf.placeholder(tf.float32, shape=[None, 5])
self._tag = tag

self._num_classes = num_classes
self._mode = mode
self._anchor_scales = anchor_scales
self._num_scales = len(anchor_scales)

self._anchor_ratios = anchor_ratios
self._num_ratios = len(anchor_ratios)

self._num_anchors = self._num_scales * self._num_ratios
# demo 中training 是false
training = mode == 'TRAIN'
testing = mode == 'TEST'

assert tag != None

# handle most of the regularizers here l2 正则项
# contrib.layer 中定义好了卷积网络的结构
weights_regularizer = tf.contrib.layers.l2_regularizer(cfg.TRAIN.WEIGHT_DECAY)
if cfg.TRAIN.BIAS_DECAY:
biases_regularizer = weights_regularizer
else:
biases_regularizer = tf.no_regularizer

# list as many types of layers as possible, even if they are not used now
# arg_scope 是slim 库中的函数,tf.contrib.slim.arg_scope(list_ops_or_scope, **kwargs) ,给list_ops_or_scope存储默认的参数

with arg_scope([slim.conv2d, slim.conv2d_in_plane, \
slim.conv2d_transpose, slim.separable_conv2d, slim.fully_connected],
weights_regularizer=weights_regularizer,
biases_regularizer=biases_regularizer,
biases_initializer=tf.constant_initializer(0.0)):
rois, cls_prob, bbox_pred = self._build_network(training) # _build_network 中对网络进行初始化,得到rois,cls_pred 等

layers_to_output = {'rois': rois}

for var in tf.trainable_variables():
self._train_summaries.append(var)

if testing:
stds = np.tile(np.array(cfg.TRAIN.BBOX_NORMALIZE_STDS), (self._num_classes))
means = np.tile(np.array(cfg.TRAIN.BBOX_NORMALIZE_MEANS), (self._num_classes))
self._predictions["bbox_pred"] *= stds
self._predictions["bbox_pred"] += means
else:
self._add_losses()
layers_to_output.update(self._losses)

val_summaries = []
with tf.device("/cpu:0"):
val_summaries.append(self._add_gt_image_summary())
for key, var in self._event_summaries.items():
val_summaries.append(tf.summary.scalar(key, var))
for key, var in self._score_summaries.items():
self._add_score_summary(key, var)
for var in self._act_summaries:
self._add_act_summary(var)
for var in self._train_summaries:
self._add_train_summary(var)

self._summary_op = tf.summary.merge_all()
self._summary_op_val = tf.summary.merge(val_summaries)

layers_to_output.update(self._predictions)

return layers_to_output
  给自定义的函数指定参数:

from tensorflow.contrib import framework

from tensorflow.contrib.framework.python.ops.arg_scope import add_args_scope

def wo(name,age):

print(name,age)

with framework.arg_scope([wo],age=20):

wo('cui')


 _build_network 返回网络的输出rois ,prediction,生成网络的整个结构

  def _build_network(self, is_training=True):
# select initializers
if cfg.TRAIN.TRUNCATED:
initializer = tf.truncated_normal_initializer(mean=0.0, stddev=0.01)
initializer_bbox = tf.truncated_normal_initializer(mean=0.0, stddev=0.001)
else:
initializer = tf.random_normal_initializer(mean=0.0, stddev=0.01)
initializer_bbox = tf.random_normal_initializer(mean=0.0, stddev=0.001)

net_conv = self._image_to_head(is_training) # 在对应的resnet_v1 中实现, 定义了网络的前半部分特征提取部分

# 分别region Proposals with tf.variable_scope(self._scope, self._scope):
# build the anchors for the image
self._anchor_component()
# region proposal network
rois = self._region_proposal(net_conv, is_training, initializer)
# region of interest pooling
if cfg.POOLING_MODE == 'crop':
pool5 = self._crop_pool_layer(net_conv, rois, "pool5")
else:
raise NotImplementedError

fc7 = self._head_to_tail(pool5, is_training)
with tf.variable_scope(self._scope, self._scope):
# region classification
cls_prob, bbox_pred = self._region_classification(fc7, is_training,
initializer, initializer_bbox)

self._score_summaries.update(self._predictions)

return rois, cls_prob, bbox_pred

  

resnet_v1中_image_to_head 的实现, 得到网络中在rpn 提取之前的部分。

  def _image_to_head(self, is_training, reuse=None):
assert (0 <= cfg.RESNET.FIXED_BLOCKS <= 3)
# Now the base is always fixed during training
with slim.arg_scope(resnet_arg_scope(is_training=False)):
net_conv = self._build_base()
  # net_conv 网络的输入第一个conv
if cfg.RESNET.FIXED_BLOCKS > 0:

# 其他层的初始化 with slim.arg_scope(resnet_arg_scope(is_training=False)):
# tensorflow.contrib.slim.python.slim.nets 中定义了resnet_v1 net_conv, _ = resnet_v1.resnet_v1(net_conv,
self._blocks[0:cfg.RESNET.FIXED_BLOCKS],
global_pool=False,
include_root_block=False,
reuse=reuse,
scope=self._scope)
if cfg.RESNET.FIXED_BLOCKS < 3:
with slim.arg_scope(resnet_arg_scope(is_training=is_training)):
net_conv, _ = resnet_v1.resnet_v1(net_conv,
self._blocks[cfg.RESNET.FIXED_BLOCKS:-1],
global_pool=False,
include_root_block=False,
reuse=reuse,
scope=self._scope)

self._act_summaries.append(net_conv)
self._layers['head'] = net_conv

 得到anchors

def _anchor_component(self):
with tf.variable_scope('ANCHOR_' + self._tag) as scope:
# just to get the shape right, feat_stride 是特征图变化的尺度,将anchors变换为对应现在的特征的尺寸
       height = tf.to_int32(tf.ceil(self._im_info[0] / np.float32(self._feat_stride[0]))) width = tf.to_int32(tf.ceil(self._im_info[1] / np.float32(self._feat_stride[0]))) 
anchors, anchor_length = tf.py_func(generate_anchors_pre, [height, width, self._feat_stride, self._anchor_scales, self._anchor_ratios], [tf.float32, tf.int32], name="generate_anchors")
anchors.set_shape([None, 4])
anchor_length.set_shape([])
self._anchors = anchors
self._anchor_length = anchor_length

  网络对每个anchor 进行分类,得到是否为object region

  def _region_proposal(self, net_conv, is_training, initializer):
rpn = slim.conv2d(net_conv, cfg.RPN_CHANNELS, [3, 3], trainable=is_training, weights_initializer=initializer,
scope="rpn_conv/3x3") # 加上3*3的卷积层
self._act_summaries.append(rpn)
rpn_cls_score = slim.conv2d(rpn, self._num_anchors * 2, [1, 1], trainable=is_training,
weights_initializer=initializer,
padding='VALID', activation_fn=None, scope='rpn_cls_score') # 对rpn 进行分类,加上一个1*1的卷积层,num_anchors*2,每个anchor 有两种分类类别
# change it so that the score has 2 as its channel size
rpn_cls_score_reshape = self._reshape_layer(rpn_cls_score, 2, 'rpn_cls_score_reshape')# 此时feature map 中的每个点对应一个可以产生9个anchor的区域
rpn_cls_prob_reshape = self._softmax_layer(rpn_cls_score_reshape, "rpn_cls_prob_reshape")
rpn_cls_pred = tf.argmax(tf.reshape(rpn_cls_score_reshape, [-1, 2]), axis=1, name="rpn_cls_pred")
rpn_cls_prob = self._reshape_layer(rpn_cls_prob_reshape, self._num_anchors * 2, "rpn_cls_prob")
rpn_bbox_pred = slim.conv2d(rpn, self._num_anchors * 4, [1, 1], trainable=is_training,
weights_initializer=initializer,
padding='VALID', activation_fn=None, scope='rpn_bbox_pred')# rpn 进行位置定位。
if is_training:
rois, roi_scores = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois")
rpn_labels = self._anchor_target_layer(rpn_cls_score, "anchor")
# Try to have a deterministic order for the computing graph, for reproducibility
with tf.control_dependencies([rpn_labels]):
rois, _ = self._proposal_target_layer(rois, roi_scores, "rpn_rois")
else:
if cfg.TEST.MODE == 'nms':
rois, _ = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois")
elif cfg.TEST.MODE == 'top':
rois, _ = self._proposal_top_layer(rpn_cls_prob, rpn_bbox_pred, "rois")
else:
raise NotImplementedError

self._predictions["rpn_cls_score"] = rpn_cls_score
self._predictions["rpn_cls_score_reshape"] = rpn_cls_score_reshape
self._predictions["rpn_cls_prob"] = rpn_cls_prob
self._predictions["rpn_cls_pred"] = rpn_cls_pred
self._predictions["rpn_bbox_pred"] = rpn_bbox_pred
self._predictions["rois"] = rois

return rois