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 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 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 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