forked from shaoanlu/faceswap-GAN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FCN8s_keras.py
131 lines (123 loc) · 6.31 KB
/
FCN8s_keras.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from keras.models import Sequential, Model
from keras.layers import *
from keras.layers.advanced_activations import LeakyReLU
from keras.activations import relu
from keras.initializers import RandomNormal
from keras.applications import *
import keras.backend as K
def FCN(num_output=21, input_shape=(500, 500, 3)):
"""Instantiate the FCN8s architecture with keras.
# Arguments
basenet: type of basene {'vgg16'}
trainable_base: Bool whether the basenet weights are trainable
num_output: number of classes
input_shape: input image shape
weights: pre-trained weights to load (None for training from scratch)
# Returns
A Keras model instance
"""
ROW_AXIS = 1
COL_AXIS = 2
CHANNEL_AXIS = 3
def _crop(target_layer, offset=(None, None), name=None):
"""Crop the bottom such that it has the same shape as target_layer."""
""" Use _keras_shape to prevent undefined output shape in Conv2DTranspose"""
def f(x):
width = x._keras_shape[ROW_AXIS]
height = x._keras_shape[COL_AXIS]
target_width = target_layer._keras_shape[ROW_AXIS]
target_height = target_layer._keras_shape[COL_AXIS]
cropped = Cropping2D(cropping=((offset[0], width - offset[0] - target_width), (offset[1], height - offset[1] - target_height)), name='{}'.format(name))(x)
return cropped
return f
input_tensor = Input(shape=input_shape)
pad1 = ZeroPadding2D(padding=(100, 100))(input_tensor)
conv1_1 = Conv2D(filters=64, kernel_size=(3, 3), activation='relu',
padding='valid', name='conv1_1')(pad1)
conv1_2 = Conv2D(filters=64, kernel_size=(3, 3), activation='relu',
padding='same', name='conv1_2')(conv1_1)
pool1 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
padding='same', name='pool1')(conv1_2)
# Block 2
conv2_1 = Conv2D(filters=128, kernel_size=(3, 3),
activation='relu',
padding='same', name='conv2_1')(pool1)
conv2_2 = Conv2D(filters=128, kernel_size=(3, 3), activation='relu',
padding='same', name='conv2_2')(conv2_1)
pool2 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
padding='same', name='pool2')(conv2_2)
# Block 3
conv3_1 = Conv2D(filters=256, kernel_size=(3, 3), activation='relu',
padding='same', name='conv3_1')(pool2)
conv3_2 = Conv2D(filters=256, kernel_size=(3, 3), activation='relu',
padding='same', name='conv3_2')(conv3_1)
conv3_3 = Conv2D(filters=256, kernel_size=(3, 3), activation='relu',
padding='same', name='conv3_3')(conv3_2)
pool3 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
padding='same', name='pool3')(conv3_3)
# Block 4
conv4_1 = Conv2D(filters=512, kernel_size=(3, 3), activation='relu',
padding='same', name='conv4_1')(pool3)
conv4_2 = Conv2D(filters=512, kernel_size=(3, 3), activation='relu',
padding='same', name='conv4_2')(conv4_1)
conv4_3 = Conv2D(filters=512, kernel_size=(3, 3), activation='relu',
padding='same', name='conv4_3')(conv4_2)
pool4 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
padding='same', name='pool4')(conv4_3)
# Block 5
conv5_1 = Conv2D(filters=512, kernel_size=(3, 3), activation='relu',
padding='same', name='conv5_1')(pool4)
conv5_2 = Conv2D(filters=512, kernel_size=(3, 3), activation='relu',
padding='same', name='conv5_2')(conv5_1)
conv5_3 = Conv2D(filters=512, kernel_size=(3, 3), activation='relu',
padding='same', name='conv5_3')(conv5_2)
pool5 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
padding='same', name='pool5')(conv5_3)
# fully conv
fc6 = Conv2D(filters=4096, kernel_size=(7, 7),
activation='relu', padding='valid',
name='fc6')(pool5)
drop6 = Dropout(0.5)(fc6)
fc7 = Conv2D(filters=4096, kernel_size=(1, 1),
activation='relu', padding='valid',
name='fc7')(drop6)
drop7 = Dropout(0.5)(fc7)
#basenet = VGG16_basenet()
# input
#input_tensor = Input(shape=input_shape)
# Get skip_layers=[drop7, pool4, pool3] from the base net: VGG16
#skip_layers = VGG16_basenet(input_tensor)
#drop7 = skip_layers[0]
score_fr = Conv2D(filters=num_output, kernel_size=(1, 1), padding='valid', name='score_fr')(drop7)
upscore2 = Conv2DTranspose(num_output, kernel_size=4, strides=2, use_bias=False, name='upscore2')(score_fr)
# scale pool4 skip for compatibility
#pool4 = skip_layers[1]
scale_pool4 = Lambda(lambda x: x * 0.01, name='scale_pool4')(pool4)
score_pool4 = Conv2D(filters=num_output, kernel_size=(1, 1),
padding='valid', name='score_pool4')(scale_pool4)
score_pool4c = _crop(upscore2, offset=(5, 5),
name='score_pool4c')(score_pool4)
fuse_pool4 = add([upscore2, score_pool4c])
upscore_pool4 = Conv2DTranspose(filters=num_output, kernel_size=(4, 4),
strides=(2, 2), padding='valid',
use_bias=False,
data_format=K.image_data_format(),
name='upscore_pool4')(fuse_pool4)
# scale pool3 skip for compatibility
#pool3 = skip_layers[2]
scale_pool3 = Lambda(lambda x: x * 0.0001, name='scale_pool3')(pool3)
score_pool3 = Conv2D(filters=num_output, kernel_size=(1, 1),
padding='valid', name='score_pool3')(scale_pool3)
score_pool3c = _crop(upscore_pool4, offset=(9, 9),
name='score_pool3c')(score_pool3)
fuse_pool3 = add([upscore_pool4, score_pool3c])
# score
upscore8 = Conv2DTranspose(filters=num_output, kernel_size=(16, 16),
strides=(8, 8), padding='valid',
use_bias=False,
data_format=K.image_data_format(),
name='upscore8')(fuse_pool3)
score = _crop(input_tensor, offset=(31, 31), name='score')(upscore8)
# model
model = Model(input_tensor, score, name='fcn_vgg16')
return model