1.Encoder
from keras.layers import *
def Conv_Encoder( input_height=416 , input_width=416 ):
Img_In = Input(shape=(input_height,input_width , 3 ))
# 416,416,3 -> 208,208,64
Img_Conv = Conv2D(64, (3, 3), activation='relu', padding='same', name='Conv1_layer1')(Img_In)
Img_Conv = Conv2D(64, (3, 3), activation='relu', padding='same', name='Conv1_layer2')(Img_Conv)
Img_Conv = MaxPooling2D((2, 2), strides=(2, 2), name='MaxPooling_layer1')(Img_Conv)
layers1 = Img_Conv
# 208,208,64 -> 128,128,128
Img_Conv = Conv2D(128, (3, 3), activation='relu', padding='same', name='Conv2_layer1')(Img_Conv)
Img_Conv = Conv2D(128, (3, 3), activation='relu', padding='same', name='Conv2_layer2')(Img_Conv)
Img_Conv = MaxPooling2D((2, 2), strides=(2, 2), name='MaxPooling_layer2')(Img_Conv)
layers2 = Img_Conv
# 104,104,128 -> 52,52,256
Img_Conv = Conv2D(256, (3, 3), activation='relu', padding='same', name='Conv3_layer1')(Img_Conv)
Img_Conv = Conv2D(256, (3, 3), activation='relu', padding='same', name='Conv3_layer2')(Img_Conv)
Img_Conv = Conv2D(256, (3, 3), activation='relu', padding='same', name='Conv3_layer3')(Img_Conv)
Img_Conv = MaxPooling2D((2, 2), strides=(2, 2), name='MaxPooling_layer3')(Img_Conv)
layers3 = Img_Conv
# 52,52,256 -> 26,26,512
Img_Conv = Conv2D(512, (3, 3), activation='relu', padding='same', name='Conv4_layer1')(Img_Conv)
Img_Conv = Conv2D(512, (3, 3), activation='relu', padding='same', name='Conv4_layer2')(Img_Conv)
Img_Conv = Conv2D(512, (3, 3), activation='relu', padding='same', name='Conv4_layer3')(Img_Conv)
Img_Conv = MaxPooling2D((2, 2), strides=(2, 2), name='MaxPooling_layer4')(Img_Conv)
layers4 = Img_Conv
# 26,26,512 -> 13,13,1024
Img_Conv = Conv2D(512, (3, 3), activation='relu', padding='same', name='Conv5_layer1')(Img_Conv)
Img_Conv = Conv2D(512, (3, 3), activation='relu', padding='same', name='Conv5_layer2')(Img_Conv)
Img_Conv = Conv2D(512, (3, 3), activation='relu', padding='same', name='Conv5_layer3')(Img_Conv)
Img_Conv = MaxPooling2D((2, 2), strides=(2, 2), name='MaxPooling_layer5')(Img_Conv)
layers5 = Img_Conv
#经过五次压缩后,图片被压缩至13*13*512,将最后压缩后的结果与每一层压缩后的结果一起返回给解码器
return Img_In , [layers1 , layers2 , layers3 , layers4 , layers5 ]
2.Decoder
from keras.models import *
from keras.layers import *
from nets.convnet import Conv_Encoder
def Conv_Decoder( layer , classNum , Top=3 ):
#数据格式
IMAGE_ORDERING = 'channels_last'
assert Top >= 3
Get_Layer = layer
# 13*13*1024
# 上采样,长宽变为原来的1/16
# 26*26*512
Get_Layer = ( ZeroPadding2D( (1,1) , data_format=IMAGE_ORDERING ))(Get_Layer)
Get_Layer = ( Conv2D(512, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(Get_Layer)
Get_Layer = ( BatchNormalization())(Get_Layer)
# 长宽变为原来的1/16
# 52*52*256
Get_Layer = ( UpSampling2D( (2,2), data_format=IMAGE_ORDERING))(Get_Layer)
Get_Layer = ( ZeroPadding2D( (1,1), data_format=IMAGE_ORDERING))(Get_Layer)
Get_Layer = ( Conv2D( 256, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(Get_Layer)
Get_Layer = ( BatchNormalization())(Get_Layer)
# 长宽变为原来的1/4
# 104,104,128
Get_Layer = ( UpSampling2D((2,2) , data_format=IMAGE_ORDERING ) )(Get_Layer)
Get_Layer = ( ZeroPadding2D((1,1) , data_format=IMAGE_ORDERING ))(Get_Layer)
Get_Layer = ( Conv2D( 128 , (3, 3), padding='valid' , data_format=IMAGE_ORDERING ))(Get_Layer)
Get_Layer = ( BatchNormalization())(Get_Layer)
# 上采样,此时hw变为原来的1/2
# 208,208,64
Get_Layer = ( UpSampling2D((2,2) , data_format=IMAGE_ORDERING ))(Get_Layer)
Get_Layer = ( ZeroPadding2D((1,1) , data_format=IMAGE_ORDERING ))(Get_Layer)
Get_Layer = ( Conv2D( 64 , (3, 3), padding='valid' , data_format=IMAGE_ORDERING ))(Get_Layer)
Get_Layer = ( BatchNormalization())(Get_Layer)
# 最后通过卷积调整通道数为类别数 即208,208,2
Result = Conv2D( classNum , (3, 3) , padding='same', data_format=IMAGE_ORDERING )( Get_Layer )
return Result
def Get_Conv( classNum , Conv , input_height=416, input_width=416 , Conv_Level=3):
#获取shape
Img_In , levels = Conv( input_height=input_height , input_width=input_width )
# 获取卷积压缩后的特征层
Conv_Result = levels[Conv_Level]
# 将特征传入解码函数
temp = Conv_Decoder(Conv_Result, classNum, Top=4 )
# 将结果进行reshape,经过softmax最后输出model
temp = Reshape((int(input_height/2)*int(input_width/2), -1))(temp)
temp = Softmax()(temp)
model = Model(Img_In,temp)
return model
def convnet_segnet( classNum , input_height=224, input_width=224 , Conv_Level=4):
#五次压缩,有五个特征层,Conv_Level设为4
model = Get_Conv( classNum , Conv_Encoder , input_height=input_height, input_width=input_width , encoder_level=Conv_Level)
model.model_name = "Conv_Model"
return model
3.分割效果
![](https://i-blog.csdnimg.cn/blog_migrate/cb762b211cbae41124dd4fd959fe515b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/27d8ed48a288d346cec620cb6bea1acb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/99b27d66acca65835177d8b4e03a613b.png)