• 软件工程学习进度第八周暨暑期学习进度之第八周汇总


    本周的主要工作是win10+TensorFlow环境下的FCN全卷积神经网络的实现

    FCN对图像进行像素级的分类,从而解决了语义级别的图像分割问题。与经典的CNN在卷积层使用全连接层得到固定长度的特征向量进行分类不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷基层的特征图(feature map)进行上采样,使它恢复到输入图像相同的尺寸,从而可以对每一个像素都产生一个预测,同时保留了原始输入图像中的空间信息,最后奇偶在上采样的特征图进行像素的分类。它与卷积神经网络(CNN)的本质区别就是将卷积神经网络的全连层换成卷积层。

    本来是打算复现FCN官方代码,后来发现官方使用的是Ubuntu+caffe,本机VMware未装Ubuntu系统所以改写FCN官方代码,并使用win10+TensorFlow实现

    在这里使用的是VGG-19的模型和数据集训练

    模型下载地址:

    http://www.vlfeat.org/matconvnet/models/beta16/imagenet-vgg-verydeep-19.mat

    数据集下载地址:

    http://data.csail.mit.edu/places/ADEchallenge/ADEChallengeData2016.zip

    文件结构:

    训练效果图:

    这里看到1000次训练结果loss较低,后续结果大多在3.0左右浮动,选用此次结果得到的模型

    测试结果:

    由于batch_size设置为2,所以测试图片为两张

    结果在logs文件夹显示出来

    原图:

    语义分割后:

    结果不是特别好,应该是学习率大小不适合导致loss值降不下来

    代码如下:

    FCN.py

      1 from __future__ import print_function
      2 import tensorflow as tf
      3 import numpy as np
      4 
      5 import TensorflowUtils as utils
      6 import read_MITSceneParsingData as scene_parsing
      7 import datetime
      8 import BatchDatsetReader as dataset
      9 from six.moves import xrange
     10 
     11 FLAGS = tf.flags.FLAGS
     12 #batch大小
     13 tf.flags.DEFINE_integer("batch_size", "2", "batch size for training")
     14 #存放存放数据集的路径,需要提前下载
     15 tf.flags.DEFINE_string("logs_dir", "logs/", "path to logs directory")
     16 tf.flags.DEFINE_string("data_dir", "Data_zoo/MIT_SceneParsing/ADEChallengeData2016/", "path to dataset")
     17 # 学习率
     18 tf.flags.DEFINE_float("learning_rate", "1e-4", "Learning rate for Adam Optimizer")
     19 # VGG网络参数文件,需要提前下载
     20 tf.flags.DEFINE_string("model_dir", "Model_zoo/", "Path to vgg model mat")
     21 tf.flags.DEFINE_bool('debug', "False", "Debug mode: True/ False")
     22 tf.flags.DEFINE_string('mode', "visualize", "Mode train/ test/ visualize")
     23 MODEL_URL = 'http://www.vlfeat.org/matconvnet/models/beta16/imagenet-vgg-verydeep-19.mat'
     24 MAX_ITERATION = int(1e5 + 1)
     25 # 最大迭代次数
     26 NUM_OF_CLASSESS = 151
     27 # 类的个数
     28 IMAGE_SIZE = 224
     29 # 图像尺寸
     30 # vggnet函数
     31 # 根据载入的权重建立原始的 VGGNet 的网络
     32 def vgg_net(weights, image):
     33     layers = (        'conv1_1', 'relu1_1', 'conv1_2', 'relu1_2', 'pool1',
     34                       'conv2_1', 'relu2_1', 'conv2_2', 'relu2_2', 'pool2',
     35                       'conv3_1', 'relu3_1', 'conv3_2', 'relu3_2', 'conv3_3',
     36                       'relu3_3', 'conv3_4', 'relu3_4', 'pool3',
     37                       'conv4_1', 'relu4_1', 'conv4_2', 'relu4_2', 'conv4_3',
     38                       'relu4_3', 'conv4_4', 'relu4_4', 'pool4',
     39                       'conv5_1', 'relu5_1', 'conv5_2', 'relu5_2', 'conv5_3',
     40                       'relu5_3', 'conv5_4', 'relu5_4'
     41     )
     42     net = {}
     43     current = image
     44     for i, name in enumerate(layers):
     45         kind = name[:4]
     46         if kind == 'conv':
     47             kernels, bias = weights[i][0][0][0][0]
     48             # matconvnet: weights are [width, height, in_channels, out_channels]
     49             # tensorflow: weights are [height, width, in_channels, out_channels]
     50             kernels = utils.get_variable(np.transpose(kernels, (1, 0, 2, 3)), name=name + "_w")
     51             bias = utils.get_variable(bias.reshape(-1), name=name + "_b")
     52             current = utils.conv2d_basic(current, kernels, bias)
     53         elif kind == 'relu':
     54             current = tf.nn.relu(current, name=name)
     55             if FLAGS.debug:
     56                 utils.add_activation_summary(current)
     57         elif kind == 'pool':
     58             current = utils.avg_pool_2x2(current)
     59         net[name] = current
     60     return net
     61 # inference函数,FCN的网络结构定义,网络中用到的参数是迁移VGG训练好的参数
     62 def inference(image, keep_prob):
     63     #输入图像和dropout值
     64     """   
     65      Semantic segmentation network definition
     66      :param image: input image. Should have values in range 0-255
     67      :param keep_prob:
     68      :return:
     69     """
     70     # 加载模型数据,获得标准化均值
     71     print("setting up vgg initialized conv layers ...")
     72     model_data = utils.get_model_data(FLAGS.model_dir, MODEL_URL)
     73     mean = model_data['normalization'][0][0][0]
     74     # 通过字典获取mean值,vgg模型参数里有normaliza这个字典,三个0用来去虚维找到mean
     75     mean_pixel = np.mean(mean, axis=(0, 1))
     76     weights = np.squeeze(model_data['layers'])
     77     # 从数组的形状中删除单维度条目,获得vgg权重
     78     # 图像预处理
     79     processed_image = utils.process_image(image, mean_pixel)
     80     # 图像减平均值实现标准化
     81     print("预处理后的图像:", np.shape(processed_image))
     82     with tf.variable_scope("inference"):
     83         # 建立原始的VGGNet-19网络
     84         print("开始建立VGG网络:")
     85         image_net = vgg_net(weights, processed_image)
     86         # 在VGGNet-19之后添加 一个池化层和三个卷积层
     87         conv_final_layer = image_net["conv5_3"]
     88         print("VGG处理后的图像:", np.shape(conv_final_layer))
     89         pool5 = utils.max_pool_2x2(conv_final_layer)
     90         W6 = utils.weight_variable([7, 7, 512, 4096], name="W6")
     91         b6 = utils.bias_variable([4096], name="b6")
     92         conv6 = utils.conv2d_basic(pool5, W6, b6)
     93         relu6 = tf.nn.relu(conv6, name="relu6")
     94         if FLAGS.debug:
     95             utils.add_activation_summary(relu6)
     96         relu_dropout6 = tf.nn.dropout(relu6, keep_prob=keep_prob)
     97         W7 = utils.weight_variable([1, 1, 4096, 4096], name="W7")
     98         b7 = utils.bias_variable([4096], name="b7")
     99         conv7 = utils.conv2d_basic(relu_dropout6, W7, b7)
    100         relu7 = tf.nn.relu(conv7, name="relu7")
    101         if FLAGS.debug:
    102             utils.add_activation_summary(relu7)
    103         relu_dropout7 = tf.nn.dropout(relu7, keep_prob=keep_prob)
    104         W8 = utils.weight_variable([1, 1, 4096, NUM_OF_CLASSESS], name="W8")
    105         b8 = utils.bias_variable([NUM_OF_CLASSESS], name="b8")
    106         conv8 = utils.conv2d_basic(relu_dropout7, W8, b8)
    107         # 第8层卷积层 分类2类 1*1*2
    108         # annotation_pred1 = tf.argmax(conv8, dimension=3, name="prediction1")
    109         # now to upscale to actual image size
    110         # 对卷积后的结果进行反卷积操作
    111         deconv_shape1 = image_net["pool4"].get_shape()
    112         # 将pool4 即1/16结果尺寸拿出来 做融合 [b,h,w,c]
    113         # 扩大两倍  所以stride = 2  kernel_size = 4
    114         W_t1 = utils.weight_variable([4, 4, deconv_shape1[3].value, NUM_OF_CLASSESS], name="W_t1")
    115         b_t1 = utils.bias_variable([deconv_shape1[3].value], name="b_t1")
    116         conv_t1 = utils.conv2d_transpose_strided(conv8, W_t1, b_t1, output_shape=tf.shape(image_net["pool4"]))
    117         fuse_1 = tf.add(conv_t1, image_net["pool4"], name="fuse_1") # 将pool4和conv_t1拼接,逐像素相加
    118 
    119         deconv_shape2 = image_net["pool3"].get_shape() # 获得pool3尺寸 是原图大小的1/8
    120         W_t2 = utils.weight_variable([4, 4, deconv_shape2[3].value, deconv_shape1[3].value], name="W_t2")
    121         b_t2 = utils.bias_variable([deconv_shape2[3].value], name="b_t2")
    122         conv_t2 = utils.conv2d_transpose_strided(fuse_1, W_t2, b_t2, output_shape=tf.shape(image_net["pool3"]))
    123         fuse_2 = tf.add(conv_t2, image_net["pool3"], name="fuse_2")
    124         shape = tf.shape(image) # 获得原始图像大小
    125         deconv_shape3 = tf.stack([shape[0], shape[1], shape[2], NUM_OF_CLASSESS])  # 矩阵拼接
    126 
    127         W_t3 = utils.weight_variable([16, 16, NUM_OF_CLASSESS, deconv_shape2[3].value], name="W_t3")
    128         b_t3 = utils.bias_variable([NUM_OF_CLASSESS], name="b_t3")
    129         conv_t3 = utils.conv2d_transpose_strided(fuse_2, W_t3, b_t3, output_shape=deconv_shape3, stride=8)
    130         annotation_pred = tf.argmax(conv_t3, dimension=3, name="prediction") # (224,224,1)目前理解是每个像素点所有通道取最大值
    131     return tf.expand_dims(annotation_pred, dim=3), conv_t3     # 从第三维度扩展形成[b,h,w,c] 其中c=1,即224*224*1*1
    132 # 返回优化器
    133 def train(loss_val, var_list):
    134     optimizer = tf.train.AdamOptimizer(FLAGS.learning_rate)
    135     grads = optimizer.compute_gradients(loss_val, var_list=var_list)
    136     if FLAGS.debug:
    137         # print(len(var_list))
    138         for grad, var in grads:
    139             utils.add_gradient_summary(grad, var)
    140     return optimizer.apply_gradients(grads)
    141 # 主函数,返回优化器的操作步骤
    142 def main(argv=None):
    143     keep_probability = tf.placeholder(tf.float32, name="keep_probabilty")
    144     image = tf.placeholder(tf.float32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 3], name="input_image")
    145     annotation = tf.placeholder(tf.int32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 1], name="annotation")
    146     # 定义好FCN的网络模型
    147     pred_annotation, logits = inference(image, keep_probability)
    148     # 定义损失函数,这里使用交叉熵的平均值作为损失函数
    149     tf.summary.image("input_image", image, max_outputs=2)
    150     tf.summary.image("ground_truth", tf.cast(annotation, tf.uint8), max_outputs=2)
    151     tf.summary.image("pred_annotation", tf.cast(pred_annotation, tf.uint8), max_outputs=2)
    152     loss = tf.reduce_mean((tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,
    153                                                                           labels=tf.squeeze(annotation, squeeze_dims=[3]),
    154                                                                           name="entropy")))
    155     loss_summary = tf.summary.scalar("entropy", loss)
    156     # 定义优化器, 返回需要训练的变量列表
    157     trainable_var = tf.trainable_variables()
    158     if FLAGS.debug:
    159         for var in trainable_var:
    160             utils.add_to_regularization_and_summary(var)
    161     train_op = train(loss, trainable_var)
    162     print("Setting up summary op...")
    163     summary_op = tf.summary.merge_all()
    164     # 加载数据集
    165 
    166     print("Setting up image reader...")
    167     train_records, valid_records = scene_parsing.read_dataset(FLAGS.data_dir)
    168     print(len(train_records))
    169     print(len(valid_records))
    170     print("Setting up dataset reader")
    171     image_options = {'resize': True, 'resize_size': IMAGE_SIZE}
    172     if FLAGS.mode == 'train':
    173         train_dataset_reader = dataset.BatchDatset(train_records, image_options)
    174         # 读取图片 产生类对象 其中包含所有图片信息
    175     validation_dataset_reader = dataset.BatchDatset(valid_records, image_options)
    176     # 开始训练模型
    177     sess = tf.Session()
    178     print("Setting up Saver...")
    179     saver = tf.train.Saver()
    180     # 保存模型类实例化
    181     # create two summary writers to show training loss and validation loss in the same graph
    182     # need to create two folders 'train' and 'validation' inside FLAGS.logs_dir
    183     train_writer = tf.summary.FileWriter(FLAGS.logs_dir + '/train', sess.graph)
    184     validation_writer = tf.summary.FileWriter(FLAGS.logs_dir + '/validation')
    185     sess.run(tf.global_variables_initializer())
    186     # 变量初始化
    187     ckpt = tf.train.get_checkpoint_state(FLAGS.logs_dir)
    188     if ckpt and ckpt.model_checkpoint_path:
    189         # 如果存在checkpoint文件 则恢复sess
    190         saver.restore(sess, ckpt.model_checkpoint_path)
    191         print("Model restored...")
    192     if FLAGS.mode == "train":
    193         for itr in xrange(MAX_ITERATION):
    194             train_images, train_annotations = train_dataset_reader.next_batch(FLAGS.batch_size)
    195             feed_dict = {image: train_images, annotation: train_annotations, keep_probability: 0.85}
    196             sess.run(train_op, feed_dict=feed_dict)
    197             if itr % 10 == 0:
    198                 train_loss, summary_str = sess.run([loss, loss_summary], feed_dict=feed_dict)
    199                 print("Step: %d, Train_loss:%g" % (itr, train_loss))
    200                 train_writer.add_summary(summary_str, itr)
    201             if itr % 500 == 0:
    202                 valid_images, valid_annotations = validation_dataset_reader.next_batch(FLAGS.batch_size)
    203                 valid_loss, summary_sva = sess.run([loss, loss_summary], feed_dict={image: valid_images, annotation: valid_annotations,
    204                                                                                     keep_probability: 1.0})
    205                 print("%s ---> Validation_loss: %g" % (datetime.datetime.now(), valid_loss))
    206                 # add validation loss to TensorBoard
    207                 validation_writer.add_summary(summary_sva, itr)
    208                 saver.save(sess, FLAGS.logs_dir + "model.ckpt", itr)
    209                 # 保存模型
    210     elif FLAGS.mode == "visualize":
    211         valid_images, valid_annotations = validation_dataset_reader.get_random_batch(FLAGS.batch_size)
    212         pred = sess.run(pred_annotation, feed_dict={image: valid_images, annotation: valid_annotations,
    213                                                 keep_probability: 1.0})
    214         # 预测测试结果
    215         valid_annotations = np.squeeze(valid_annotations, axis=3)
    216         pred = np.squeeze(pred, axis=3)
    217         # 从数组的形状中删除单维条目,即把shape中为1的维度去掉
    218         for itr in range(FLAGS.batch_size):
    219             utils.save_image(valid_images[itr].astype(np.uint8), FLAGS.logs_dir, name="inp_" + str(5+itr))
    220             utils.save_image(valid_annotations[itr].astype(np.uint8), FLAGS.logs_dir, name="gt_" + str(5+itr))
    221             utils.save_image(pred[itr].astype(np.uint8), FLAGS.logs_dir, name="pred_" + str(5+itr))
    222             print("Saved image: %d" % itr)
    223 
    224 if __name__ == "__main__":
    225     tf.app.run()

    TensorflowUtils.py

      1 # Utils used with tensorflow implemetation
      2 import tensorflow as tf
      3 import numpy as np
      4 import scipy.misc as misc
      5 import os, sys
      6 from six.moves import urllib
      7 import tarfile
      8 import zipfile
      9 import scipy.io
     10 from functools import reduce
     11 
     12 # 下载VGG模型的数据
     13 def get_model_data(dir_path, model_url):
     14     maybe_download_and_extract(dir_path, model_url)
     15     filename = model_url.split("/")[-1]
     16     filepath = os.path.join(dir_path, filename)
     17     if not os.path.exists(filepath):
     18         raise IOError("VGG Model not found!")
     19     data = scipy.io.loadmat(filepath)
     20     return data
     21 
     22 
     23 def maybe_download_and_extract(dir_path, url_name, is_tarfile=False, is_zipfile=False):
     24     if not os.path.exists(dir_path):
     25         os.makedirs(dir_path)
     26     filename = url_name.split('/')[-1]
     27     filepath = os.path.join(dir_path, filename)
     28     if not os.path.exists(filepath):
     29         def _progress(count, block_size, total_size):
     30             sys.stdout.write(
     31                 '
    >> Downloading %s %.1f%%' % (filename, float(count * block_size) / float(total_size) * 100.0))
     32             sys.stdout.flush()
     33 
     34         filepath, _ = urllib.request.urlretrieve(url_name, filepath, reporthook=_progress)
     35         print()
     36         statinfo = os.stat(filepath)
     37         print('Succesfully downloaded', filename, statinfo.st_size, 'bytes.')
     38         if is_tarfile:
     39             tarfile.open(filepath, 'r:gz').extractall(dir_path)
     40         elif is_zipfile:
     41             with zipfile.ZipFile(filepath) as zf:
     42                 zip_dir = zf.namelist()[0]
     43                 zf.extractall(dir_path)
     44 
     45 
     46 def save_image(image, save_dir, name, mean=None):
     47     """
     48     Save image by unprocessing if mean given else just save
     49     :param mean:
     50     :param image:
     51     :param save_dir:
     52     :param name:
     53     :return:
     54     """
     55     if mean:
     56         image = unprocess_image(image, mean)
     57     misc.imsave(os.path.join(save_dir, name + ".png"), image)
     58 
     59 
     60 def get_variable(weights, name):
     61     init = tf.constant_initializer(weights, dtype=tf.float32)
     62     var = tf.get_variable(name=name, initializer=init,  shape=weights.shape)
     63     return var
     64 
     65 
     66 def weight_variable(shape, stddev=0.02, name=None):
     67     # print(shape)
     68     initial = tf.truncated_normal(shape, stddev=stddev)
     69     if name is None:
     70         return tf.Variable(initial)
     71     else:
     72         return tf.get_variable(name, initializer=initial)
     73 
     74 
     75 def bias_variable(shape, name=None):
     76     initial = tf.constant(0.0, shape=shape)
     77     if name is None:
     78         return tf.Variable(initial)
     79     else:
     80         return tf.get_variable(name, initializer=initial)
     81 
     82 
     83 def get_tensor_size(tensor):
     84     from operator import mul
     85     return reduce(mul, (d.value for d in tensor.get_shape()), 1)
     86 
     87 
     88 def conv2d_basic(x, W, bias):
     89     conv = tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="SAME")
     90     return tf.nn.bias_add(conv, bias)
     91 
     92 
     93 def conv2d_strided(x, W, b):
     94     conv = tf.nn.conv2d(x, W, strides=[1, 2, 2, 1], padding="SAME")
     95     return tf.nn.bias_add(conv, b)
     96 
     97 
     98 def conv2d_transpose_strided(x, W, b, output_shape=None, stride = 2):
     99     # print x.get_shape()
    100     # print W.get_shape()
    101     if output_shape is None:
    102         output_shape = x.get_shape().as_list()
    103         output_shape[1] *= 2
    104         output_shape[2] *= 2
    105         output_shape[3] = W.get_shape().as_list()[2]
    106     # print output_shape
    107     conv = tf.nn.conv2d_transpose(x, W, output_shape, strides=[1, stride, stride, 1], padding="SAME")
    108     return tf.nn.bias_add(conv, b)
    109 
    110 
    111 def leaky_relu(x, alpha=0.0, name=""):
    112     return tf.maximum(alpha * x, x, name)
    113 
    114 
    115 def max_pool_2x2(x):
    116     return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
    117 
    118 
    119 def avg_pool_2x2(x):
    120     return tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
    121 
    122 
    123 def local_response_norm(x):
    124     return tf.nn.lrn(x, depth_radius=5, bias=2, alpha=1e-4, beta=0.75)
    125 
    126 
    127 def batch_norm(x, n_out, phase_train, scope='bn', decay=0.9, eps=1e-5):
    128     """
    129     Code taken from http://stackoverflow.com/a/34634291/2267819
    130     """
    131     with tf.variable_scope(scope):
    132         beta = tf.get_variable(name='beta', shape=[n_out], initializer=tf.constant_initializer(0.0)
    133                                , trainable=True)
    134         gamma = tf.get_variable(name='gamma', shape=[n_out], initializer=tf.random_normal_initializer(1.0, 0.02),
    135                                 trainable=True)
    136         batch_mean, batch_var = tf.nn.moments(x, [0, 1, 2], name='moments')
    137         ema = tf.train.ExponentialMovingAverage(decay=decay)
    138 
    139         def mean_var_with_update():
    140             ema_apply_op = ema.apply([batch_mean, batch_var])
    141             with tf.control_dependencies([ema_apply_op]):
    142                 return tf.identity(batch_mean), tf.identity(batch_var)
    143 
    144         mean, var = tf.cond(phase_train,
    145                             mean_var_with_update,
    146                             lambda: (ema.average(batch_mean), ema.average(batch_var)))
    147         normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, eps)
    148     return normed
    149 
    150 
    151 def process_image(image, mean_pixel):
    152     return image - mean_pixel
    153 
    154 
    155 def unprocess_image(image, mean_pixel):
    156     return image + mean_pixel
    157 
    158 
    159 def bottleneck_unit(x, out_chan1, out_chan2, down_stride=False, up_stride=False, name=None):
    160     """
    161     Modified implementation from github ry?!
    162     """
    163 
    164     def conv_transpose(tensor, out_channel, shape, strides, name=None):
    165         out_shape = tensor.get_shape().as_list()
    166         in_channel = out_shape[-1]
    167         kernel = weight_variable([shape, shape, out_channel, in_channel], name=name)
    168         shape[-1] = out_channel
    169         return tf.nn.conv2d_transpose(x, kernel, output_shape=out_shape, strides=[1, strides, strides, 1],
    170                                       padding='SAME', name='conv_transpose')
    171 
    172     def conv(tensor, out_chans, shape, strides, name=None):
    173         in_channel = tensor.get_shape().as_list()[-1]
    174         kernel = weight_variable([shape, shape, in_channel, out_chans], name=name)
    175         return tf.nn.conv2d(x, kernel, strides=[1, strides, strides, 1], padding='SAME', name='conv')
    176 
    177     def bn(tensor, name=None):
    178         """
    179         :param tensor: 4D tensor input
    180         :param name: name of the operation
    181         :return: local response normalized tensor - not using batch normalization :(
    182         """
    183         return tf.nn.lrn(tensor, depth_radius=5, bias=2, alpha=1e-4, beta=0.75, name=name)
    184 
    185     in_chans = x.get_shape().as_list()[3]
    186 
    187     if down_stride or up_stride:
    188         first_stride = 2
    189     else:
    190         first_stride = 1
    191 
    192     with tf.variable_scope('res%s' % name):
    193         if in_chans == out_chan2:
    194             b1 = x
    195         else:
    196             with tf.variable_scope('branch1'):
    197                 if up_stride:
    198                     b1 = conv_transpose(x, out_chans=out_chan2, shape=1, strides=first_stride,
    199                                         name='res%s_branch1' % name)
    200                 else:
    201                     b1 = conv(x, out_chans=out_chan2, shape=1, strides=first_stride, name='res%s_branch1' % name)
    202                 b1 = bn(b1, 'bn%s_branch1' % name, 'scale%s_branch1' % name)
    203 
    204         with tf.variable_scope('branch2a'):
    205             if up_stride:
    206                 b2 = conv_transpose(x, out_chans=out_chan1, shape=1, strides=first_stride, name='res%s_branch2a' % name)
    207             else:
    208                 b2 = conv(x, out_chans=out_chan1, shape=1, strides=first_stride, name='res%s_branch2a' % name)
    209             b2 = bn(b2, 'bn%s_branch2a' % name, 'scale%s_branch2a' % name)
    210             b2 = tf.nn.relu(b2, name='relu')
    211 
    212         with tf.variable_scope('branch2b'):
    213             b2 = conv(b2, out_chans=out_chan1, shape=3, strides=1, name='res%s_branch2b' % name)
    214             b2 = bn(b2, 'bn%s_branch2b' % name, 'scale%s_branch2b' % name)
    215             b2 = tf.nn.relu(b2, name='relu')
    216 
    217         with tf.variable_scope('branch2c'):
    218             b2 = conv(b2, out_chans=out_chan2, shape=1, strides=1, name='res%s_branch2c' % name)
    219             b2 = bn(b2, 'bn%s_branch2c' % name, 'scale%s_branch2c' % name)
    220 
    221         x = b1 + b2
    222         return tf.nn.relu(x, name='relu')
    223 
    224 
    225 def add_to_regularization_and_summary(var):
    226     if var is not None:
    227         tf.summary.histogram(var.op.name, var)
    228         tf.add_to_collection("reg_loss", tf.nn.l2_loss(var))
    229 
    230 
    231 def add_activation_summary(var):
    232     if var is not None:
    233         tf.summary.histogram(var.op.name + "/activation", var)
    234         tf.summary.scalar(var.op.name + "/sparsity", tf.nn.zero_fraction(var))
    235 
    236 
    237 def add_gradient_summary(grad, var):
    238     if grad is not None:
    239         tf.summary.histogram(var.op.name + "/gradient", grad)

    read_MITSceneParsingData.py

     1 import numpy as np
     2 import os
     3 import random
     4 from six.moves import cPickle as pickle
     5 from tensorflow.python.platform import gfile
     6 import glob
     7 
     8 import TensorflowUtils as utils
     9 
    10 # DATA_URL = 'http://sceneparsing.csail.mit.edu/data/ADEChallengeData2016.zip'
    11 DATA_URL = 'http://data.csail.mit.edu/places/ADEchallenge/ADEChallengeData2016.zip'
    12 
    13 
    14 def read_dataset(data_dir):
    15     pickle_filename = "MITSceneParsing.pickle"
    16     pickle_filepath = os.path.join(data_dir, pickle_filename)
    17     # if not os.path.exists(pickle_filepath):
    18     # utils.maybe_download_and_extract(data_dir, DATA_URL, is_zipfile=True) # 不存在文件 则下载
    19     SceneParsing_folder = os.path.splitext(DATA_URL.split("/")[-1])[0]
    20     result = create_image_lists(r"F:pyProgramFCN_testData_zooMIT_SceneParsingADEChallengeData2016ADEChallengeData2016")
    21     print ("Pickling ...")
    22     with open(pickle_filepath, 'wb') as f:
    23         pickle.dump(result, f, pickle.HIGHEST_PROTOCOL)
    24     # else:
    25     print ("Found pickle file!")
    26 
    27     with open(pickle_filepath,
    28               'rb') as f:
    29         # 打开pickle文件
    30         result = pickle.load(f)
    31         training_records = result['training']
    32         validation_records = result['validation']
    33         del result
    34 
    35     return training_records, validation_records
    36 
    37 
    38 def create_image_lists(image_dir):
    39     if not gfile.Exists(image_dir):
    40         print("Image directory '" + image_dir + "' not found.")
    41         return None
    42     directories = ['training', 'validation']
    43     image_list = {}
    44 
    45     for directory in directories: # 训练集和验证集 分别制作
    46         file_list = []
    47         image_list[directory] = []
    48 
    49         # 获取images目录下所有的图片名
    50         file_glob = os.path.join(image_dir, "images", directory, '*.' + 'jpg')
    51         file_list.extend(glob.glob(file_glob))  # 加入文件列表  包含所有图片文件全路径+文件名字  如 Data_zoo/MIT_SceneParsing/ADEChallengeData2016/images/training/hi.jpg
    52 
    53         if not file_list:
    54             print('No files found')
    55         else:
    56             for f in file_list: # 扫描文件列表   这里f对应文件全路径
    57                 filename = os.path.splitext(f.split("\")[-1])[0]
    58                 annotation_file = os.path.join(image_dir, "annotations", directory, filename + '.png')
    59                 if os.path.exists(annotation_file):
    60                     record = {'image': f, 'annotation': annotation_file, 'filename': filename}
    61                     image_list[directory].append(record)
    62                 else:
    63                     print("Annotation file not found for %s - Skipping" % filename)
    64 
    65         random.shuffle(image_list[directory]) # 对图片列表进行洗牌
    66         no_of_images = len(image_list[directory])
    67         print('No. of %s files: %d' % (directory, no_of_images))
    68 
    69     return image_list

    BatchDatsetReader.py

     1 """
     2 Code ideas from https://github.com/Newmu/dcgan and tensorflow mnist dataset reader
     3 """
     4 import numpy as np
     5 import scipy.misc as misc
     6 import imageio
     7 
     8 class BatchDatset:
     9     files = []
    10     images = []
    11     annotations = []
    12     image_options = {}
    13     batch_offset = 0
    14     epochs_completed = 0
    15 
    16     def __init__(self, records_list, image_options={}):
    17         """
    18         Intialize a generic file reader with batching for list of files
    19         :param records_list: list of file records to read -
    20         sample record: {'image': f, 'annotation': annotation_file, 'filename': filename}
    21         :param image_options: A dictionary of options for modifying the output image
    22         Available options:
    23         resize = True/ False
    24         resize_size = #size of output image - does bilinear resize
    25         color=True/False
    26         """
    27         print("Initializing Batch Dataset Reader...")
    28         print(image_options)
    29         self.files = records_list
    30         self.image_options = image_options
    31         self._read_images()
    32 
    33     def _read_images(self):
    34         self.__channels = True
    35         # 读取训练集图像
    36         self.images = np.array([self._transform(filename['image']) for filename in self.files])
    37         self.__channels = False
    38         # 读取label的图像,由于label图像是二维的,这里需要扩展为三维
    39         self.annotations = np.array(
    40             [np.expand_dims(self._transform(filename['annotation']), axis=3) for filename in self.files])
    41         print (self.images.shape)
    42         print (self.annotations.shape)
    43 
    44 
    45     def _transform(self, filename):
    46         image = imageio.imread(filename)
    47         if self.__channels and len(image.shape) < 3:  # make sure images are of shape(h,w,3)
    48             image = np.array([image for i in range(3)])
    49 
    50         if self.image_options.get("resize", False) and self.image_options["resize"]:
    51             resize_size = int(self.image_options["resize_size"])
    52             resize_image = misc.imresize(image,
    53                                          [resize_size, resize_size], interp='nearest')
    54         else:
    55             resize_image = image
    56 
    57         return np.array(resize_image)
    58 
    59     def get_records(self):
    60         return self.images, self.annotations
    61 
    62     def reset_batch_offset(self, offset=0):
    63         self.batch_offset = offset
    64 
    65     def next_batch(self, batch_size):
    66         start = self.batch_offset
    67         # 当前第几个batch
    68         self.batch_offset += batch_size
    69         # 读取下一个batch  所有offset偏移量+batch_size
    70         if self.batch_offset > self.images.shape[0]:
    71             # 如果下一个batch的偏移量超过了图片总数说明完成了一个epoch
    72             self.epochs_completed += 1    # epochs完成总数+1
    73             print("****************** Epochs completed: " + str(self.epochs_completed) + "******************")
    74             # Shuffle the data
    75             perm = np.arange(self.images.shape[0])
    76             # arange生成数组(0 - len-1) 获取图片索引
    77             np.random.shuffle(perm)    # 对图片索引洗牌
    78             self.images = self.images[perm]   # 洗牌之后的图片顺序
    79             self.annotations = self.annotations[perm]   # 下一个epoch从0开始
    80             # Start next epoch
    81             start = 0
    82             self.batch_offset = batch_size     # 已完成的batch偏移量
    83         end = self.batch_offset      # 开始到结束self.batch_offset   self.batch_offset+batch_size
    84         return self.images[start:end], self.annotations[start:end]   # 取出batch
    85     def get_random_batch(self, batch_size):
    86         # 按照一个batch_size一个块,进行对所有图片总数进行随机操作,相当于洗牌工作
    87         indexes = np.random.randint(0, self.images.shape[0], size=[batch_size]).tolist()
    88         return self.images[indexes], self.annotations[indexes]

    遇到的问题及解决办法:

    scipy.misc模块中imread函数以失效,用imageio.imread代替

    scipy模块版本与pillow版本不匹配,需将scipy降到1.2.1版本,才能和 pillow6.0.0以上版本相容

    (https://www.lfd.uci.edu/~gohlke/pythonlibs/网址中最低版本1.3.0, 所以采用pip install scipy==1.2.1方式安装即可)

    读取pickle文件时,判断文件是否存在的函数出现问题,不存在也会自动创建 所以无论存不存在都会判断为存在,此处为找到好的解决办法,只能不做判 断,载入数据集时是不包含pickle文件,所以根据数据集直接生成

    Windows操作系统和Linux文件路径表示方式不一样,Windows是‘’,Linux是‘/’

    本周的进度就是这些。

    马上就要开学了,下一周会重点复习UML和java,加油!

  • 相关阅读:
    XML文件处理
    前端技术学习路线及技术汇总
    Install wget for mac
    AT&T Assembly for Linux and Mac (sys_write)
    AT&T Assembly for Linux and Mac (sys_exit)
    [leetCode]5. 最长回文子串(DP)
    [深入理解JVM虚拟机]第3章-垃圾收集器、内存分配策略
    [深入理解JVM虚拟机]第2章-Java内存区域与内存溢出异常
    [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)
    [LeetCode]415. 字符串相加
  • 原文地址:https://www.cnblogs.com/zdm-code/p/11408559.html
Copyright © 2020-2023  润新知