diff --git a/yolov3.py b/yolov3.py index 5e79a10..0fa0d13 100644 --- a/yolov3.py +++ b/yolov3.py @@ -48,7 +48,7 @@ class WeightReader: def load_weights(self, model): """ - Load weights into created model + Load weights into created model. """ for i in range(106): try: @@ -81,21 +81,26 @@ class WeightReader: def reset(self): """ - Resets offset to restart loading weights + Resets offset to restart loading weights. """ self.offset = 0 # Step 2: -# _conv_block(input, convs, skip=True) is a function to create convolutional layer def _conv_block(input_layer, convs, skip=True): + """ + Function to create convolutional layer. + """ tmp = input_layer count = 0 for conv in convs: if count == (len(convs) - 2) and skip: skip_connection = tmp count += 1 + # Peculiar padding as darknet prefer left and top - if conv['stride'] > 1: tmp = ZeroPadding2D(((1,0),(1,0)))(tmp) + if conv['stride'] > 1: + tmp = ZeroPadding2D(((1,0),(1,0)))(tmp) + tmp = Conv2D(conv['filter'], conv['kernel'], strides=conv['stride'], @@ -104,99 +109,100 @@ def _conv_block(input_layer, convs, skip=True): name='conv_' + str(conv['layer_idx']), use_bias=False if conv['bnorm'] else True)(tmp) - if conv['bnorm']: tmp = BatchNormalization(epsilon=0.001, name='bnorm_' - + str(conv['layer_idx']))(tmp) - if conv['leaky']: tmp = LeakyReLU(alpha=0.1, name='leaky_' - + str(conv['layer_idx']))(tmp) + if conv['bnorm']: + tmp = BatchNormalization(epsilon=0.001, name='bnorm_' + str(conv['layer_idx']))(tmp) + if conv['leaky']: + tmp = LeakyReLU(alpha=0.1, name='leaky_' + str(conv['layer_idx']))(tmp) return add([skip_connection, tmp]) if skip else tmp -# make_yolov3_model() is a function to create layers of convoluational and stack together as a -# whole yolo model def make_yolov3_model(): + """ + Function to create layers of convoluational and stack together as a whole yolo model. + """ input_image = Input(shape=(None, None, 3)) # Layer 0 => 4 - x = _conv_block(input_image, - [{'filter': 32, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 0}, - {'filter': 64, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 1}, - {'filter': 32, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 2}, - {'filter': 64, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 3}]) + tmp = _conv_block(input_image, + [{'filter': 32, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 0}, + {'filter': 64, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 1}, + {'filter': 32, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 2}, + {'filter': 64, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 3}]) # Layer 5 => 8 - x = _conv_block(x, - [{'filter': 128, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 5}, - {'filter': 64, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 6}, - {'filter': 128, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 7}]) + tmp = _conv_block(tmp, + [{'filter': 128, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 5}, + {'filter': 64, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 6}, + {'filter': 128, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 7}]) # Layer 9 => 11 - x = _conv_block(x, - [{'filter': 64, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 9}, - {'filter': 128, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 10}]) + tmp = _conv_block(tmp, + [{'filter': 64, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 9}, + {'filter': 128, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 10}]) # Layer 12 => 15 - x = _conv_block(x, - [{'filter': 256, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 12}, - {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 13}, - {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 14}]) + tmp = _conv_block(tmp, + [{'filter': 256, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 12}, + {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 13}, + {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 14}]) # Layer 16 => 36 for i in range(7): - x = _conv_block(x, - [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 16+i*3}, - {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 17+i*3}]) - skip_36 = x + tmp = _conv_block(tmp, + [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 16+i*3}, + {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 17+i*3}]) + skip_36 = tmp # Layer 37 => 40 - x = _conv_block(x, - [{'filter': 512, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 37}, - {'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 38}, - {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 39}]) + tmp = _conv_block(tmp, + [{'filter': 512, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 37}, + {'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 38}, + {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 39}]) # Layer 41 => 61 for i in range(7): - x = _conv_block(x, - [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 41+i*3}, - {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 42+i*3}]) - skip_61 = x + tmp = _conv_block(tmp, + [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 41+i*3}, + {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 42+i*3}]) + skip_61 = tmp # Layer 62 => 65 - x = _conv_block(x, - [{'filter': 1024, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 62}, - {'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 63}, - {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 64}]) + tmp = _conv_block(tmp, + [{'filter': 1024, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 62}, + {'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 63}, + {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 64}]) # Layer 66 => 74 for i in range(3): - x = _conv_block(x, - [{'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 66+i*3}, - {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 67+i*3}]) + tmp = _conv_block(tmp, + [{'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 66+i*3}, + {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 67+i*3}]) # Layer 75 => 79 - x = _conv_block(x, - [{'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 75}, - {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 76}, - {'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 77}, - {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 78}, - {'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 79}], - skip=False) + tmp = _conv_block(tmp, + [{'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 75}, + {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 76}, + {'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 77}, + {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 78}, + {'filter': 512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 79}], + skip=False) # Layer 80 => 82 - yolo_82 = _conv_block(x, + yolo_82 = _conv_block(tmp, [{'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 80}, {'filter': 255, 'kernel': 1, 'stride': 1, 'bnorm': False, 'leaky': False, 'layer_idx': 81}], skip=False) # Layer 83 => 86 - x = _conv_block(x, - [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 84}], - skip=False) + tmp = _conv_block(tmp, + [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 84}], + skip=False) - x = UpSampling2D(2)(x) - x = concatenate([x, skip_61]) + tmp = UpSampling2D(2)(tmp) + tmp = concatenate([tmp, skip_61]) # Layer 87 => 91 - x = _conv_block(x, + tmp = _conv_block(tmp, [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 87}, {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 88}, {'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 89}, @@ -205,21 +211,21 @@ def make_yolov3_model(): skip=False) # Layer 92 => 94 - yolo_94 = _conv_block(x, + yolo_94 = _conv_block(tmp, [{'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 92}, {'filter': 255, 'kernel': 1, 'stride': 1, 'bnorm': False, 'leaky': False, 'layer_idx': 93}], skip=False) # Layer 95 => 98 - x = _conv_block(x, - [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 96}], - skip=False) + tmp = _conv_block(tmp, + [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 96}], + skip=False) - x = UpSampling2D(2)(x) - x = concatenate([x, skip_36]) + tmp = UpSampling2D(2)(tmp) + tmp = concatenate([tmp, skip_36]) # Layer 99 => 106 - yolo_106 = _conv_block(x, + yolo_106 = _conv_block(tmp, [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 99}, {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 100}, {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 101}, @@ -233,33 +239,35 @@ def make_yolov3_model(): return model -"""**step 4:** Prediction - by loading the image to model and make prediction -""" - +# Step 4: +# Prediction def load_image_pixels(filename, shape): - # load image to get its shape + """ + Loading the image to model and make prediction + """ + + # Load image to get its shape image = load_img(filename) width, height = image.size - # load image with required size + # Load image with required size image = load_img(filename, target_size=shape) image = img_to_array(image) - # grayscale image normalization + # Grayscale image normalization image = image.astype('float32') image /= 255.0 - # add a dimension so that we have one sample + # Add a dimension so that we have one sample image = expand_dims(image, 0) return image, width, height -"""**Step 4:** Decode the prediction output to rectangle coordinates -- `BoundBox` class is used to return object bounding box coordinates, object name and threshold score -- `decode_netout` function is used to decode the prediction output to rectangle coordinates -""" - +# Step 4: Decode the prediction output to rectangle coordinates class BoundBox: + """ + BoundBox class is used to return object bounding box coordinates, object name and threshold + score decode_netout` function is used to decode the prediction output to rectangle coordinates + """ def __init__(self, xmin, ymin, xmax, ymax, objness = None, classes = None): self.xmin = xmin self.ymin = ymin