def TinyYOLO(inputs, num_anchors, num_classes): '''Create Tiny YOLO3 Model in Keras''' x1 = compose( YOLOConv2D_BN_Leaky(16, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), YOLOConv2D_BN_Leaky(32, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), YOLOConv2D_BN_Leaky(64, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), YOLOConv2D_BN_Leaky(128, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), YOLOConv2D_BN_Leaky(256, (3, 3)))(inputs) x2 = compose( MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), YOLOConv2D_BN_Leaky(512, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='same'), YOLOConv2D_BN_Leaky(1024, (3, 3)), YOLOConv2D_BN_Leaky(256, (1, 1)))(x1) y1 = compose(YOLOConv2D_BN_Leaky(512, (3, 3)), YOLOConv2D(num_anchors * (num_classes + 5), (1, 1)))(x2) x2 = compose(YOLOConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x2) y2 = compose(Concatenate(), YOLOConv2D_BN_Leaky(256, (3, 3)), YOLOConv2D(num_anchors * (num_classes + 5), (1, 1)))([x2, x1]) return Model(inputs, [y1, y2])
def tiny_yolo_body(inputs, num_anchors, num_classes): '''Create Tiny YOLO_v3 model CNN body in keras.''' x1 = compose( DarknetConv2D_BN_Leaky(16, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), DarknetConv2D_BN_Leaky(32, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), DarknetConv2D_BN_Leaky(64, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), DarknetConv2D_BN_Leaky(128, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), DarknetConv2D_BN_Leaky(256, (3, 3)))(inputs) x2 = compose( MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), DarknetConv2D_BN_Leaky(512, (3, 3)), MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='same'), DarknetConv2D_BN_Leaky(1024, (3, 3)), DarknetConv2D_BN_Leaky(256, (1, 1)))(x1) y1 = compose(DarknetConv2D_BN_Leaky(512, (3, 3)), DarknetConv2D(num_anchors * (num_classes + 5), (1, 1)))(x2) x2 = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x2) y2 = compose(Concatenate(), DarknetConv2D_BN_Leaky(256, (3, 3)), DarknetConv2D(num_anchors * (num_classes + 5), (1, 1)))([x2, x1]) return Model(inputs, [y1, y2])
def make_last_layers(x, num_filters, out_filters): '''6 Conv2D_BN_Leaky layers followed by a Conv2D_linear layer''' x = compose(DarknetConv2D_BN_Leaky(num_filters, (1, 1)), DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), DarknetConv2D_BN_Leaky(num_filters, (1, 1)), DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), DarknetConv2D_BN_Leaky(num_filters, (1, 1)))(x) y = compose(DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), DarknetConv2D(out_filters, (1, 1)))(x) return x, y
def UpperLayer(x, num_filters, out_filters): '''6 Conv2D_BN_Leaky layers followed by Conv2D_Linear layer''' x = compose(YOLOConv2D_BN_Leaky(num_filters, (1, 1)), YOLOConv2D_BN_Leaky(num_filters * 2, (3, 3)), YOLOConv2D_BN_Leaky(num_filters, (1, 1)), YOLOConv2D_BN_Leaky(num_filters * 2, (3, 3)), YOLOConv2D_BN_Leaky(num_filters, (1, 1)))(x) y = compose(YOLOConv2D_BN_Leaky(num_filters * 2, (3, 3)), YOLOConv2D(out_filters, (1, 1)))(x) return x, y
def yolo_body(inputs, num_anchors, num_classes): """Create YOLO_V3 model CNN body in Keras.""" darknet = Model(inputs, darknet_body(inputs)) x, y1 = make_last_layers(darknet.output, 512, num_anchors * (num_classes + 5)) x = compose(DarknetConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, darknet.layers[152].output]) x, y2 = make_last_layers(x, 256, num_anchors * (num_classes + 5)) x = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, darknet.layers[92].output]) x, y3 = make_last_layers(x, 128, num_anchors * (num_classes + 5)) return Model(inputs, [y1, y2, y3])
def DarknetConv2D_BN_Leaky(*args, **kwargs): """Darknet Convolution2D followed by BatchNormalization and LeakyReLU.""" no_bias_kwargs = {'use_bias': False} no_bias_kwargs.update(kwargs) return compose( DarknetConv2D(*args, **no_bias_kwargs), BatchNormalization(), LeakyReLU(alpha=0.1))
def YOLOBody(inputs, num_anchors, num_classes): '''Create YOLO3 Model in Keras''' model = Model(inputs, Body(inputs)) x, y1 = UpperLayer(model.output, 512, num_anchors * (num_classes + 5)) x = compose(YOLOConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, model.layers[152].output]) x, y2 = UpperLayer(x, 256, num_anchors * (num_classes + 5)) x = compose(YOLOConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, model.layers[92].output]) x, y3 = UpperLayer(x, 128, num_anchors * (num_classes + 5)) return Model(inputs, [y1, y2, y3])
def resblock_body(x, num_filters, num_blocks): '''A series of resblocks starting with a downsampling Convolution2D''' # Darknet uses left and top padding instead of 'same' mode x = ZeroPadding2D(((1, 0), (1, 0)))(x) x = DarknetConv2D_BN_Leaky(num_filters, (3, 3), strides=(2, 2))(x) for i in range(num_blocks): y = compose(DarknetConv2D_BN_Leaky(num_filters // 2, (1, 1)), DarknetConv2D_BN_Leaky(num_filters, (3, 3)))(x) x = Add()([x, y]) return x
def ResBlock(x, num_filters, num_blocks): x = ZeroPadding2D(((1, 0), (1, 0)))(x) x = YOLOConv2D_BN_Leaky(num_filters, (3, 3), strides=(2, 2))(x) for i in range(num_blocks): y = compose(YOLOConv2D_BN_Leaky(num_filters // 2, (1, 1)), YOLOConv2D_BN_Leaky(num_filters, (3, 3)))(x) x = Add()([x, y]) return x
def yolo_body_distributed(inputs, num_anchors, num_classes): """Create YOLO_V3 model CNN body in Keras.""" darknet = Model(inputs, darknet_body_distributed(inputs)) with tf.device('/gpu:1'): x, y1 = make_last_layers_distributed(darknet.output, 512, num_anchors*(num_classes+5)) with tf.device('/gpu:0'): x = compose( DarknetConv2D_BN_Leaky(256, (1,1)), UpSampling2D(2))(x) with tf.device('/cpu:0'): x = Concatenate()([x,darknet.layers[152].output]) with tf.device('/gpu:1'): x, y2 = make_last_layers_distributed(x, 256, num_anchors*(num_classes+5)) with tf.device('/gpu:0'): x = compose( DarknetConv2D_BN_Leaky(128, (1,1)), UpSampling2D(2))(x) with tf.device('/cpu:0'): x = Concatenate()([x,darknet.layers[92].output]) with tf.device('/gpu:0'): x, y3 = make_last_layers_distributed(x, 128, num_anchors*(num_classes+5)) return Model(inputs, [y1,y2,y3])
def YOLOConv2D_BN_Leaky(*args, **kwargs): no_bias_kwargs = {'use_bias': False} no_bias_kwargs.update(kwargs) return compose(YOLOConv2D(*args, **no_bias_kwargs), BatchNormalization(), LeakyReLU(alpha=0.1))