# FCN

1 实例分割,

2FCN与CNN区别

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')
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:
#根据给出的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:
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"]))

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"]))

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：

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120