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 resblock_body(x, num_filters, num_blocks, all_narrow=True): '''A series of resblocks starting with a downsampling Convolution2D''' # Darknet uses left and top padding instead of 'same' mode preconv1 = ZeroPadding2D(((1, 0), (1, 0)))(x) preconv1 = DarknetConv2D_BN_Mish(num_filters, (3, 3), strides=(2, 2))(preconv1) shortconv = DarknetConv2D_BN_Mish( num_filters // 2 if all_narrow else num_filters, (1, 1))(preconv1) mainconv = DarknetConv2D_BN_Mish( num_filters // 2 if all_narrow else num_filters, (1, 1))(preconv1) for i in range(num_blocks): y = compose( DarknetConv2D_BN_Mish(num_filters // 2, (1, 1)), DarknetConv2D_BN_Mish( num_filters // 2 if all_narrow else num_filters, (3, 3)))(mainconv) mainconv = Add()([mainconv, y]) postconv = DarknetConv2D_BN_Mish( num_filters // 2 if all_narrow else num_filters, (1, 1))(mainconv) route = Concatenate()([postconv, shortconv]) return DarknetConv2D_BN_Mish(num_filters, (1, 1))(route)
def DarknetConv2D_BN_Mish(*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(), Mish())
def yolo4_body(inputs, num_anchors, num_classes): """Create YOLO_V4 model CNN body in Keras.""" darknet = Model(inputs, darknet_body(inputs)) #19x19 head y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(darknet.output) y19 = DarknetConv2D_BN_Leaky(1024, (3, 3))(y19) y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(y19) maxpool1 = MaxPooling2D(pool_size=(13, 13), strides=(1, 1), padding='same')(y19) maxpool2 = MaxPooling2D(pool_size=(9, 9), strides=(1, 1), padding='same')(y19) maxpool3 = MaxPooling2D(pool_size=(5, 5), strides=(1, 1), padding='same')(y19) y19 = Concatenate()([maxpool1, maxpool2, maxpool3, y19]) y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(y19) y19 = DarknetConv2D_BN_Leaky(1024, (3, 3))(y19) y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(y19) y19_upsample = compose(DarknetConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(y19) #38x38 head y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(darknet.layers[204].output) y38 = Concatenate()([y38, y19_upsample]) y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(y38) y38 = DarknetConv2D_BN_Leaky(512, (3, 3))(y38) y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(y38) y38 = DarknetConv2D_BN_Leaky(512, (3, 3))(y38) y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(y38) y38_upsample = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(y38) #76x76 head y76 = DarknetConv2D_BN_Leaky(128, (1, 1))(darknet.layers[131].output) y76 = Concatenate()([y76, y38_upsample]) y76 = DarknetConv2D_BN_Leaky(128, (1, 1))(y76) y76 = DarknetConv2D_BN_Leaky(256, (3, 3))(y76) y76 = DarknetConv2D_BN_Leaky(128, (1, 1))(y76) y76 = DarknetConv2D_BN_Leaky(256, (3, 3))(y76) y76 = DarknetConv2D_BN_Leaky(128, (1, 1))(y76) #76x76 output y76_output = DarknetConv2D_BN_Leaky(256, (3, 3))(y76) y76_output = DarknetConv2D(num_anchors * (num_classes + 5), (1, 1))(y76_output) #38x38 output y76_downsample = ZeroPadding2D(((1, 0), (1, 0)))(y76) y76_downsample = DarknetConv2D_BN_Leaky(256, (3, 3), strides=(2, 2))(y76_downsample) y38 = Concatenate()([y76_downsample, y38]) y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(y38) y38 = DarknetConv2D_BN_Leaky(512, (3, 3))(y38) y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(y38) y38 = DarknetConv2D_BN_Leaky(512, (3, 3))(y38) y38 = DarknetConv2D_BN_Leaky(256, (1, 1))(y38) y38_output = DarknetConv2D_BN_Leaky(512, (3, 3))(y38) y38_output = DarknetConv2D(num_anchors * (num_classes + 5), (1, 1))(y38_output) #19x19 output y38_downsample = ZeroPadding2D(((1, 0), (1, 0)))(y38) y38_downsample = DarknetConv2D_BN_Leaky(512, (3, 3), strides=(2, 2))(y38_downsample) y19 = Concatenate()([y38_downsample, y19]) y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(y19) y19 = DarknetConv2D_BN_Leaky(1024, (3, 3))(y19) y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(y19) y19 = DarknetConv2D_BN_Leaky(1024, (3, 3))(y19) y19 = DarknetConv2D_BN_Leaky(512, (1, 1))(y19) y19_output = DarknetConv2D_BN_Leaky(1024, (3, 3))(y19) y19_output = DarknetConv2D(num_anchors * (num_classes + 5), (1, 1))(y19_output) yolo4_model = Model(inputs, [y19_output, y38_output, y76_output]) return yolo4_model