alex_bn_lee

导航

【653】FCN——全卷积网络详解

[1] 语义分割--全卷积网络FCN详解【解释详细】

[2] 四、全卷积网络FCN详细讲解(超级详细哦)

[3] github - FCN32、FCN8

[4] keras.applications【VGG16】

[5] keras—VGG16

[6] 五、VGG、AlexNet、ResNet网络(超详细哦)

一、总体说明

  FCN = CNN(VGG16) + UpSampling

  • FCN-32s: conv7 直接上采样 32 倍到原来的尺寸

  • FCN-16s: 

    • conv7 上采样 2 倍 (/16)

    • pool4 (/16)  

    • 两者 add 之后,上采样 16 倍到原来的尺寸

  • FCN-8s:

    • conv7 上采样 2 倍 (/16)

    • pool4 (/16)  

    • 两者 add 之后,上采样 2 倍 (/8)

    • pool3 (/8)

    • 上面两者 add 之后,上采样 8 倍到原来的尺寸

 

二、结构图示

  图示如下所示:

  第1阶段

这里写图片描述 
  以经典的分类网络为初始化。最后两级是全连接(红色),参数弃去不用。

  第2阶段

这里写图片描述 
  从特征小图(16*16*4096)预测分割小图(16*16*21),之后直接升采样为大图。 
  反卷积(橙色)的步长为32,这个网络称为FCN-32s。 
  这一阶段使用单GPU训练约需3天。

 

  第3阶段

这里写图片描述 
  升采样分为两次完成(橙色×2)。 
  在第二次升采样前,把第4个pooling层(绿色)的预测结果(蓝色)融合进来。使用跳级结构提升精确性。 
  第二次反卷积步长为16,这个网络称为FCN-16s。 
  这一阶段使用单GPU训练约需1天。

 

  第4阶段

这里写图片描述 
  升采样分为三次完成(橙色×3)。 
  进一步融合了第3个pooling层的预测结果。 
  第三次反卷积步长为8,记为FCN-8s。 

 

三、代码实现

  FCN-32s

from keras.applications import vgg16
from keras.models import Model, Sequential
from keras.layers import Conv2D, Conv2DTranspose, Input, Cropping2D, add, Dropout, Reshape, Activation
from keras.utils.vis_utils import plot_model

def FCN32(nClasses, input_height, input_width):

    assert input_height % 32 == 0
    assert input_width % 32 == 0

    img_input = Input(shape=(input_height, input_width, 3))
    
    # VGG16 structrue
    # 2conv + 1pool -> block1_pool
    # 2conv + 1pool -> block2_pool
    # 3conv + 1pool -> block3_pool
    # 3conv + 1pool -> block4_pool
    # 3conv + 1pool -> block5_pool
    model = vgg16.VGG16(include_top=False, weights='imagenet', input_tensor=img_input)
    assert isinstance(model, Model)

    o = Conv2D(4096, 7, padding="same", activation="relu", name="fc6")(model.output)
    o = Dropout(rate=0.5)(o)
    o = Conv2D(4096, 1, padding="same", activation="relu", name="fc7")(o)
    o = Dropout(rate=0.5)(o)

    o = Conv2D(nClasses, 1, padding="same", activation="relu", kernel_initializer="he_normal", name="score_fr")(o)

    o = Conv2DTranspose(nClasses, 32, strides=(32, 32), padding="valid", activation=None, name="score2")(o)

    #o = Reshape((-1, nClasses))(o)
    o = Activation("softmax")(o)

    fcn8 = Model(inputs=img_input, outputs=o)
    # mymodel.summary()
    return fcn8


if __name__ == '__main__':
    m = FCN32(2, 512, 512)
    m.summary()
    plot_model(m, show_shapes=True, to_file='model_fcn32.png')
    print(len(m.layers)) 

 

  FCN-16s

from keras.applications import vgg16
from keras.models import Model, Sequential
from keras.layers import Conv2D, Conv2DTranspose, Input, Cropping2D, add, Dropout, Reshape, Activation


def FCN16_helper(nClasses, input_height, input_width):

    assert input_height % 32 == 0
    assert input_width % 32 == 0

    img_input = Input(shape=(input_height, input_width, 3))

    model = vgg16.VGG16(include_top=False,weights='imagenet', input_tensor=img_input)
    assert isinstance(model, Model)

    o = Conv2D(4096,7,padding="same",activation="relu",name="fc6")(model.output)
    o = Dropout(rate=0.5)(o)
    o = Conv2D(4096,1,padding="same",activation="relu",name="fc7")(o)
    o = Dropout(rate=0.5)(o)
    
    # /32
    o = Conv2D(nClasses, 1, padding="same", activation="relu", kernel_initializer="he_normal",name="score_fr")(o)
    
    # 用于与 block4_pool合并
    # /32 * 2 = /16
    o = Conv2DTranspose(nClasses, 2, strides=(2, 2), padding="valid", activation=None, name="score2")(o)

    fcn16 = Model(inputs=img_input, outputs=o)

    return fcn16

