FCN

您所在的位置:网站首页 卷积神经网络的缺点和问题 FCN

FCN

2024-03-27 09:42| 来源: 网络整理| 查看: 265

来源:https://blog.csdn.net/zhyj3038/article/details/71195262

1 实例分割,

对图像中的每一个像素点进行分类,同种物体的不同实例也用不同的类标进行标注,中间是实例分割,右图是语义分割.

2FCN与CNN区别

3CNN中Alexnet的代码:https://blog.csdn.net/akadiao/article/details/78592290?locationNum=10&fps=1

def AlexNet(images, classNum=None, dropoutrate=None): parameters = [] # 卷积层1 conv1, parameters = convLayer(images, name='conv1', kh=11, kw=11, n_out=64, dh=4, dw=4, p=parameters) # 添加LRN层和最大池化层 # 对conv1进行LRN处理 lrn1 = tf.nn.lrn(conv1, 4, bias=1.0, alpha=0.001/9, beta=0.75, name='lrn1') # 对lrn1进行最大池化处理,池化尺寸3*3,步长2*2,padding模式选VALID即取样不能超过边框 pool1 = tf.nn.max_pool(lrn1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool1') # 打印出结果pool1的结构 print pool1.op.name, ' ', pool1.get_shape().as_list() # 卷积层2 conv2, parameters = convLayer(pool1, name='conv2', kh=5, kw=5, n_out=192, dh=1, dw=1, p=parameters) # LRN处理 lrn2 = tf.nn.lrn(conv2, 4, bias=1.0,alpha=0.001/9, beta=0.75, name='lrn2') # 最大池化处理 pool2 = tf.nn.max_pool(lrn2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool2') # 打印出结果pool2的结构 print pool2.op.name, ' ', pool2.get_shape().as_list() # 卷积层3 conv3, parameters = convLayer(pool2, name='conv3', kh=3, kw=3, n_out=384, dh=1, dw=1, p=parameters) # 卷积层4 conv4, parameters = convLayer(conv3, name='conv4', kh=3, kw=3, n_out=256, dh=1, dw=1, p=parameters) # 卷积层5 conv5, parameters = convLayer(conv4, name='conv5', kh=3, kw=3, n_out=256, dh=1, dw=1, p=parameters) pool5 = tf.nn.max_pool(conv5, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool5') print pool5.op.name, ' ', pool5.get_shape().as_list() fc_in = tf.reshape(pool5, [-1, 256*6*6]) fc6 = fcLayer(fc_in, 256*6*6, 4096, True, 'fc6') dropout6 = tf.nn.dropout(fc6, dropoutrate) fc7 = fcLayer(dropout6, 4096, 4096,True, 'fc7') dropout7 = tf.nn.dropout(fc7, dropoutrate) fc8 = fcLayer(dropout7, 4096, classNum, True, 'fc8') return pool5, parameters FCN网络结构的部分代码,将三个全连接换成了卷积层: with tf.variable_scope("inference"): image_net = vgg_net(weights, processed_image) conv_final_layer = image_net["conv5_3"] pool5 = utils.max_pool_2x2(conv_final_layer) W6 = utils.weight_variable([7, 7, 512, 4096], name="W6") b6 = utils.bias_variable([4096], name="b6") conv6 = utils.conv2d_basic(pool5, W6, b6) relu6 = tf.nn.relu(conv6, name="relu6") if FLAGS.debug: utils.add_activation_summary(relu6) #根据给出的keep_prob参数,将输入tensor x按比例输出。 relu_dropout6 = tf.nn.dropout(relu6, keep_prob=keep_prob) W7 = utils.weight_variable([1, 1, 4096, 4096], name="W7")#图片的尺寸变成1*1,卷积核的数量4096,输出的尺寸就是1*1*4096,最后额 b7 = utils.bias_variable([4096], name="b7") conv7 = utils.conv2d_basic(relu_dropout6, W7, b7) relu7 = tf.nn.relu(conv7, name="relu7") if FLAGS.debug: utils.add_activation_summary(relu7) relu_dropout7 = tf.nn.dropout(relu7, keep_prob=keep_prob) W8 = utils.weight_variable([1, 1, 4096, NUM_OF_CLASSESS], name="W8") b8 = utils.bias_variable([NUM_OF_CLASSESS], name="b8") conv8 = utils.conv2d_basic(relu_dropout7, W8, b8) # annotation_pred1 = tf.argmax(conv8, dimension=3, name="prediction1") # now to upscale to actual image size 现在升级为实际的图像大小 deconv_shape1 = image_net["pool4"].get_shape() W_t1 = utils.weight_variable([4, 4, deconv_shape1[3].value, NUM_OF_CLASSESS], name="W_t1") b_t1 = utils.bias_variable([deconv_shape1[3].value], name="b_t1") conv_t1 = utils.conv2d_transpose_strided(conv8, W_t1, b_t1, output_shape=tf.shape(image_net["pool4"])) fuse_1 = tf.add(conv_t1, image_net["pool4"], name="fuse_1") deconv_shape2 = image_net["pool3"].get_shape() W_t2 = utils.weight_variable([4, 4, deconv_shape2[3].value, deconv_shape1[3].value], name="W_t2") b_t2 = utils.bias_variable([deconv_shape2[3].value], name="b_t2") conv_t2 = utils.conv2d_transpose_strided(fuse_1, W_t2, b_t2, output_shape=tf.shape(image_net["pool3"])) fuse_2 = tf.add(conv_t2, image_net["pool3"], name="fuse_2") shape = tf.shape(image) deconv_shape3 = tf.stack([shape[0], shape[1], shape[2], NUM_OF_CLASSESS]) W_t3 = utils.weight_variable([16, 16, NUM_OF_CLASSESS, deconv_shape2[3].value], name="W_t3") b_t3 = utils.bias_variable([NUM_OF_CLASSESS], name="b_t3") conv_t3 = utils.conv2d_transpose_strided(fuse_2, W_t3, b_t3, output_shape=deconv_shape3, stride=8) annotation_pred = tf.argmax(conv_t3, dimension=3, name="prediction") return tf.expand_dims(annotation_pred, dim=3), conv_t3 #对conv8此时进行32倍的上采样可以得到原图大小,这个时候得到的结果就是叫做FCN-32s. #在FCN-32s的基础上进行fine tuning,把pool4层和conv8的2倍上采样结果相加之后进行一个16倍的上采样,得到的结果是FCN-16s.如conv_t1 #FCN-16s的基础上进行fine tuning,把pool3层和2倍上采样的pool4层和4倍上采样的conv8层加起来,进行一个8倍的上采样,得到的结果就是FCN-8s

4 FCN的优点和缺点:

FCN的优点,能够end-to-end, pixels-to-pixels,而且相比于传统的基于cnn做分割的网络更加高效,因为避免了由于使用像素块而带来的重复存储和计算卷积的问题。

FCN的缺点也很明显,首先是训练比较麻烦,需要训练三次才能够得到FCN-8s,而且得到的结果还是不精细,对图像的细节不够敏感,这是因为在进行decode,也就是恢复原图像大小的过程时,输入上采样层的label map太稀疏,而且上采样过程就是一个简单的deconvolution. 

其次是对各个像素进行分类,没有考虑到像素之间的关系.忽略了在通常的基于像素分类的分割方法中使用的空间规整步骤,缺乏空间一致性.

5 FCN的实施过程中的跳跃连接的理解:

  这个结构的作用就在于优化结果,因为如果将全卷积之后的结果直接上采样得到的结果是很粗糙的,所以作者将不同池化层的结果进行上采样之后来优化输出。具体结构如下:

6 U-net:

和FCN相比,结构上比较大的改动在上采样阶段,上采样层也包括了很多层的特征.

还有一个比FCN好的地方在于,Unet只需要一次训练,FCN需要三次训练.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3