欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

5. VGGnet_train.py ( Faster-RCNN_TF代码解读)

程序员文章站 2024-03-14 10:01:04
...

5. /lib/networks/VGGnet_train.py

本文件是整个faster网络结构。从VGG到RPN,到RoI Proposal,最后是RCNN。
网络结构如下:
5. VGGnet_train.py ( Faster-RCNN_TF代码解读)

调用函数链接:

  1. 本文件调用的函数,如feed(), conv(), softmax()等都在network.py中。
  2. ‘rpn-data’层所用到的函数:anchor_target_layer
  3. ‘rpn-rois’层所用到的函数:proposal_layer
  4. ‘roi-data’层所用到的函数:proposal_target_layer

代码解读:

import tensorflow as tf
from networks.network import Network


#define

n_classes = 21
_feat_stride = [16,]
anchor_scales = [8, 16, 32]

class VGGnet_train(Network):
    def __init__(self, trainable=True):
        self.inputs = []
        self.data = tf.placeholder(tf.float32, shape=[None, None, None, 3])
        self.im_info = tf.placeholder(tf.float32, shape=[None, 3])
        self.gt_boxes = tf.placeholder(tf.float32, shape=[None, 5])
        #该参数定义dropout比例
        self.keep_prob = tf.placeholder(tf.float32)
        self.layers = dict({'data':self.data, 'im_info':self.im_info, 'gt_boxes':self.gt_boxes})
        self.trainable = trainable
        self.setup()

        # create ops and placeholders for bbox normalization process
        #建立weights,biases变量,用tf.assign来更新
        with tf.variable_scope('bbox_pred', reuse=True):
            weights = tf.get_variable("weights")
            biases = tf.get_variable("biases")

            self.bbox_weights = tf.placeholder(weights.dtype, shape=weights.get_shape())
            self.bbox_biases = tf.placeholder(biases.dtype, shape=biases.get_shape())
            #tf.assign用来更新参数值
            self.bbox_weights_assign = weights.assign(self.bbox_weights)
            self.bbox_bias_assign = biases.assign(self.bbox_biases)

    def setup(self):
        #feed就是从self.layers中的信息提取出来(包括slef.daya,self.im_info,self.gt_boxes)存入self.input
        #feed返回的是self,为conv第一个参数,conv参数(self,卷积核高,宽,深度,stride高,宽)
        #return self 用法:
        #class human(object)
        #   def __init__(self,weight):
        #       self.weight=weight
        #   def get_weight(self):
        #       return self.weight
        #想要调用get_weight,直接用human.get_weight(45)会告知调用之前要先实例化,weight为未绑定函数
        #而   human.get_weight(human(45))就可以正常输出,说明human(45)将get_weight绑定了
        #其实human(45)作为一个self传给get_weight()
        #conv:卷积高、宽、输出深度、步长高、宽
        (self.feed('data')
             .conv(3, 3, 64, 1, 1, name='conv1_1', trainable=False)
             .conv(3, 3, 64, 1, 1, name='conv1_2', trainable=False)
             .max_pool(2, 2, 2, 2, padding='VALID', name='pool1')
             .conv(3, 3, 128, 1, 1, name='conv2_1', trainable=False)
             .conv(3, 3, 128, 1, 1, name='conv2_2', trainable=False)
             .max_pool(2, 2, 2, 2, padding='VALID', name='pool2')
             .conv(3, 3, 256, 1, 1, name='conv3_1')
             .conv(3, 3, 256, 1, 1, name='conv3_2')
             .conv(3, 3, 256, 1, 1, name='conv3_3')
             .max_pool(2, 2, 2, 2, padding='VALID', name='pool3')
             .conv(3, 3, 512, 1, 1, name='conv4_1')
             .conv(3, 3, 512, 1, 1, name='conv4_2')
             .conv(3, 3, 512, 1, 1, name='conv4_3')
             .max_pool(2, 2, 2, 2, padding='VALID', name='pool4')
             .conv(3, 3, 512, 1, 1, name='conv5_1')
             .conv(3, 3, 512, 1, 1, name='conv5_2')
             .conv(3, 3, 512, 1, 1, name='conv5_3'))
        #========= RPN ============
        #feed操作就是保证self.inputs中只存有下一步操作所需要的上一层的输出数据,每一个op操作都会包含一个feed操作(定义在layer函数里)
        #在初始化feed时候可能需要好几种数据,如feed('rpn_cls_score','gt_boxes','im_info','data')
        (self.feed('conv5_3')
             .conv(3,3,512,1,1,name='rpn_conv/3x3')
            #anchor_scales为3个尺度,又有3个比例1:1,1:2,2:1,所以*3,又score为2个得分,所以*2
             .conv(1,1,len(anchor_scales)*3*2 ,1 , 1, padding='VALID', relu = False, name='rpn_cls_score'))
        #feed的返回值为参数层的输出,都是从self.layers这个字典中取的,layer函数中有将各层的输出存进self.layers的操作
        #'rpn-data'层给出了rpn中的所有信息,包括图片anchor(标签-1,0,1),回归值(dx,dy,dw,dh),两个权重
        #data:为图片像素信息,info:im_info[0]存的是图片像素行数即高,im_info[1]存的是图片像素列数即宽
        #gt_boxes:GT信息,为5维度,前四个为(xmin,ymin)(xmax,ymax),最后一个为标签
        #rpn_cls_score就把他看成一个简单的feature-map,深度为3*3*2,对应3比例*3尺度*2分类值
        #[anchor_target_layer](https://blog.csdn.net/u014256231/article/details/79698070)
        (self.feed('rpn_cls_score','gt_boxes','im_info','data')
             .anchor_target_layer(_feat_stride, anchor_scales, name = 'rpn-data' ))

        # Loss of rpn_cls & rpn_boxes
        #回归bbox,存的是(dx,dy,dw,dh)
        (self.feed('rpn_conv/3x3')
             .conv(1,1,len(anchor_scales)*3*4, 1, 1, padding='VALID', relu = False, name='rpn_bbox_pred'))

        #========= RoI Proposal ============
        #先reshape后softmax**
        (self.feed('rpn_cls_score')
             .reshape_layer(2,name = 'rpn_cls_score_reshape')#形状shape(1,9n,n,2)
             .softmax(name='rpn_cls_prob'))#形状shape(1,9n,n,2)
        #再reshape
        (self.feed('rpn_cls_prob')#形状shape(1,9n,n,2)
             .reshape_layer(len(anchor_scales)*3*2,name = 'rpn_cls_prob_reshape'))#形状shape(1,n,n,18),信息还原成'rpn_cls_score',刚才两步reshape_layer操作:1、修改为softmax格式。2、还原rpn_cls_score信息位置格式,只不过内容变为sotfmax得分

        (self.feed('rpn_cls_prob_reshape','rpn_bbox_pred','im_info')
            # 初始得到blob,内容为[proposal引索(全0),proposal],shape(proposals.shape[0](即暂存的proposals个数),5)
            #[proposal_layer](https://blog.csdn.net/u014256231/article/details/79698562)
             .proposal_layer(_feat_stride, anchor_scales, 'TRAIN',name = 'rpn_rois'))
        #产生筛选后的roi,对应labels,三个(len(rois),4*21)大小的矩阵,其中一个对fg-roi对应引索行的对应类别的4个位置填上(dx,dy,dw,dh),另两个对fg-roi对应引索行的对应类别的4个位置填上(1,1,1,1)
        #[proposal_target_layer](https://blog.csdn.net/u014256231/article/details/79698825)
        (self.feed('rpn_rois','gt_boxes')
             .proposal_target_layer(n_classes,name = 'roi-data'))


        #========= RCNN ============
        (self.feed('conv5_3', 'roi-data')
             .roi_pool(7, 7, 1.0/16, name='pool_5')
             .fc(4096, name='fc6')
             .dropout(0.5, name='drop6')
             .fc(4096, name='fc7')
             .dropout(0.5, name='drop7')
             .fc(n_classes, relu=False, name='cls_score')
             .softmax(name='cls_prob'))

        (self.feed('drop7')
             .fc(n_classes*4, relu=False, name='bbox_pred'))