240 lines
9.3 KiB
Python
240 lines
9.3 KiB
Python
from __future__ import print_function
|
|
from __future__ import absolute_import
|
|
|
|
from keras.layers import Input, Activation, Add
|
|
from keras.layers import Conv2D, MaxPooling2D, ZeroPadding2D
|
|
from keras.layers import BatchNormalization
|
|
from keras. models import Model
|
|
from keras import backend as K
|
|
from keras.utils.data_utils import get_file
|
|
|
|
# TH_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_th_dim_ordering_th_kernels_notop.h5'
|
|
|
|
WEIGHTS_PATH_NO_TOP = ('https://github.com/fchollet/deep-learning-models/'
|
|
'releases/download/v0.2/'
|
|
'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5')
|
|
|
|
|
|
def identity_block(input_tensor, kernel_size, filters, stage, block):
|
|
"""The identity block is the block that has no conv layer at shortcut.
|
|
# Arguments
|
|
input_tensor: input tensor
|
|
kernel_size: default 3, the kernel size of
|
|
middle conv layer at main path
|
|
filters: list of integers, the filters of 3 conv layer at main path
|
|
stage: integer, current stage label, used for generating layer names
|
|
block: 'a','b'..., current block label, used for generating layer names
|
|
# Returns
|
|
Output tensor for the block.
|
|
"""
|
|
filters1, filters2, filters3 = filters
|
|
if K.image_data_format() == 'channels_last':
|
|
bn_axis = 3
|
|
else:
|
|
bn_axis = 1
|
|
conv_name_base = 'res' + str(stage) + block + '_branch'
|
|
bn_name_base = 'bn' + str(stage) + block + '_branch'
|
|
|
|
x = Conv2D(filters1, (1, 1),
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '2a')(input_tensor)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(filters2, kernel_size,
|
|
padding='same',
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '2b')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(filters3, (1, 1),
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '2c')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
|
|
|
|
x = Add()([x, input_tensor])
|
|
x = Activation('relu')(x)
|
|
return x
|
|
|
|
|
|
|
|
def conv_block(input_tensor,
|
|
kernel_size,
|
|
filters,
|
|
stage,
|
|
block,
|
|
strides=(2, 2)):
|
|
"""A block that has a conv layer at shortcut.
|
|
# Arguments
|
|
input_tensor: input tensor
|
|
kernel_size: default 3, the kernel size of
|
|
middle conv layer at main path
|
|
filters: list of integers, the filters of 3 conv layer at main path
|
|
stage: integer, current stage label, used for generating layer names
|
|
block: 'a','b'..., current block label, used for generating layer names
|
|
strides: Strides for the first conv layer in the block.
|
|
# Returns
|
|
Output tensor for the block.
|
|
Note that from stage 3,
|
|
the first conv layer at main path is with strides=(2, 2)
|
|
And the shortcut should have strides=(2, 2) as well
|
|
"""
|
|
filters1, filters2, filters3 = filters
|
|
if K.image_data_format() == 'channels_last':
|
|
bn_axis = 3
|
|
else:
|
|
bn_axis = 1
|
|
conv_name_base = 'res' + str(stage) + block + '_branch'
|
|
bn_name_base = 'bn' + str(stage) + block + '_branch'
|
|
|
|
x = Conv2D(filters1, (1, 1), strides=strides,
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '2a')(input_tensor)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(filters2, kernel_size, padding='same',
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '2b')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(filters3, (1, 1),
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '2c')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
|
|
|
|
shortcut = Conv2D(filters3, (1, 1), strides=strides,
|
|
kernel_initializer='he_normal',
|
|
name=conv_name_base + '1')(input_tensor)
|
|
shortcut = BatchNormalization(
|
|
axis=bn_axis, name=bn_name_base + '1')(shortcut)
|
|
|
|
x = Add()([x, shortcut])
|
|
x = Activation('relu')(x)
|
|
return x
|
|
|
|
|
|
def conv_block_atrous(input_tensor, kernel_size, filters, stage, block, atrous_rate=(2, 2)):
|
|
nb_filter1, nb_filter2, nb_filter3 = filters
|
|
if K.image_data_format() == 'channels_last':
|
|
bn_axis = 3
|
|
else:
|
|
bn_axis = 1
|
|
|
|
conv_name_base = 'res' + str(stage) + block + '_branch'
|
|
bn_name_base = 'bn' + str(stage) + block + '_branch'
|
|
|
|
x = Conv2D(nb_filter1, (1, 1), name=conv_name_base + '2a')(input_tensor)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(nb_filter2, kernel_size, padding='same',dilation_rate=atrous_rate,name=conv_name_base + '2b')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
|
|
|
|
shortcut = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '1')(input_tensor)
|
|
shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut)
|
|
|
|
x = Add()([x, shortcut])
|
|
x = Activation('relu')(x)
|
|
return x
|
|
|
|
|
|
def identity_block_atrous(input_tensor, kernel_size, filters, stage, block, atrous_rate=(2, 2)):
|
|
nb_filter1, nb_filter2, nb_filter3 = filters
|
|
if K.image_data_format() == 'channels_last':
|
|
bn_axis = 3
|
|
else:
|
|
bn_axis = 1
|
|
|
|
conv_name_base = 'res' + str(stage) + block + '_branch'
|
|
bn_name_base = 'bn' + str(stage) + block + '_branch'
|
|
|
|
x = Conv2D(nb_filter1, (1, 1), name=conv_name_base + '2a')(input_tensor)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(nb_filter2, kernel_size, dilation_rate=atrous_rate,
|
|
padding='same', name=conv_name_base + '2b')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
|
|
x = Activation('relu')(x)
|
|
|
|
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c')(x)
|
|
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
|
|
|
|
x = Add()([x, input_tensor])
|
|
x = Activation('relu')(x)
|
|
return x
|
|
|
|
|
|
def dcn_resnet(input_tensor=None):
|
|
input_shape = (None, None, 3)
|
|
|
|
if input_tensor is None:
|
|
img_input = Input(shape=input_shape)
|
|
else:
|
|
if not K.is_keras_tensor(input_tensor):
|
|
img_input = Input(tensor=input_tensor)
|
|
else:
|
|
img_input = input_tensor
|
|
|
|
if K.image_data_format() == 'channels_last':
|
|
bn_axis = 3
|
|
else:
|
|
bn_axis = 1
|
|
|
|
# conv_1
|
|
x = ZeroPadding2D(padding=(3, 3), name='conv1_pad')(img_input)
|
|
x = Conv2D(64, (7, 7),
|
|
strides=(2, 2),
|
|
padding='valid',
|
|
kernel_initializer='he_normal',
|
|
name='conv1')(x)
|
|
x = BatchNormalization(axis=bn_axis, name='bn_conv1')(x)
|
|
x = Activation('relu')(x)
|
|
x = ZeroPadding2D(padding=(1, 1), name='pool1_pad')(x)
|
|
x = MaxPooling2D((3, 3), strides=(2, 2))(x)
|
|
|
|
# conv_2
|
|
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
|
|
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
|
|
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
|
|
|
|
# conv_3
|
|
x = conv_block(x, 3, [128, 128, 512], stage=3, block='a', strides=(2, 2))
|
|
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
|
|
x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
|
|
x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')
|
|
|
|
# conv_4
|
|
x = conv_block_atrous(x, 3, [256, 256, 1024], stage=4, block='a', atrous_rate=(2, 2))
|
|
x = identity_block_atrous(x, 3, [256, 256, 1024], stage=4, block='b', atrous_rate=(2, 2))
|
|
x = identity_block_atrous(x, 3, [256, 256, 1024], stage=4, block='c', atrous_rate=(2, 2))
|
|
x = identity_block_atrous(x, 3, [256, 256, 1024], stage=4, block='d', atrous_rate=(2, 2))
|
|
x = identity_block_atrous(x, 3, [256, 256, 1024], stage=4, block='e', atrous_rate=(2, 2))
|
|
x = identity_block_atrous(x, 3, [256, 256, 1024], stage=4, block='f', atrous_rate=(2, 2))
|
|
|
|
# conv_5
|
|
x = conv_block_atrous(x, 3, [512, 512, 2048], stage=5, block='a', atrous_rate=(4, 4))
|
|
x = identity_block_atrous(x, 3, [512, 512, 2048], stage=5, block='b', atrous_rate=(4, 4))
|
|
x = identity_block_atrous(x, 3, [512, 512, 2048], stage=5, block='c', atrous_rate=(4, 4))
|
|
|
|
# Create model
|
|
model = Model(img_input, x)
|
|
|
|
# Load weights
|
|
|
|
weights_path = get_file(
|
|
'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5',
|
|
WEIGHTS_PATH_NO_TOP,
|
|
cache_subdir='models',
|
|
md5_hash='a268eb855778b3df3c7506639542a6af')
|
|
model.load_weights(weights_path)
|
|
|
|
return model
|