From d3daf23342d80270c7bc5c13cdf15631cf376336 Mon Sep 17 00:00:00 2001 From: LucasMahieu Date: Fri, 23 Oct 2020 13:51:15 +0200 Subject: [PATCH 1/2] Get input image shape statically in the model construction function Instead of using input.get_shape() fonction We can pass input image shape to yolo_v3 and yolo_v3_tiny constructor function. Since the input placeholder shape is statically defined (to None, size, size, 3) We can have access to this 'size' when constructing the yolo_v3 or yolo_v3_tiny models. This if more efficient for inference. This commit should not break any anterior codes since it is only adding 1 optional argument to model constructor functions --- README.md | 6 ++++++ convert_weights.py | 5 ++++- convert_weights_pb.py | 5 +++-- demo.py | 2 +- utils.py | 3 ++- yolo_v3.py | 8 +++----- yolo_v3_tiny.py | 4 +--- 7 files changed, 20 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index b279db1..d811bb6 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ To run demo type this in the command line: 1. Use yolov3-spp 6. `--ckpt_file` 1. Output checkpoint file + 7. `--size` + 1. Input image size 2. convert_weights_pb.py: 1. `--class_names` 1. Path to the class names file @@ -51,6 +53,8 @@ To run demo type this in the command line: 1. Use yolov3-spp 6. `--output_graph` 1. Location to write the output .pb graph to + 7. `--size` + 1. Input image size 3. demo.py 1. `--class_names` 1. Path to the class names file @@ -68,3 +72,5 @@ To run demo type this in the command line: 1. Desired iou threshold 8. `--gpu_memory_fraction` 1. Fraction of gpu memory to work with + 9. `--size` + 1. Input image size diff --git a/convert_weights.py b/convert_weights.py index 01f656e..890b752 100644 --- a/convert_weights.py +++ b/convert_weights.py @@ -21,6 +21,8 @@ 'spp', False, 'Use SPP version of YOLOv3') tf.app.flags.DEFINE_string( 'ckpt_file', './saved_model/model.ckpt', 'Chceckpoint file') +tf.app.flags.DEFINE_integer( + 'size', 416, 'Input Image size') def main(argv=None): @@ -39,7 +41,8 @@ def main(argv=None): with tf.variable_scope('detector'): detections = model(inputs, len(classes), - data_format=FLAGS.data_format) + data_format=FLAGS.data_format, + img_size=[FLAGS.size, FLAGS.size]) load_ops = load_weights(tf.global_variables( scope='detector'), FLAGS.weights_file) diff --git a/convert_weights_pb.py b/convert_weights_pb.py index 1ade65a..1770cd3 100644 --- a/convert_weights_pb.py +++ b/convert_weights_pb.py @@ -23,8 +23,9 @@ 'tiny', False, 'Use tiny version of YOLOv3') tf.app.flags.DEFINE_bool( 'spp', False, 'Use SPP version of YOLOv3') + tf.app.flags.DEFINE_integer( - 'size', 416, 'Image size') + 'size', 416, 'Input image size') @@ -42,7 +43,7 @@ def main(argv=None): inputs = tf.placeholder(tf.float32, [None, FLAGS.size, FLAGS.size, 3], "inputs") with tf.variable_scope('detector'): - detections = model(inputs, len(classes), data_format=FLAGS.data_format) + detections = model(inputs, len(classes), data_format=FLAGS.data_format, img_size=[FLAGS.size, FLAGS.size]) load_ops = load_weights(tf.global_variables(scope='detector'), FLAGS.weights_file) # Sets the output nodes in the current session diff --git a/demo.py b/demo.py index de7e931..ff78394 100644 --- a/demo.py +++ b/demo.py @@ -33,7 +33,7 @@ 'spp', False, 'Use SPP version of YOLOv3') tf.app.flags.DEFINE_integer( - 'size', 416, 'Image size') + 'size', 416, 'Input image size') tf.app.flags.DEFINE_float( 'conf_threshold', 0.5, 'Confidence threshold') diff --git a/utils.py b/utils.py index c4cce93..6e5bfc8 100644 --- a/utils.py +++ b/utils.py @@ -20,7 +20,8 @@ def get_boxes_and_inputs(model, num_classes, size, data_format): with tf.variable_scope('detector'): detections = model(inputs, num_classes, - data_format=data_format) + data_format=data_format, + img_size=[size, size]) boxes = detections_boxes(detections) diff --git a/yolo_v3.py b/yolo_v3.py index ef1d1a7..15992e5 100644 --- a/yolo_v3.py +++ b/yolo_v3.py @@ -200,7 +200,7 @@ def _upsample(inputs, out_shape, data_format='NCHW'): return inputs -def yolo_v3(inputs, num_classes, is_training=False, data_format='NCHW', reuse=False, with_spp=False): +def yolo_v3(inputs, num_classes, is_training=False, data_format='NCHW', reuse=False, with_spp=False, img_size=[416, 416]): """ Creates YOLO v3 model. @@ -213,8 +213,6 @@ def yolo_v3(inputs, num_classes, is_training=False, data_format='NCHW', reuse=Fa :param with_spp: whether or not is using spp layer. :return: """ - # it will be needed later on - img_size = inputs.get_shape().as_list()[1:3] # transpose the inputs to NCHW if data_format == 'NCHW': @@ -277,7 +275,7 @@ def yolo_v3(inputs, num_classes, is_training=False, data_format='NCHW', reuse=Fa return detections -def yolo_v3_spp(inputs, num_classes, is_training=False, data_format='NCHW', reuse=False): +def yolo_v3_spp(inputs, num_classes, is_training=False, data_format='NCHW', reuse=False, img_size=[416, 416]): """ Creates YOLO v3 with SPP model. @@ -289,4 +287,4 @@ def yolo_v3_spp(inputs, num_classes, is_training=False, data_format='NCHW', reus :param reuse: whether or not the network and its variables should be reused. :return: """ - return yolo_v3(inputs, num_classes, is_training=is_training, data_format=data_format, reuse=reuse, with_spp=True) + return yolo_v3(inputs, num_classes, is_training=is_training, data_format=data_format, reuse=reuse, with_spp=True, img_size=img_size) diff --git a/yolo_v3_tiny.py b/yolo_v3_tiny.py index 5f308f5..4ea996e 100644 --- a/yolo_v3_tiny.py +++ b/yolo_v3_tiny.py @@ -15,7 +15,7 @@ (81, 82), (135, 169), (344, 319)] -def yolo_v3_tiny(inputs, num_classes, is_training=False, data_format='NCHW', reuse=False): +def yolo_v3_tiny(inputs, num_classes, is_training=False, data_format='NCHW', reuse=False, img_size=[416, 416]): """ Creates YOLO v3 tiny model. @@ -27,8 +27,6 @@ def yolo_v3_tiny(inputs, num_classes, is_training=False, data_format='NCHW', reu :param reuse: whether or not the network and its variables should be reused. :return: """ - # it will be needed later on - img_size = inputs.get_shape().as_list()[1:3] # transpose the inputs to NCHW if data_format == 'NCHW': From efd58246c741ab4c6ef3131fa2c62b9ac19068cc Mon Sep 17 00:00:00 2001 From: LucasMahieu Date: Wed, 13 Jan 2021 14:17:26 +0100 Subject: [PATCH 2/2] Fix a bug in non_max_supression There was a bug in the way the all zero prediction was removed from the image_prediction tensor This solution is correct, much more simple and clear. --- utils.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/utils.py b/utils.py index 6e5bfc8..60ff353 100644 --- a/utils.py +++ b/utils.py @@ -186,10 +186,8 @@ def non_max_suppression(predictions_with_boxes, confidence_threshold, iou_thresh result = {} for i, image_pred in enumerate(predictions): - shape = image_pred.shape - non_zero_idxs = np.nonzero(image_pred) - image_pred = image_pred[non_zero_idxs] - image_pred = image_pred.reshape(-1, shape[-1]) + # Remove predictions if all the prediction vector is zero + image_pred = image_pred[np.any(image_pred, axis=-1)] bbox_attrs = image_pred[:, :5] classes = image_pred[:, 5:]