def FCN16(nClasses, input_height, input_width):

    fcn16 = FCN16_helper(nClasses, input_height, input_width)

    # Conv to be applied on Pool4
    # 这些 layer 的名字也可以通过后面的 summary 显示查看
    # /16
    skip_con1 = Conv2D(nClasses, 1, padding="same", activation=None, kernel_initializer="he_normal",
                       name="score_pool4")(fcn16.get_layer("block4_pool").output)
    Summed = add(inputs=[skip_con1, fcn16.output])
    
    # /16 * 16 = /1
    Up = Conv2DTranspose(nClasses, 16, strides=(16, 16), padding="valid", activation=None,name="upsample")(Summed)

    #Up = Reshape((-1, nClasses))(Up)
    Up = Activation("softmax")(Up)

    mymodel = Model(inputs=fcn16.input, outputs=Up)

    return mymodel


if __name__ == '__main__':
    m16 = FCN16(2, 512, 512)
    #plot_model(m, show_shapes=True, to_file='model_fcn8.png')
    m16.summary() 
    print(len(m.layers))

 

  FCN-8s

from keras.applications import vgg16
from keras.models import Model, Sequential
from keras.layers import Conv2D, Conv2DTranspose, Input, Cropping2D, add, Dropout, Reshape, Activation


def FCN8_helper(nClasses, input_height, input_width):

    assert input_height % 32 == 0
    assert input_width % 32 == 0

    img_input = Input(shape=(input_height, input_width, 3))

    model = vgg16.VGG16(include_top=False,weights='imagenet', input_tensor=img_input)
    assert isinstance(model, Model)

    o = Conv2D(4096,7,padding="same",activation="relu",name="fc6")(model.output)
    o = Dropout(rate=0.5)(o)
    o = Conv2D(4096,1,padding="same",activation="relu",name="fc7")(o)
    o = Dropout(rate=0.5)(o)
    
    # /32
    o = Conv2D(nClasses, 1, padding="same", activation="relu", kernel_initializer="he_normal",name="score_fr")(o)
    
    # 用于与 block4_pool合并
    # /32 * 2 = /16
    o = Conv2DTranspose(nClasses, 2, strides=(2, 2), padding="valid", activation=None, name="score2")(o)

    fcn8 = Model(inputs=img_input, outputs=o)

    return fcn8

def FCN8(nClasses, input_height, input_width):

    fcn8 = FCN8_helper(nClasses, input_height, input_width)

    # Conv to be applied on Pool4
    # 这些 layer 的名字也可以通过后面的 summary 显示查看
    # /16
    skip_con1 = Conv2D(nClasses, 1, padding="same", activation=None, kernel_initializer="he_normal",
                       name="score_pool4")(fcn8.get_layer("block4_pool").output)
    Summed = add(inputs=[skip_con1, fcn8.output])
    
    # /16 * 2 = /8
    x = Conv2DTranspose(nClasses, 2, strides=(2, 2), padding="valid", activation=None,name="score4")(Summed)

    ###
    # /8
    skip_con2 = Conv2D(nClasses, 1, padding="same", activation=None, kernel_initializer="he_normal",
                       name="score_pool3")(fcn8.get_layer("block3_pool").output)
    Summed2 = add(inputs=[skip_con2, x])

    #####
    # /8 * 8 = /1
    Up = Conv2DTranspose(nClasses, 8, strides=(8, 8),padding="valid", activation=None, name="upsample")(Summed2)

    #Up = Reshape((-1, nClasses))(Up)
    Up = Activation("softmax")(Up)

    mymodel = Model(inputs=fcn8.input, outputs=Up)

    return mymodel


if __name__ == '__main__':
    m = FCN8(2, 512, 512)
    #plot_model(m, show_shapes=True, to_file='model_fcn8.png')
    m.summary() 
    print(len(m.layers))

 

四、模型网络图

  FCN-32s

  FCN-16s

  FCN-8s

 

posted on 2021-09-03 15:44  McDelfino  阅读(899)  评论(0编辑  收藏  举报