From 13e6adc274c408a6f1fed83b836b7e6452024d93 Mon Sep 17 00:00:00 2001 From: aditya-5842 Date: Sat, 27 Mar 2021 03:45:36 +0530 Subject: [PATCH 1/2] yolov4-tiny-3l issue resolved --- convert_tflite.py | 1 + core/backbone.py | 43 ++++++++++++++++++++++++++++++++++++++++++ core/config.py | 8 ++++++-- core/utils.py | 25 +++++++++++++++++------- core/yolov4.py | 30 +++++++++++++++++++++++++++++ data/classes/obj.names | 1 + save_model.py | 26 ++++++++++++++++++------- 7 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 data/classes/obj.names diff --git a/convert_tflite.py b/convert_tflite.py index 8d45ca58..ed9c0032 100644 --- a/convert_tflite.py +++ b/convert_tflite.py @@ -36,6 +36,7 @@ def save_tflite(): converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS] converter.allow_custom_ops = True elif FLAGS.quantize_mode == 'int8': + converter.experimental_new_converter = False converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS] diff --git a/core/backbone.py b/core/backbone.py index 6108498b..142aa6c8 100644 --- a/core/backbone.py +++ b/core/backbone.py @@ -146,6 +146,49 @@ def cspdarknet53_tiny(input_data): return route_1, input_data +def cspdarknet53_tiny_3l(input_data): + input_data = common.convolutional(input_data, (3, 3, 3, 32), downsample=True) + input_data = common.convolutional(input_data, (3, 3, 32, 64), downsample=True) + input_data = common.convolutional(input_data, (3, 3, 64, 64)) + + route = input_data + input_data = common.route_group(input_data, 2, 1) + input_data = common.convolutional(input_data, (3, 3, 32, 32)) + route_1 = input_data + input_data = common.convolutional(input_data, (3, 3, 32, 32)) + input_data = tf.concat([input_data, route_1], axis=-1) + input_data = common.convolutional(input_data, (1, 1, 64, 64)) + input_data = tf.concat([route, input_data], axis=-1) + input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) + + input_data = common.convolutional(input_data, (3, 3, 128, 128)) + route = input_data + input_data = common.route_group(input_data, 2, 1) + input_data = common.convolutional(input_data, (3, 3, 64, 64)) + route_1 = input_data + input_data = common.convolutional(input_data, (3, 3, 64, 64)) + input_data = tf.concat([input_data, route_1], axis=-1) + input_data = common.convolutional(input_data, (1, 1, 128, 128)) + route_2 = input_data + input_data = tf.concat([route, input_data], axis=-1) + input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) + + input_data = common.convolutional(input_data, (3, 3, 256, 256)) + route = input_data + input_data = common.route_group(input_data, 2, 1) + input_data = common.convolutional(input_data, (3, 3, 128, 128)) + route_1 = input_data + input_data = common.convolutional(input_data, (3, 3, 128, 128)) + input_data = tf.concat([input_data, route_1], axis=-1) + input_data = common.convolutional(input_data, (1, 1, 256, 256)) + route_1 = input_data + input_data = tf.concat([route, input_data], axis=-1) + input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) + + input_data = common.convolutional(input_data, (3, 3, 512, 512)) + + return route_1, route_2, input_data + def darknet53_tiny(input_data): input_data = common.convolutional(input_data, (3, 3, 3, 16)) input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) diff --git a/core/config.py b/core/config.py index 7ea25ff6..b973075b 100644 --- a/core/config.py +++ b/core/config.py @@ -11,14 +11,18 @@ # YOLO options __C.YOLO = edict() -__C.YOLO.CLASSES = "./data/classes/coco.names" +__C.YOLO.CLASSES = "./data/classes/obj.names" __C.YOLO.ANCHORS = [12,16, 19,36, 40,28, 36,75, 76,55, 72,146, 142,110, 192,243, 459,401] __C.YOLO.ANCHORS_V3 = [10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326] -__C.YOLO.ANCHORS_TINY = [23,27, 37,58, 81,82, 81,82, 135,169, 344,319] +# __C.YOLO.ANCHORS_TINY = [23,27, 37,58, 81,82, 81,82, 135,169, 344,319] +__C.YOLO.ANCHORS_TINY = [10,14, 23,27, 37,58, 81,82, 135,169, 344,319] +__C.YOLO.ANCHORS_TINY_3l = [12,16, 19,36, 40,28, 36,75, 76,55, 72,146, 142,110, 192,243, 459,401] __C.YOLO.STRIDES = [8, 16, 32] __C.YOLO.STRIDES_TINY = [16, 32] +__C.YOLO.STRIDES_TINY_3l = [8, 16, 32] __C.YOLO.XYSCALE = [1.2, 1.1, 1.05] __C.YOLO.XYSCALE_TINY = [1.05, 1.05] +__C.YOLO.XYSCALE_TINY_3l = [1.05, 1.05, 1.05] __C.YOLO.ANCHOR_PER_SCALE = 3 __C.YOLO.IOU_LOSS_THRESH = 0.5 diff --git a/core/utils.py b/core/utils.py index 87f7d158..481d2470 100644 --- a/core/utils.py +++ b/core/utils.py @@ -23,6 +23,9 @@ def load_weights(model, weights_file, model_name='yolov4', is_tiny=False): if model_name == 'yolov3': layer_size = 13 output_pos = [9, 12] + elif model_name == 'yolov4-tiny-3l': + layer_size = 24 + output_pos = [17, 20, 23] else: layer_size = 21 output_pos = [17, 20] @@ -81,24 +84,32 @@ def read_class_names(class_file_name): def load_config(FLAGS): if FLAGS.tiny: - STRIDES = np.array(cfg.YOLO.STRIDES_TINY) - ANCHORS = get_anchors(cfg.YOLO.ANCHORS_TINY, FLAGS.tiny) - XYSCALE = cfg.YOLO.XYSCALE_TINY if FLAGS.model == 'yolov4' else [1, 1] + if FLAGS.model == 'yolov4-tiny-3l': + STRIDES = np.array(cfg.YOLO.STRIDES_TINY_3l) + ANCHORS = get_anchors(cfg.YOLO.ANCHORS_TINY_3l, FLAGS.tiny, FLAGS.model) + XYSCALE = cfg.YOLO.XYSCALE_TINY_3l + else: + STRIDES = np.array(cfg.YOLO.STRIDES_TINY) + ANCHORS = get_anchors(cfg.YOLO.ANCHORS_TINY, FLAGS.tiny, FLAGS.model) + XYSCALE = cfg.YOLO.XYSCALE_TINY if FLAGS.model == 'yolov4' else [1, 1] else: STRIDES = np.array(cfg.YOLO.STRIDES) if FLAGS.model == 'yolov4': - ANCHORS = get_anchors(cfg.YOLO.ANCHORS, FLAGS.tiny) + ANCHORS = get_anchors(cfg.YOLO.ANCHORS, FLAGS.tiny, FLAGS.model) elif FLAGS.model == 'yolov3': - ANCHORS = get_anchors(cfg.YOLO.ANCHORS_V3, FLAGS.tiny) + ANCHORS = get_anchors(cfg.YOLO.ANCHORS_V3, FLAGS.tiny, FLAGS.model) XYSCALE = cfg.YOLO.XYSCALE if FLAGS.model == 'yolov4' else [1, 1, 1] NUM_CLASS = len(read_class_names(cfg.YOLO.CLASSES)) return STRIDES, ANCHORS, NUM_CLASS, XYSCALE -def get_anchors(anchors_path, tiny=False): +def get_anchors(anchors_path, tiny=False, model='yolov4'): anchors = np.array(anchors_path) if tiny: - return anchors.reshape(2, 3, 2) + if model == 'yolov4-tiny-3l': + return anchors.reshape(3, 3, 2) + else: + return anchors.reshape(2, 3, 2) else: return anchors.reshape(3, 3, 2) diff --git a/core/yolov4.py b/core/yolov4.py index 1edd656d..486a7e42 100644 --- a/core/yolov4.py +++ b/core/yolov4.py @@ -18,6 +18,13 @@ def YOLO(input_layer, NUM_CLASS, model='yolov4', is_tiny=False): if is_tiny: if model == 'yolov4': return YOLOv4_tiny(input_layer, NUM_CLASS) + elif model == 'yolov4-tiny-3l': + print("#"*100) + print("\n"*5) + print("loading tiny-3l") + print("\n"*5) + print("#"*100) + return YOLOv4_tiny_3l(input_layer, NUM_CLASS) elif model == 'yolov3': return YOLOv3_tiny(input_layer, NUM_CLASS) else: @@ -143,6 +150,29 @@ def YOLOv4_tiny(input_layer, NUM_CLASS): return [conv_mbbox, conv_lbbox] +def YOLOv4_tiny_3l(input_layer, NUM_CLASS): + route_1, route_2, conv = backbone.cspdarknet53_tiny_3l(input_layer) + + conv = common.convolutional(conv, (1, 1, 512, 256)) + + conv_lobj_branch = common.convolutional(conv, (3, 3, 256, 512)) + conv_lbbox = common.convolutional(conv_lobj_branch, (1, 1, 512, 3 * (NUM_CLASS + 5)), activate=False, bn=False) + + conv = common.convolutional(conv, (1, 1, 256, 128)) + conv = common.upsample(conv) + conv = tf.concat([conv, route_1], axis=-1) + + conv = common.convolutional(conv, (3, 3, 384, 256)) + conv_mbbox = common.convolutional(conv, (1, 1, 256, 3 * (NUM_CLASS + 5)), activate=False, bn=False) + + conv = common.convolutional(conv, (1, 1, 256, 64)) + conv = common.upsample(conv) + conv = tf.concat([conv, route_2], axis=-1) + + conv_sobj_branch = common.convolutional(conv, (3, 3, 192, 128)) + conv_sbbox = common.convolutional(conv_sobj_branch, (1, 1, 128, 3 * (NUM_CLASS + 5)), activate=False, bn=False) + return [conv_sbbox, conv_mbbox, conv_lbbox] + def YOLOv3_tiny(input_layer, NUM_CLASS): route_1, conv = backbone.darknet53_tiny(input_layer) diff --git a/data/classes/obj.names b/data/classes/obj.names new file mode 100644 index 00000000..dc61934f --- /dev/null +++ b/data/classes/obj.names @@ -0,0 +1 @@ +license_plate \ No newline at end of file diff --git a/save_model.py b/save_model.py index 5946c554..6145bed8 100644 --- a/save_model.py +++ b/save_model.py @@ -21,13 +21,25 @@ def save_tf(): bbox_tensors = [] prob_tensors = [] if FLAGS.tiny: - for i, fm in enumerate(feature_maps): - if i == 0: - output_tensors = decode(fm, FLAGS.input_size // 16, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) - else: - output_tensors = decode(fm, FLAGS.input_size // 32, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) - bbox_tensors.append(output_tensors[0]) - prob_tensors.append(output_tensors[1]) + if FLAGS.model == 'yolov4-tiny-3l': + for i, fm in enumerate(feature_maps): + # import pdb; pdb.set_trace() + if i == 0: + output_tensors = decode(fm, FLAGS.input_size // 8, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) + elif i == 1: + output_tensors = decode(fm, FLAGS.input_size // 16, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) + else: + output_tensors = decode(fm, FLAGS.input_size // 32, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) + bbox_tensors.append(output_tensors[0]) + prob_tensors.append(output_tensors[1]) + else: + for i, fm in enumerate(feature_maps): + if i == 0: + output_tensors = decode(fm, FLAGS.input_size // 16, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) + else: + output_tensors = decode(fm, FLAGS.input_size // 32, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE, FLAGS.framework) + bbox_tensors.append(output_tensors[0]) + prob_tensors.append(output_tensors[1]) else: for i, fm in enumerate(feature_maps): if i == 0: From dbebe3c52297744e897b5b17babec078e01de833 Mon Sep 17 00:00:00 2001 From: aditya-5842 Date: Sat, 27 Mar 2021 04:05:33 +0530 Subject: [PATCH 2/2] updated the readme --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 8b6da877..2eea933c 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,11 @@ python detect.py --weights ./checkpoints/yolov4-416 --size 416 --model yolov4 -- python detect.py --weights ./checkpoints/yolov4-tiny-416 --size 416 --model yolov4 --image ./data/kite.jpg --tiny +# yolov4-tiny-3l +python save_model.py --weights ./data/yolov4-tiny-3l-608_5000.weights --output ./checkpoints/yolov4-tiny-3l-608 --input_size 608 --model yolov4-tiny-3l --tiny + +# Run yolov4-tiny-3l tensorflow model +python detect.py --weights ./checkpoints/yolov4-tiny-3l-608 --size 608 --model yolov4 --images ./data/images/kite.jpg --tiny ``` If you want to run yolov3 or yolov3-tiny change ``--model yolov3`` in command @@ -48,6 +53,15 @@ python save_model.py --weights ./data/yolov4.weights --output ./checkpoints/yolo # yolov4 python convert_tflite.py --weights ./checkpoints/yolov4-416 --output ./checkpoints/yolov4-416.tflite +# yolov4-tiny +python save_model.py --weights ./data/yolov4-tiny-3l-608_5000.weights --output ./checkpoints/yolov4-tiny-3l-608 --input_size 608 --model yolov4-tiny-3l --tiny -framework tflite + +# convert custom yolov4-tiny-3l tflite model +python convert_tflite.py --weights ./checkpoints/yolov4-tiny-3l-608 --output ./checkpoints/yolov4-tiny-3l-608.tflite + +# yolov4-tiny-3l quantize float16 +python convert_tflite.py --weights ./checkpoints/yolov4-tiny-3l-608 --output ./checkpoints/yolov4-tiny-3l-fp16.tflite --quantize_mode float16 + # yolov4 quantize float16 python convert_tflite.py --weights ./checkpoints/yolov4-416 --output ./checkpoints/yolov4-416-fp16.tflite --quantize_mode float16