-
Notifications
You must be signed in to change notification settings - Fork 85
/
encoders.py
176 lines (140 loc) · 5.85 KB
/
encoders.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
from __future__ import (
absolute_import,
unicode_literals
)
import keras
import keras.backend as K
from keras.models import Model
from keras.utils.data_utils import get_file
from keras.utils import layer_utils
from keras_fcn.blocks import (
vgg_conv,
vgg_fc
)
from keras_fcn.backend import load_weights
class Encoder(Model):
"""Encoder for Fully Convolutional Networks.
:param inputs: 4D Tensor, the input tensor
:param blocks: 1D array, list of functional convolutional blocks
:return A Keras Model with outputs including the output of
each block except the final conv block (using the encoder's top instead)
>>> from keras.layers import Input
>>> from keras_fcn.encoders import Encoder
>>> from keras_fcn.blocks import (vgg_conv, vgg_fc)
>>> inputs = Input(shape=(224, 224, 3))
>>> blocks = [vgg_conv(64, 2, 'block1'),
>>> vgg_conv(128, 2, 'block2'),
>>> vgg_conv(256, 3, 'block3'),
>>> vgg_conv(512, 3, 'block4'),
>>> vgg_conv(512, 3, 'block5'),
>>> vgg_fc(4096)]
>>> encoder = Encoder(inputs, blocks, weights='imagenet',
>>> trainable=True)
>>> feat_pyramid = encoder.outputs # A feature pyramid with 5 scales
"""
def __init__(self, inputs, blocks, weights=None,
trainable=True, name='encoder'):
inverse_pyramid = []
# convolutional block
conv_blocks = blocks[:-1]
for i, block in enumerate(conv_blocks):
if i == 0:
x = block(inputs)
inverse_pyramid.append(x)
elif i < len(conv_blocks) - 1:
x = block(x)
inverse_pyramid.append(x)
else:
x = block(x)
# fully convolutional block
fc_block = blocks[-1]
y = fc_block(x)
inverse_pyramid.append(y)
outputs = list(reversed(inverse_pyramid))
super(Encoder, self).__init__(
inputs=inputs, outputs=outputs)
# load pre-trained weights
if weights is not None:
weights_path = get_file(
'{}_weights_tf_dim_ordering_tf_kernels.h5'.format(name),
weights,
cache_subdir='models')
layer_names = load_weights(self, weights_path)
if K.image_data_format() == 'channels_first':
layer_utils.convert_all_kernels_in_model(self)
# Freezing basenet weights
if trainable is False:
for layer in self.layers:
if layer.name in layer_names:
layer.trainable = False
class VGGEncoder(Encoder):
"""VGG VGGEncoder.
:param inputs: 4D Tensor, the input tensor
:param filters: 1D array, number of filters per block
:param convs: 1D array, number of convolutional layers per block, with
length the same as `filters`.
:return A Keras Model with outputs including the output of
each block except `pool5` (using drop7 from `pool5` instead)
>>> from keras_fcn.encoders import VGGEncoder
>>> from keras.layers import Input
>>> x = Input(shape=(224, 224, 3))
>>> encoder = VGGEncoder(Input(x),
>>> filters=[64, 128, 256, 512, 512],
>>> convs=[2, 2, 3, 3, 3])
>>> feat_pyramid = encoder.outputs
"""
def __init__(self, inputs, filters, convs, weight_decay=0.,
weights=None, trainable=True):
blocks = []
# Convolutional blocks
for i, (fltr, conv) in enumerate(zip(filters, convs)):
block_name = 'block{}'.format(i + 1)
block = vgg_conv(filters=fltr, convs=conv, padding=False,
weight_decay=weight_decay,
block_name=block_name)
blocks.append(block)
# Fully Convolutional block
fc_block = vgg_fc(filters=4096, weight_decay=weight_decay)
blocks.append(fc_block)
super(VGGEncoder, self).__init__(inputs=inputs, blocks=blocks,
weights=weights, trainable=trainable)
class VGG16(VGGEncoder):
"""A VGG16 feature encoder.
>>> from keras_fcn.encoders import VGG16
>>> from keras.layers import Input
>>> x = Input(shape=(224, 224, 3))
>>> encoder = VGG16(x)
>>> feat_pyramid = encoder.outputs
"""
def __init__(self, inputs, weight_decay=0.,
weights='imagenet', trainable=True):
if weights == 'imagenet':
weights = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
else:
weights = None
super(VGG16, self).__init__(inputs,
filters=[64, 128, 256, 512, 512],
convs=[2, 2, 3, 3, 3],
weight_decay=weight_decay,
weights=weights,
trainable=trainable)
class VGG19(VGGEncoder):
"""VGG19 net.
>>> from keras_fcn.encoders import VGG19
>>> from keras.layers import Input
>>> x = Input(shape=(224, 224, 3))
>>> encoder = VGG19(x)
>>> feat_pyramids = encoder.outputs
"""
def __init__(self, inputs, weight_decay=0.,
weights='imagenet', trainable=True):
if weights == 'imagenet':
weights = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5'
else:
weights = None
super(VGG19, self).__init__(inputs,
filters=[64, 128, 256, 512, 512],
convs=[2, 2, 4, 4, 4],
weight_decay=weight_decay,
weights=weights,
trainable=trainable)