26 |
Data Extraction
27 | Click Here for Speed Detection 28 |29 | {% if fname %} 30 |
Data Extraction completed successfully.
31 | Download .csv 32 | {% endif %} 33 | 34 | 35 |├── README.md
├── __pycache__
├── car_colour_new.cpython-36.pyc
├── detect_object.cpython-36.pyc
├── speed_check.cpython-36.pyc
├── speed_check_new.cpython-36.pyc
└── yolov4inTFNew.cpython-36.pyc
├── app.py
├── app_helper.py
├── app_old.py
├── benchmarks.py
├── car_colour_new.py
├── color_short
├── green
│ └── green_0.jpg
└── yellow
│ └── yellow_0.jpg
├── color_short_output
└── green
│ └── op_img.jpg
├── command.txt
├── conda-cpu.yml
├── conda-gpu.yml
├── convert_tflite.py
├── convert_trt.py
├── core
├── __pycache__
│ ├── backbone.cpython-36.pyc
│ ├── common.cpython-36.pyc
│ ├── config.cpython-36.pyc
│ ├── utils.cpython-36.pyc
│ └── yolov4.cpython-36.pyc
├── backbone.py
├── common.py
├── config.py
├── dataset.py
├── utils.py
└── yolov4.py
├── data
├── anchors
│ ├── basline_anchors.txt
│ ├── basline_tiny_anchors.txt
│ ├── yolov3_anchors.txt
│ └── yolov4_anchors.txt
├── classes
│ ├── coco.names
│ ├── license.names
│ ├── logo.names
│ ├── voc.names
│ └── yymnist.names
├── logo.names
├── ss
│ ├── dataOutput.png
│ ├── result14.jpg
│ ├── result15.jpg
│ ├── result16.jpg
│ ├── result5.png
│ ├── result6.jpg
│ ├── result7.jpg
│ └── result8.jpg
├── yolov4-license.cfg
├── yolov4-logo.cfg
└── yolov4.cfg
├── detect.py
├── detect_flask.py
├── detect_object.py
├── detect_video.py
├── evaluate.py
├── mAP
├── extra
│ ├── intersect-gt-and-pred.py
│ └── remove_space.py
└── main.py
├── main.py
├── myhaar.xml
├── new_ocr.py
├── requirements-gpu.txt
├── requirements.txt
├── save_model.py
├── scripts
├── coco_annotation.py
├── coco_convert.py
├── get_coco_dataset_2017.sh
├── google_utils.py
├── voc
│ ├── README.md
│ ├── get_voc2012.sh
│ ├── voc_convert.py
│ └── voc_make_names.py
└── voc_annotation.py
├── speed_check.py
├── speed_check_new.py
├── static
├── css
│ ├── main.css
│ └── test.css
├── detections
│ ├── data
│ │ └── output.csv
│ └── speed
│ │ └── speed.csv
└── img
│ ├── images.txt
│ └── security-camera.png
├── templates
├── about.html
├── data_done.html
├── index.html
├── layout.html
├── speed.html
├── uploaded copy.html
└── uploaded.html
└── train.py
/README.md:
--------------------------------------------------------------------------------
1 | ## Video Surveillance System
2 |
3 | ### Vehicle Identification and Speed Detection (VISD)
4 |
5 | ### Description:
6 |
7 | VISD extracts vehicle information like License Plate number, Manufacturer and colour from a video and provides this data in the form of a CSV file. VISD can also perform vehicle speed detection on a video.
8 | VISD extracts vehicle information by performing vehicle detection, license plate detection ,logo detection and color detection on frames extracted from the video. Vehicle Detection,license plate detection and logo detection are done using YOLOv4 and color detection is done using pixel method.
9 | Another important feature of VSID is speed detection which is performed using Haarcascade Classifier.
10 | All these features of VSID are provided to the user using a Web Application which is created using Flask (Screenshots included below).
11 |
12 | ### How To Run?
13 |
14 | Download the required Weights File:
15 |
16 |
Pre-Trained YOLOv4 weights : https://drive.google.com/file/d/1OTVtOd3VvCPvw_IHGfINtzZt8OQx4ICn/view?usp=sharing
17 |License Plate YOLOv4 weights : https://drive.google.com/file/d/1HyLvb-fdGY0FrBxhNm1djGh2nrlNR0T7/view?usp=sharing
18 |Vehicle Logo YOLOv4 weights : https://drive.google.com/file/d/1nXoFgDE5qhG9DSocsLwm0cXeAPMmAy_o/view?usp=sharing
19 | 20 | Paste all the weights file in /data folder. 21 | 22 | Download the required python modules: 23 |The AI Guy : https://github.com/theAIGuysCode
56 | -------------------------------------------------------------------------------- /__pycache__/car_colour_new.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/__pycache__/car_colour_new.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/detect_object.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/__pycache__/detect_object.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/speed_check.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/__pycache__/speed_check.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/speed_check_new.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/__pycache__/speed_check_new.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/yolov4inTFNew.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/__pycache__/yolov4inTFNew.cpython-36.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, Response, request, session, redirect, url_for, send_from_directory, flash 2 | from werkzeug.utils import secure_filename 3 | 4 | from PIL import Image 5 | import os 6 | import sys 7 | import cv2 8 | from yolov4inTFNew import get_image_data 9 | 10 | app = Flask(__name__) 11 | UPLOAD_FOLDER = './static/uploads' 12 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 13 | 14 | @app.route("/") 15 | def index(): 16 | return render_template("index.html") 17 | 18 | @app.route("/about") 19 | def about(): 20 | return render_template("about.html") 21 | 22 | @app.route('/uploader', methods = ['GET', 'POST']) 23 | def upload_file(): 24 | if request.method == 'POST': 25 | f = request.files['file'] 26 | # create a secure filename 27 | filename = secure_filename(f.filename) 28 | print(filename) 29 | # save file to /static/uploads 30 | filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) 31 | print(filepath) 32 | f.save(filepath) 33 | # logo, lp_text = get_image_data(filepath) 34 | 35 | return render_template("uploaded.html", fname=filename,detected_logo=logo, detected_lp_text=lp_text) 36 | 37 | if __name__ == '__main__': 38 | app.run(port=4000, debug=True) 39 | -------------------------------------------------------------------------------- /app_helper.py: -------------------------------------------------------------------------------- 1 | import time 2 | from absl import app, logging 3 | import cv2 4 | import numpy as np 5 | import tensorflow as tf 6 | from yolov3_tf2.models import ( 7 | YoloV3, YoloV3Tiny 8 | ) 9 | from yolov3_tf2.dataset import transform_images, load_tfrecord_dataset 10 | from yolov3_tf2.utils import draw_outputs 11 | from flask import Flask, request, Response, jsonify, send_from_directory, abort 12 | import os 13 | import imageio 14 | 15 | def get_image(image_path , img_name): 16 | classes_path = './data/labels/coco.names' 17 | weights_path = './weights/yolov3.tf' 18 | tiny = False 19 | size = 416 20 | output_path = './static/detections/' 21 | num_classes = 80 22 | 23 | # load in weights and classes 24 | physical_devices = tf.config.experimental.list_physical_devices('GPU') 25 | if len(physical_devices) > 0: 26 | tf.config.experimental.set_memory_growth(physical_devices[0], True) 27 | 28 | if tiny: 29 | yolo = YoloV3Tiny(classes=num_classes) 30 | else: 31 | yolo = YoloV3(classes=num_classes) 32 | 33 | yolo.load_weights(weights_path).expect_partial() 34 | print('weights loaded') 35 | 36 | class_names = [c.strip() for c in open(classes_path).readlines()] 37 | print('classes loaded') 38 | #reading the images & apply detection with loaded weight file 39 | image = imageio.imread(image_path) 40 | filename = img_name 41 | img_raw = tf.image.decode_image( 42 | open(image_path, 'rb').read(), channels=3) 43 | img = tf.expand_dims(img_raw, 0) 44 | img = transform_images(img, size) 45 | 46 | t1 = time.time() 47 | boxes, scores, classes, nums = yolo(img) 48 | t2 = time.time() 49 | print('time: {}'.format(t2 - t1)) 50 | 51 | print('detections:') 52 | for i in range(nums[0]): 53 | print('\t{}, {}, {}'.format(class_names[int(classes[0][i])], 54 | np.array(scores[0][i]), 55 | np.array(boxes[0][i]))) 56 | img = cv2.cvtColor(img_raw.numpy(), cv2.COLOR_RGB2BGR) 57 | img = draw_outputs(img, (boxes, scores, classes, nums), class_names) 58 | cv2.imwrite(output_path + '{}' .format(filename), img) 59 | print('output saved to: {}'.format(output_path + '{}'.format(filename))) -------------------------------------------------------------------------------- /app_old.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, print_function 2 | # coding=utf-8 3 | import sys 4 | import os 5 | import glob 6 | import re 7 | import glob 8 | import os 9 | import cv2 10 | import numpy as np 11 | import pandas as pd 12 | import detect_object 13 | from shutil import copyfile 14 | import shutil 15 | from distutils.dir_util import copy_tree 16 | 17 | # Flask utils 18 | from flask import Flask, redirect, url_for, request, render_template 19 | from werkzeug.utils import secure_filename 20 | from gevent.pywsgi import WSGIServer 21 | 22 | # Define a flask app 23 | app = Flask(__name__) 24 | 25 | for f in os.listdir("static\\similar_images\\"): 26 | os.remove("static\\similar_images\\"+f) 27 | 28 | print('Model loaded. Check http://127.0.0.1:5000/') 29 | 30 | 31 | @app.route('/', methods=['GET']) 32 | def index(): 33 | # Main page 34 | return render_template('index.html') 35 | 36 | 37 | @app.route('/predict', methods=['GET', 'POST']) 38 | def upload(): 39 | if request.method == 'POST': 40 | # Get the file from post request 41 | f = request.files['file'] 42 | 43 | # Save the file to ./uploads 44 | basepath = os.path.dirname(__file__) 45 | file_path = os.path.join( 46 | basepath, 'uploads', secure_filename(f.filename)) 47 | f.save(file_path) 48 | 49 | # Make prediction 50 | get_detected_object = detect_object(file_path) 51 | return get_detected_object 52 | return None 53 | 54 | 55 | if __name__ == '__main__': 56 | app.run(debug=True) 57 | -------------------------------------------------------------------------------- /benchmarks.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import tensorflow as tf 3 | import time 4 | import cv2 5 | from core.yolov4 import YOLOv4, YOLOv3_tiny, YOLOv3, decode 6 | from absl import app, flags, logging 7 | from absl.flags import FLAGS 8 | from tensorflow.python.saved_model import tag_constants 9 | from core import utils 10 | from core.config import cfg 11 | from tensorflow.compat.v1 import ConfigProto 12 | from tensorflow.compat.v1 import InteractiveSession 13 | 14 | flags.DEFINE_boolean('tiny', False, 'yolo or yolo-tiny') 15 | flags.DEFINE_string('framework', 'tf', '(tf, tflite, trt') 16 | flags.DEFINE_string('model', 'yolov4', 'yolov3 or yolov4') 17 | flags.DEFINE_string('weights', './data/yolov4.weights', 'path to weights file') 18 | flags.DEFINE_string('images', './data/images/kite.jpg', 'path to input image') 19 | flags.DEFINE_integer('size', 416, 'resize images to') 20 | 21 | 22 | def main(_argv): 23 | if FLAGS.tiny: 24 | STRIDES = np.array(cfg.YOLO.STRIDES_TINY) 25 | ANCHORS = utils.get_anchors(cfg.YOLO.ANCHORS_TINY, FLAGS.tiny) 26 | else: 27 | STRIDES = np.array(cfg.YOLO.STRIDES) 28 | if FLAGS.model == 'yolov4': 29 | ANCHORS = utils.get_anchors(cfg.YOLO.ANCHORS, FLAGS.tiny) 30 | else: 31 | ANCHORS = utils.get_anchors(cfg.YOLO.ANCHORS_V3, FLAGS.tiny) 32 | NUM_CLASS = len(utils.read_class_names(cfg.YOLO.CLASSES)) 33 | XYSCALE = cfg.YOLO.XYSCALE 34 | 35 | config = ConfigProto() 36 | config.gpu_options.allow_growth = True 37 | session = InteractiveSession(config=config) 38 | input_size = FLAGS.size 39 | physical_devices = tf.config.experimental.list_physical_devices('GPU') 40 | if len(physical_devices) > 0: 41 | tf.config.experimental.set_memory_growth(physical_devices[0], True) 42 | if FLAGS.framework == 'tf': 43 | input_layer = tf.keras.layers.Input([input_size, input_size, 3]) 44 | if FLAGS.tiny: 45 | feature_maps = YOLOv3_tiny(input_layer, NUM_CLASS) 46 | bbox_tensors = [] 47 | for i, fm in enumerate(feature_maps): 48 | bbox_tensor = decode(fm, NUM_CLASS, i) 49 | bbox_tensors.append(bbox_tensor) 50 | model = tf.keras.Model(input_layer, bbox_tensors) 51 | utils.load_weights_tiny(model, FLAGS.weights) 52 | else: 53 | if FLAGS.model == 'yolov3': 54 | feature_maps = YOLOv3(input_layer, NUM_CLASS) 55 | bbox_tensors = [] 56 | for i, fm in enumerate(feature_maps): 57 | bbox_tensor = decode(fm, NUM_CLASS, i) 58 | bbox_tensors.append(bbox_tensor) 59 | model = tf.keras.Model(input_layer, bbox_tensors) 60 | utils.load_weights_v3(model, FLAGS.weights) 61 | elif FLAGS.model == 'yolov4': 62 | feature_maps = YOLOv4(input_layer, NUM_CLASS) 63 | bbox_tensors = [] 64 | for i, fm in enumerate(feature_maps): 65 | bbox_tensor = decode(fm, NUM_CLASS, i) 66 | bbox_tensors.append(bbox_tensor) 67 | model = tf.keras.Model(input_layer, bbox_tensors) 68 | utils.load_weights(model, FLAGS.weights) 69 | elif FLAGS.framework == 'trt': 70 | saved_model_loaded = tf.saved_model.load(FLAGS.weights, tags=[tag_constants.SERVING]) 71 | signature_keys = list(saved_model_loaded.signatures.keys()) 72 | print(signature_keys) 73 | infer = saved_model_loaded.signatures['serving_default'] 74 | 75 | logging.info('weights loaded') 76 | 77 | @tf.function 78 | def run_model(x): 79 | return model(x) 80 | 81 | # Test the TensorFlow Lite model on random input data. 82 | sum = 0 83 | original_image = cv2.imread(FLAGS.image) 84 | original_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB) 85 | original_image_size = original_image.shape[:2] 86 | image_data = utils.image_preprocess(np.copy(original_image), [FLAGS.size, FLAGS.size]) 87 | image_data = image_data[np.newaxis, ...].astype(np.float32) 88 | img_raw = tf.image.decode_image( 89 | open(FLAGS.image, 'rb').read(), channels=3) 90 | img_raw = tf.expand_dims(img_raw, 0) 91 | img_raw = tf.image.resize(img_raw, (FLAGS.size, FLAGS.size)) 92 | batched_input = tf.constant(image_data) 93 | for i in range(1000): 94 | prev_time = time.time() 95 | # pred_bbox = model.predict(image_data) 96 | if FLAGS.framework == 'tf': 97 | pred_bbox = [] 98 | result = run_model(image_data) 99 | for value in result: 100 | value = value.numpy() 101 | pred_bbox.append(value) 102 | if FLAGS.model == 'yolov4': 103 | pred_bbox = utils.postprocess_bbbox(pred_bbox, ANCHORS, STRIDES, XYSCALE) 104 | else: 105 | pred_bbox = utils.postprocess_bbbox(pred_bbox, ANCHORS, STRIDES) 106 | bboxes = utils.postprocess_boxes(pred_bbox, original_image_size, input_size, 0.25) 107 | bboxes = utils.nms(bboxes, 0.213, method='nms') 108 | elif FLAGS.framework == 'trt': 109 | pred_bbox = [] 110 | result = infer(batched_input) 111 | for key, value in result.items(): 112 | value = value.numpy() 113 | pred_bbox.append(value) 114 | if FLAGS.model == 'yolov4': 115 | pred_bbox = utils.postprocess_bbbox(pred_bbox, ANCHORS, STRIDES, XYSCALE) 116 | else: 117 | pred_bbox = utils.postprocess_bbbox(pred_bbox, ANCHORS, STRIDES) 118 | bboxes = utils.postprocess_boxes(pred_bbox, original_image_size, input_size, 0.25) 119 | bboxes = utils.nms(bboxes, 0.213, method='nms') 120 | # pred_bbox = pred_bbox.numpy() 121 | curr_time = time.time() 122 | exec_time = curr_time - prev_time 123 | if i == 0: continue 124 | sum += (1 / exec_time) 125 | info = str(i) + " time:" + str(round(exec_time, 3)) + " average FPS:" + str(round(sum / i, 2)) + ", FPS: " + str( 126 | round((1 / exec_time), 1)) 127 | print(info) 128 | 129 | 130 | if __name__ == '__main__': 131 | try: 132 | app.run(main) 133 | except SystemExit: 134 | pass 135 | -------------------------------------------------------------------------------- /car_colour_new.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | import cv2 3 | import os 4 | import numpy as np 5 | from PIL import Image 6 | 7 | class Channel_value: 8 | val = -1.0 9 | intensity = -1.0 10 | 11 | def atmospheric_light(img, gray): 12 | top_num = int(img.shape[0] * img.shape[1] * 0.001) 13 | toplist = [Channel_value()] * top_num 14 | dark_channel = dark_channel_find(img) 15 | 16 | for y in range(img.shape[0]): 17 | for x in range(img.shape[1]): 18 | val = img.item(y, x, dark_channel) 19 | intensity = gray.item(y, x) 20 | for t in toplist: 21 | if t.val < val or (t.val == val and t.intensity < intensity): 22 | t.val = val 23 | t.intensity = intensity 24 | break 25 | max_channel = Channel_value() 26 | for t in toplist: 27 | if t.intensity > max_channel.intensity: 28 | max_channel = t 29 | return max_channel.intensity 30 | 31 | #Finding the dark channel i.e. the pixel with the lowest R/G/B value 32 | def dark_channel_find(img): 33 | return np.unravel_index(np.argmin(img), img.shape)[2] 34 | 35 | #Finding a coarse image which gives us a transmission map 36 | def coarse(minimum, x, maximum): 37 | return max(minimum, min(x, maximum)) 38 | 39 | #Uses values from other functions to aggregate and give us a clear image 40 | def dehaze(img, light_intensity, windowSize, t0, w): 41 | size = (img.shape[0], img.shape[1]) 42 | 43 | outimg = np.zeros(img.shape, img.dtype) 44 | 45 | for y in range(size[0]): 46 | for x in range(size[1]): 47 | x_low = max(x-(windowSize//2), 0) 48 | y_low = max(y-(windowSize//2), 0) 49 | x_high = min(x+(windowSize//2), size[1]) 50 | y_high = min(y+(windowSize//2), size[0]) 51 | 52 | sliceimg = img[y_low:y_high, x_low:x_high] 53 | 54 | dark_channel = dark_channel_find(sliceimg) 55 | t = 1.0 - (w * img.item(y, x, dark_channel) / light_intensity) 56 | 57 | outimg.itemset((y,x,0), coarse(0, ((img.item(y,x,0) - light_intensity) / max(t, t0) + light_intensity), 255)) 58 | outimg.itemset((y,x,1), coarse(0, ((img.item(y,x,1) - light_intensity) / max(t, t0) + light_intensity), 255)) 59 | outimg.itemset((y,x,2), coarse(0, ((img.item(y,x,2) - light_intensity) / max(t, t0) + light_intensity), 255)) 60 | return outimg 61 | 62 | # Commented out IPython magic to ensure Python compatibility. 63 | # %pylab inline 64 | import matplotlib.pyplot as plt 65 | import matplotlib.image as mpimg 66 | 67 | def main(): 68 | d="./color_short" 69 | cd="./color_short_output" 70 | folder=os.listdir(d) 71 | for fold in folder: 72 | # print(fold) 73 | files=os.listdir(os.path.join(d,fold)) 74 | for f in files: 75 | # print(f) 76 | img = cv2.imread(os.path.join(d,fold,f)) 77 | imgplot = plt.imshow(img) 78 | plt.show() 79 | 80 | img = np.array(img, dtype=np.uint8) 81 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 82 | light_intensity = atmospheric_light(img, gray) 83 | w = 0.95 84 | t0 = 0.55 85 | outimg = dehaze(img, light_intensity, 20, t0, w) 86 | name = os.path.join(cd,fold,f) 87 | imgplot = plt.imshow(outimg) 88 | plt.show() 89 | # print(name) 90 | cv2.imwrite(name, outimg) 91 | 92 | # main() 93 | 94 | import matplotlib.pyplot as plt 95 | from PIL import Image 96 | 97 | class Colors(object): 98 | class Color(object): 99 | def __init__(self, value): 100 | self.value = value 101 | 102 | def __str__(self): 103 | return "%s : %s" % (self.__class__.__name__, self.value) 104 | 105 | class Red(Color): pass 106 | class Blue(Color): pass 107 | class Green(Color): pass 108 | class Yellow(Color): pass 109 | class White(Color): pass 110 | class Gray(Color): pass 111 | class Black(Color): pass 112 | class Pink(Color): pass 113 | class Teal(Color): pass 114 | 115 | class ColorWheel(object): 116 | def __init__(self, rgb): 117 | r, g, b = rgb 118 | 119 | self.rgb = (Colors.Red(r), Colors.Green(g), Colors.Blue(b), ) 120 | 121 | 122 | def estimate_color(self): 123 | dominant_colors = self.get_dominant_colors() 124 | 125 | total_colors = len(dominant_colors) 126 | 127 | if total_colors == 1: 128 | return dominant_colors[0] 129 | elif total_colors == 2: 130 | color_classes = [x.__class__ for x in dominant_colors] 131 | 132 | if Colors.Red in color_classes and Colors.Green in color_classes: 133 | return Colors.Yellow(dominant_colors[0].value) 134 | elif Colors.Red in color_classes and Colors.Blue in color_classes: 135 | return Colors.Pink(dominant_colors[0].value) 136 | elif Colors.Blue in color_classes and Colors.Green in color_classes: 137 | return Colors.Teal(dominant_colors[0].value) 138 | elif total_colors == 3: 139 | if dominant_colors[0].value > 200: 140 | return Colors.White(dominant_colors[0].value) 141 | elif dominant_colors[0].value > 100: 142 | return Colors.Gray(dominant_colors[0].value) 143 | else: 144 | return Colors.Black(dominant_colors[0].value) 145 | else: 146 | print("Dominant Colors : %s" % dominant_colors) 147 | 148 | def get_dominant_colors(self): 149 | max_color = max([x.value for x in self.rgb]) 150 | 151 | return [x for x in self.rgb if x.value >= max_color * .9] 152 | 153 | def process_image(image): 154 | d={} 155 | image_color_quantities = {} 156 | width, height = image.size 157 | # print(image.size) 158 | 159 | 160 | width_margin = int(width - (width * .65)) 161 | height_margin = int(height - (height * .65)) 162 | # print(width_margin,height_margin) 163 | for x in range(width_margin, width - width_margin): 164 | for y in range(height_margin, height - height_margin): 165 | r, g, b = image.getpixel((x, y)) 166 | 167 | key = "%s:%s:%s" % (r, g, b, ) 168 | 169 | key = (r, g, b, ) 170 | 171 | image_color_quantities[key] = image_color_quantities.get(key, 0) + 1 172 | 173 | total_assessed_pixels = sum([v for k, v in image_color_quantities.items() if v > 10]) 174 | 175 | strongest_color_wheels = [(ColorWheel(k), v / float(total_assessed_pixels) * 100, ) for k, v in image_color_quantities.items() if v > 10] 176 | final_colors = {} 177 | 178 | for color_wheel, strength in strongest_color_wheels: 179 | color = color_wheel.estimate_color() 180 | 181 | final_colors[color.__class__] = final_colors.get(color.__class__, 0) + strength 182 | 183 | for color, strength in final_colors.items(): 184 | d[color.__name__]=strength 185 | return d 186 | 187 | import matplotlib.pyplot as plt 188 | import matplotlib.image as mpimg 189 | 190 | 191 | def get_car_colour(path): 192 | # image = cv2.imread(path) 193 | # img = np.array(image, dtype=np.uint8) 194 | # gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 195 | # light_intensity = atmospheric_light(img, gray) 196 | # w = 0.95 197 | # t0 = 0.55 198 | # outimg = dehaze(img, light_intensity, 20, t0, w) 199 | # op_folder = "./color_short_output/green" 200 | # cv2.imwrite(os.path.join(op_folder, 'op_img.jpg'), outimg) 201 | # outimg = Image.open(os.path.join(op_folder, 'op_img.jpg')) 202 | # d = process_image(outimg) 203 | 204 | image = Image.open(path) 205 | d = process_image(image) 206 | 207 | # print(d) 208 | 209 | colour = max(d, key=d.get) 210 | return(colour) 211 | -------------------------------------------------------------------------------- /color_short/green/green_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/color_short/green/green_0.jpg -------------------------------------------------------------------------------- /color_short/yellow/yellow_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/color_short/yellow/yellow_0.jpg -------------------------------------------------------------------------------- /color_short_output/green/op_img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/color_short_output/green/op_img.jpg -------------------------------------------------------------------------------- /command.txt: -------------------------------------------------------------------------------- 1 | curl.exe -X POST -F image=@suz.jpg "http://localhost:5000/api/test" --output output.png -------------------------------------------------------------------------------- /conda-cpu.yml: -------------------------------------------------------------------------------- 1 | name: yolov4-cpu 2 | 3 | dependencies: 4 | - python==3.7 5 | - pip 6 | - matplotlib 7 | - opencv 8 | - pip: 9 | - opencv-python==4.1.1.26 10 | - lxml 11 | - tqdm 12 | - tensorflow==2.3.0rc0 13 | - absl-py 14 | - easydict 15 | - pillow -------------------------------------------------------------------------------- /conda-gpu.yml: -------------------------------------------------------------------------------- 1 | name: yolov4-gpu 2 | 3 | dependencies: 4 | - python==3.7 5 | - pip 6 | - matplotlib 7 | - opencv 8 | - cudnn 9 | - cudatoolkit==10.1.243 10 | - pip: 11 | - tensorflow-gpu==2.3.0rc0 12 | - opencv-python==4.1.1.26 13 | - lxml 14 | - tqdm 15 | - absl-py 16 | - easydict 17 | - pillow 18 | -------------------------------------------------------------------------------- /convert_tflite.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from absl import app, flags, logging 3 | from absl.flags import FLAGS 4 | import numpy as np 5 | import cv2 6 | from core.yolov4 import YOLOv4, YOLOv3, YOLOv3_tiny, decode 7 | import core.utils as utils 8 | import os 9 | from core.config import cfg 10 | 11 | flags.DEFINE_string('weights', './checkpoints/yolov4-416', 'path to weights file') 12 | flags.DEFINE_string('output', './checkpoints/yolov4-416-fp32.tflite', 'path to output') 13 | flags.DEFINE_integer('input_size', 416, 'path to output') 14 | flags.DEFINE_string('quantize_mode', 'float32', 'quantize mode (int8, float16, float32)') 15 | flags.DEFINE_string('dataset', "/Volumes/Elements/data/coco_dataset/coco/5k.txt", 'path to dataset') 16 | 17 | def representative_data_gen(): 18 | fimage = open(FLAGS.dataset).read().split() 19 | for input_value in range(10): 20 | if os.path.exists(fimage[input_value]): 21 | original_image=cv2.imread(fimage[input_value]) 22 | original_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB) 23 | image_data = utils.image_preprocess(np.copy(original_image), [FLAGS.input_size, FLAGS.input_size]) 24 | img_in = image_data[np.newaxis, ...].astype(np.float32) 25 | print("calibration image {}".format(fimage[input_value])) 26 | yield [img_in] 27 | else: 28 | continue 29 | 30 | def save_tflite(): 31 | converter = tf.lite.TFLiteConverter.from_saved_model(FLAGS.weights) 32 | 33 | if FLAGS.quantize_mode == 'float16': 34 | converter.optimizations = [tf.lite.Optimize.DEFAULT] 35 | converter.target_spec.supported_types = [tf.compat.v1.lite.constants.FLOAT16] 36 | converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS] 37 | converter.allow_custom_ops = True 38 | elif FLAGS.quantize_mode == 'int8': 39 | converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] 40 | converter.optimizations = [tf.lite.Optimize.DEFAULT] 41 | converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS] 42 | converter.allow_custom_ops = True 43 | converter.representative_dataset = representative_data_gen 44 | 45 | tflite_model = converter.convert() 46 | open(FLAGS.output, 'wb').write(tflite_model) 47 | 48 | logging.info("model saved to: {}".format(FLAGS.output)) 49 | 50 | def demo(): 51 | interpreter = tf.lite.Interpreter(model_path=FLAGS.output) 52 | interpreter.allocate_tensors() 53 | logging.info('tflite model loaded') 54 | 55 | input_details = interpreter.get_input_details() 56 | print(input_details) 57 | output_details = interpreter.get_output_details() 58 | print(output_details) 59 | 60 | input_shape = input_details[0]['shape'] 61 | 62 | input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32) 63 | 64 | interpreter.set_tensor(input_details[0]['index'], input_data) 65 | interpreter.invoke() 66 | output_data = [interpreter.get_tensor(output_details[i]['index']) for i in range(len(output_details))] 67 | 68 | print(output_data) 69 | 70 | def main(_argv): 71 | save_tflite() 72 | demo() 73 | 74 | if __name__ == '__main__': 75 | try: 76 | app.run(main) 77 | except SystemExit: 78 | pass 79 | 80 | 81 | -------------------------------------------------------------------------------- /convert_trt.py: -------------------------------------------------------------------------------- 1 | from absl import app, flags, logging 2 | from absl.flags import FLAGS 3 | import tensorflow as tf 4 | physical_devices = tf.config.experimental.list_physical_devices('GPU') 5 | if len(physical_devices) > 0: 6 | tf.config.experimental.set_memory_growth(physical_devices[0], True) 7 | import numpy as np 8 | import cv2 9 | from tensorflow.python.compiler.tensorrt import trt_convert as trt 10 | import core.utils as utils 11 | from tensorflow.python.saved_model import signature_constants 12 | import os 13 | from tensorflow.compat.v1 import ConfigProto 14 | from tensorflow.compat.v1 import InteractiveSession 15 | 16 | flags.DEFINE_string('weights', './checkpoints/yolov4-416', 'path to weights file') 17 | flags.DEFINE_string('output', './checkpoints/yolov4-trt-fp16-416', 'path to output') 18 | flags.DEFINE_integer('input_size', 416, 'path to output') 19 | flags.DEFINE_string('quantize_mode', 'float16', 'quantize mode (int8, float16)') 20 | flags.DEFINE_string('dataset', "/media/user/Source/Data/coco_dataset/coco/5k.txt", 'path to dataset') 21 | flags.DEFINE_integer('loop', 8, 'loop') 22 | 23 | def representative_data_gen(): 24 | fimage = open(FLAGS.dataset).read().split() 25 | batched_input = np.zeros((FLAGS.loop, FLAGS.input_size, FLAGS.input_size, 3), dtype=np.float32) 26 | for input_value in range(FLAGS.loop): 27 | if os.path.exists(fimage[input_value]): 28 | original_image=cv2.imread(fimage[input_value]) 29 | original_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB) 30 | image_data = utils.image_preporcess(np.copy(original_image), [FLAGS.input_size, FLAGS.input_size]) 31 | img_in = image_data[np.newaxis, ...].astype(np.float32) 32 | batched_input[input_value, :] = img_in 33 | # batched_input = tf.constant(img_in) 34 | print(input_value) 35 | # yield (batched_input, ) 36 | # yield tf.random.normal((1, 416, 416, 3)), 37 | else: 38 | continue 39 | batched_input = tf.constant(batched_input) 40 | yield (batched_input,) 41 | 42 | def save_trt(): 43 | 44 | if FLAGS.quantize_mode == 'int8': 45 | conversion_params = trt.DEFAULT_TRT_CONVERSION_PARAMS._replace( 46 | precision_mode=trt.TrtPrecisionMode.INT8, 47 | max_workspace_size_bytes=4000000000, 48 | use_calibration=True, 49 | max_batch_size=8) 50 | converter = trt.TrtGraphConverterV2( 51 | input_saved_model_dir=FLAGS.weights, 52 | conversion_params=conversion_params) 53 | converter.convert(calibration_input_fn=representative_data_gen) 54 | elif FLAGS.quantize_mode == 'float16': 55 | conversion_params = trt.DEFAULT_TRT_CONVERSION_PARAMS._replace( 56 | precision_mode=trt.TrtPrecisionMode.FP16, 57 | max_workspace_size_bytes=4000000000, 58 | max_batch_size=8) 59 | converter = trt.TrtGraphConverterV2( 60 | input_saved_model_dir=FLAGS.weights, conversion_params=conversion_params) 61 | converter.convert() 62 | else : 63 | conversion_params = trt.DEFAULT_TRT_CONVERSION_PARAMS._replace( 64 | precision_mode=trt.TrtPrecisionMode.FP32, 65 | max_workspace_size_bytes=4000000000, 66 | max_batch_size=8) 67 | converter = trt.TrtGraphConverterV2( 68 | input_saved_model_dir=FLAGS.weights, conversion_params=conversion_params) 69 | converter.convert() 70 | 71 | # converter.build(input_fn=representative_data_gen) 72 | converter.save(output_saved_model_dir=FLAGS.output) 73 | print('Done Converting to TF-TRT') 74 | 75 | saved_model_loaded = tf.saved_model.load(FLAGS.output) 76 | graph_func = saved_model_loaded.signatures[ 77 | signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] 78 | trt_graph = graph_func.graph.as_graph_def() 79 | for n in trt_graph.node: 80 | print(n.op) 81 | if n.op == "TRTEngineOp": 82 | print("Node: %s, %s" % (n.op, n.name.replace("/", "_"))) 83 | else: 84 | print("Exclude Node: %s, %s" % (n.op, n.name.replace("/", "_"))) 85 | logging.info("model saved to: {}".format(FLAGS.output)) 86 | 87 | trt_engine_nodes = len([1 for n in trt_graph.node if str(n.op) == 'TRTEngineOp']) 88 | print("numb. of trt_engine_nodes in TensorRT graph:", trt_engine_nodes) 89 | all_nodes = len([1 for n in trt_graph.node]) 90 | print("numb. of all_nodes in TensorRT graph:", all_nodes) 91 | 92 | def main(_argv): 93 | config = ConfigProto() 94 | config.gpu_options.allow_growth = True 95 | session = InteractiveSession(config=config) 96 | save_trt() 97 | 98 | if __name__ == '__main__': 99 | try: 100 | app.run(main) 101 | except SystemExit: 102 | pass 103 | 104 | 105 | -------------------------------------------------------------------------------- /core/__pycache__/backbone.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/core/__pycache__/backbone.cpython-36.pyc -------------------------------------------------------------------------------- /core/__pycache__/common.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/core/__pycache__/common.cpython-36.pyc -------------------------------------------------------------------------------- /core/__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/core/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /core/__pycache__/utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/core/__pycache__/utils.cpython-36.pyc -------------------------------------------------------------------------------- /core/__pycache__/yolov4.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/core/__pycache__/yolov4.cpython-36.pyc -------------------------------------------------------------------------------- /core/backbone.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding=utf-8 3 | 4 | import tensorflow as tf 5 | import core.common as common 6 | 7 | def darknet53(input_data): 8 | 9 | input_data = common.convolutional(input_data, (3, 3, 3, 32)) 10 | input_data = common.convolutional(input_data, (3, 3, 32, 64), downsample=True) 11 | 12 | for i in range(1): 13 | input_data = common.residual_block(input_data, 64, 32, 64) 14 | 15 | input_data = common.convolutional(input_data, (3, 3, 64, 128), downsample=True) 16 | 17 | for i in range(2): 18 | input_data = common.residual_block(input_data, 128, 64, 128) 19 | 20 | input_data = common.convolutional(input_data, (3, 3, 128, 256), downsample=True) 21 | 22 | for i in range(8): 23 | input_data = common.residual_block(input_data, 256, 128, 256) 24 | 25 | route_1 = input_data 26 | input_data = common.convolutional(input_data, (3, 3, 256, 512), downsample=True) 27 | 28 | for i in range(8): 29 | input_data = common.residual_block(input_data, 512, 256, 512) 30 | 31 | route_2 = input_data 32 | input_data = common.convolutional(input_data, (3, 3, 512, 1024), downsample=True) 33 | 34 | for i in range(4): 35 | input_data = common.residual_block(input_data, 1024, 512, 1024) 36 | 37 | return route_1, route_2, input_data 38 | 39 | def cspdarknet53(input_data): 40 | 41 | input_data = common.convolutional(input_data, (3, 3, 3, 32), activate_type="mish") 42 | input_data = common.convolutional(input_data, (3, 3, 32, 64), downsample=True, activate_type="mish") 43 | 44 | route = input_data 45 | route = common.convolutional(route, (1, 1, 64, 64), activate_type="mish") 46 | input_data = common.convolutional(input_data, (1, 1, 64, 64), activate_type="mish") 47 | for i in range(1): 48 | input_data = common.residual_block(input_data, 64, 32, 64, activate_type="mish") 49 | input_data = common.convolutional(input_data, (1, 1, 64, 64), activate_type="mish") 50 | 51 | input_data = tf.concat([input_data, route], axis=-1) 52 | input_data = common.convolutional(input_data, (1, 1, 128, 64), activate_type="mish") 53 | input_data = common.convolutional(input_data, (3, 3, 64, 128), downsample=True, activate_type="mish") 54 | route = input_data 55 | route = common.convolutional(route, (1, 1, 128, 64), activate_type="mish") 56 | input_data = common.convolutional(input_data, (1, 1, 128, 64), activate_type="mish") 57 | for i in range(2): 58 | input_data = common.residual_block(input_data, 64, 64, 64, activate_type="mish") 59 | input_data = common.convolutional(input_data, (1, 1, 64, 64), activate_type="mish") 60 | input_data = tf.concat([input_data, route], axis=-1) 61 | 62 | input_data = common.convolutional(input_data, (1, 1, 128, 128), activate_type="mish") 63 | input_data = common.convolutional(input_data, (3, 3, 128, 256), downsample=True, activate_type="mish") 64 | route = input_data 65 | route = common.convolutional(route, (1, 1, 256, 128), activate_type="mish") 66 | input_data = common.convolutional(input_data, (1, 1, 256, 128), activate_type="mish") 67 | for i in range(8): 68 | input_data = common.residual_block(input_data, 128, 128, 128, activate_type="mish") 69 | input_data = common.convolutional(input_data, (1, 1, 128, 128), activate_type="mish") 70 | input_data = tf.concat([input_data, route], axis=-1) 71 | 72 | input_data = common.convolutional(input_data, (1, 1, 256, 256), activate_type="mish") 73 | route_1 = input_data 74 | input_data = common.convolutional(input_data, (3, 3, 256, 512), downsample=True, activate_type="mish") 75 | route = input_data 76 | route = common.convolutional(route, (1, 1, 512, 256), activate_type="mish") 77 | input_data = common.convolutional(input_data, (1, 1, 512, 256), activate_type="mish") 78 | for i in range(8): 79 | input_data = common.residual_block(input_data, 256, 256, 256, activate_type="mish") 80 | input_data = common.convolutional(input_data, (1, 1, 256, 256), activate_type="mish") 81 | input_data = tf.concat([input_data, route], axis=-1) 82 | 83 | input_data = common.convolutional(input_data, (1, 1, 512, 512), activate_type="mish") 84 | route_2 = input_data 85 | input_data = common.convolutional(input_data, (3, 3, 512, 1024), downsample=True, activate_type="mish") 86 | route = input_data 87 | route = common.convolutional(route, (1, 1, 1024, 512), activate_type="mish") 88 | input_data = common.convolutional(input_data, (1, 1, 1024, 512), activate_type="mish") 89 | for i in range(4): 90 | input_data = common.residual_block(input_data, 512, 512, 512, activate_type="mish") 91 | input_data = common.convolutional(input_data, (1, 1, 512, 512), activate_type="mish") 92 | input_data = tf.concat([input_data, route], axis=-1) 93 | 94 | input_data = common.convolutional(input_data, (1, 1, 1024, 1024), activate_type="mish") 95 | input_data = common.convolutional(input_data, (1, 1, 1024, 512)) 96 | input_data = common.convolutional(input_data, (3, 3, 512, 1024)) 97 | input_data = common.convolutional(input_data, (1, 1, 1024, 512)) 98 | 99 | input_data = tf.concat([tf.nn.max_pool(input_data, ksize=13, padding='SAME', strides=1), tf.nn.max_pool(input_data, ksize=9, padding='SAME', strides=1) 100 | , tf.nn.max_pool(input_data, ksize=5, padding='SAME', strides=1), input_data], axis=-1) 101 | input_data = common.convolutional(input_data, (1, 1, 2048, 512)) 102 | input_data = common.convolutional(input_data, (3, 3, 512, 1024)) 103 | input_data = common.convolutional(input_data, (1, 1, 1024, 512)) 104 | 105 | return route_1, route_2, input_data 106 | 107 | def cspdarknet53_tiny(input_data): 108 | input_data = common.convolutional(input_data, (3, 3, 3, 32), downsample=True) 109 | input_data = common.convolutional(input_data, (3, 3, 32, 64), downsample=True) 110 | input_data = common.convolutional(input_data, (3, 3, 64, 64)) 111 | 112 | route = input_data 113 | input_data = common.route_group(input_data, 2, 1) 114 | input_data = common.convolutional(input_data, (3, 3, 32, 32)) 115 | route_1 = input_data 116 | input_data = common.convolutional(input_data, (3, 3, 32, 32)) 117 | input_data = tf.concat([input_data, route_1], axis=-1) 118 | input_data = common.convolutional(input_data, (1, 1, 32, 64)) 119 | input_data = tf.concat([route, input_data], axis=-1) 120 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 121 | 122 | input_data = common.convolutional(input_data, (3, 3, 64, 128)) 123 | route = input_data 124 | input_data = common.route_group(input_data, 2, 1) 125 | input_data = common.convolutional(input_data, (3, 3, 64, 64)) 126 | route_1 = input_data 127 | input_data = common.convolutional(input_data, (3, 3, 64, 64)) 128 | input_data = tf.concat([input_data, route_1], axis=-1) 129 | input_data = common.convolutional(input_data, (1, 1, 64, 128)) 130 | input_data = tf.concat([route, input_data], axis=-1) 131 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 132 | 133 | input_data = common.convolutional(input_data, (3, 3, 128, 256)) 134 | route = input_data 135 | input_data = common.route_group(input_data, 2, 1) 136 | input_data = common.convolutional(input_data, (3, 3, 128, 128)) 137 | route_1 = input_data 138 | input_data = common.convolutional(input_data, (3, 3, 128, 128)) 139 | input_data = tf.concat([input_data, route_1], axis=-1) 140 | input_data = common.convolutional(input_data, (1, 1, 128, 256)) 141 | route_1 = input_data 142 | input_data = tf.concat([route, input_data], axis=-1) 143 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 144 | 145 | input_data = common.convolutional(input_data, (3, 3, 512, 512)) 146 | 147 | return route_1, input_data 148 | 149 | def darknet53_tiny(input_data): 150 | input_data = common.convolutional(input_data, (3, 3, 3, 16)) 151 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 152 | input_data = common.convolutional(input_data, (3, 3, 16, 32)) 153 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 154 | input_data = common.convolutional(input_data, (3, 3, 32, 64)) 155 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 156 | input_data = common.convolutional(input_data, (3, 3, 64, 128)) 157 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 158 | input_data = common.convolutional(input_data, (3, 3, 128, 256)) 159 | route_1 = input_data 160 | input_data = tf.keras.layers.MaxPool2D(2, 2, 'same')(input_data) 161 | input_data = common.convolutional(input_data, (3, 3, 256, 512)) 162 | input_data = tf.keras.layers.MaxPool2D(2, 1, 'same')(input_data) 163 | input_data = common.convolutional(input_data, (3, 3, 512, 1024)) 164 | 165 | return route_1, input_data 166 | 167 | 168 | -------------------------------------------------------------------------------- /core/common.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding=utf-8 3 | 4 | import tensorflow as tf 5 | # import tensorflow_addons as tfa 6 | class BatchNormalization(tf.keras.layers.BatchNormalization): 7 | """ 8 | "Frozen state" and "inference mode" are two separate concepts. 9 | `layer.trainable = False` is to freeze the layer, so the layer will use 10 | stored moving `var` and `mean` in the "inference mode", and both `gama` 11 | and `beta` will not be updated ! 12 | """ 13 | def call(self, x, training=False): 14 | if not training: 15 | training = tf.constant(False) 16 | training = tf.logical_and(training, self.trainable) 17 | return super().call(x, training) 18 | 19 | def convolutional(input_layer, filters_shape, downsample=False, activate=True, bn=True, activate_type='leaky'): 20 | if downsample: 21 | input_layer = tf.keras.layers.ZeroPadding2D(((1, 0), (1, 0)))(input_layer) 22 | padding = 'valid' 23 | strides = 2 24 | else: 25 | strides = 1 26 | padding = 'same' 27 | 28 | conv = tf.keras.layers.Conv2D(filters=filters_shape[-1], kernel_size = filters_shape[0], strides=strides, padding=padding, 29 | use_bias=not bn, kernel_regularizer=tf.keras.regularizers.l2(0.0005), 30 | kernel_initializer=tf.random_normal_initializer(stddev=0.01), 31 | bias_initializer=tf.constant_initializer(0.))(input_layer) 32 | 33 | if bn: conv = BatchNormalization()(conv) 34 | if activate == True: 35 | if activate_type == "leaky": 36 | conv = tf.nn.leaky_relu(conv, alpha=0.1) 37 | elif activate_type == "mish": 38 | conv = mish(conv) 39 | return conv 40 | 41 | def mish(x): 42 | return x * tf.math.tanh(tf.math.softplus(x)) 43 | # return tf.keras.layers.Lambda(lambda x: x*tf.tanh(tf.math.log(1+tf.exp(x))))(x) 44 | 45 | def residual_block(input_layer, input_channel, filter_num1, filter_num2, activate_type='leaky'): 46 | short_cut = input_layer 47 | conv = convolutional(input_layer, filters_shape=(1, 1, input_channel, filter_num1), activate_type=activate_type) 48 | conv = convolutional(conv , filters_shape=(3, 3, filter_num1, filter_num2), activate_type=activate_type) 49 | 50 | residual_output = short_cut + conv 51 | return residual_output 52 | 53 | # def block_tiny(input_layer, input_channel, filter_num1, activate_type='leaky'): 54 | # conv = convolutional(input_layer, filters_shape=(3, 3, input_channel, filter_num1), activate_type=activate_type) 55 | # short_cut = input_layer 56 | # conv = convolutional(conv, filters_shape=(3, 3, input_channel, filter_num1), activate_type=activate_type) 57 | # 58 | # input_data = tf.concat([conv, short_cut], axis=-1) 59 | # return residual_output 60 | 61 | def route_group(input_layer, groups, group_id): 62 | convs = tf.split(input_layer, num_or_size_splits=groups, axis=-1) 63 | return convs[group_id] 64 | 65 | def upsample(input_layer): 66 | return tf.image.resize(input_layer, (input_layer.shape[1] * 2, input_layer.shape[2] * 2), method='bilinear') 67 | 68 | -------------------------------------------------------------------------------- /core/config.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding=utf-8 3 | from easydict import EasyDict as edict 4 | 5 | 6 | __C = edict() 7 | # Consumers can get config by: from config import cfg 8 | 9 | cfg = __C 10 | 11 | # YOLO options 12 | __C.YOLO = edict() 13 | 14 | __C.YOLO.CLASSES = "./data/classes/coco.names" 15 | __C.YOLO.ANCHORS = [12,16, 19,36, 40,28, 36,75, 76,55, 72,146, 142,110, 192,243, 459,401] 16 | __C.YOLO.ANCHORS_V3 = [10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326] 17 | __C.YOLO.ANCHORS_TINY = [23,27, 37,58, 81,82, 81,82, 135,169, 344,319] 18 | __C.YOLO.STRIDES = [8, 16, 32] 19 | __C.YOLO.STRIDES_TINY = [16, 32] 20 | __C.YOLO.XYSCALE = [1.2, 1.1, 1.05] 21 | __C.YOLO.XYSCALE_TINY = [1.05, 1.05] 22 | __C.YOLO.ANCHOR_PER_SCALE = 3 23 | __C.YOLO.IOU_LOSS_THRESH = 0.5 24 | 25 | 26 | # Train options 27 | __C.TRAIN = edict() 28 | 29 | __C.TRAIN.ANNOT_PATH = "./data/dataset/val2017.txt" 30 | __C.TRAIN.BATCH_SIZE = 2 31 | # __C.TRAIN.INPUT_SIZE = [320, 352, 384, 416, 448, 480, 512, 544, 576, 608] 32 | __C.TRAIN.INPUT_SIZE = 416 33 | __C.TRAIN.DATA_AUG = True 34 | __C.TRAIN.LR_INIT = 1e-3 35 | __C.TRAIN.LR_END = 1e-6 36 | __C.TRAIN.WARMUP_EPOCHS = 2 37 | __C.TRAIN.FISRT_STAGE_EPOCHS = 20 38 | __C.TRAIN.SECOND_STAGE_EPOCHS = 30 39 | 40 | 41 | 42 | # TEST options 43 | __C.TEST = edict() 44 | 45 | __C.TEST.ANNOT_PATH = "./data/dataset/val2017.txt" 46 | __C.TEST.BATCH_SIZE = 2 47 | __C.TEST.INPUT_SIZE = 416 48 | __C.TEST.DATA_AUG = False 49 | __C.TEST.DECTECTED_IMAGE_PATH = "./data/detection/" 50 | __C.TEST.SCORE_THRESHOLD = 0.25 51 | __C.TEST.IOU_THRESHOLD = 0.5 52 | 53 | 54 | -------------------------------------------------------------------------------- /core/dataset.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding=utf-8 3 | 4 | import os 5 | import cv2 6 | import random 7 | import numpy as np 8 | import tensorflow as tf 9 | import core.utils as utils 10 | from core.config import cfg 11 | 12 | 13 | class Dataset(object): 14 | """implement Dataset here""" 15 | 16 | def __init__(self, FLAGS, is_training: bool, dataset_type: str = "converted_coco"): 17 | self.tiny = FLAGS.tiny 18 | self.strides, self.anchors, NUM_CLASS, XYSCALE = utils.load_config(FLAGS) 19 | self.dataset_type = dataset_type 20 | 21 | self.annot_path = ( 22 | cfg.TRAIN.ANNOT_PATH if is_training else cfg.TEST.ANNOT_PATH 23 | ) 24 | self.input_sizes = ( 25 | cfg.TRAIN.INPUT_SIZE if is_training else cfg.TEST.INPUT_SIZE 26 | ) 27 | self.batch_size = ( 28 | cfg.TRAIN.BATCH_SIZE if is_training else cfg.TEST.BATCH_SIZE 29 | ) 30 | self.data_aug = cfg.TRAIN.DATA_AUG if is_training else cfg.TEST.DATA_AUG 31 | 32 | self.train_input_sizes = cfg.TRAIN.INPUT_SIZE 33 | self.classes = utils.read_class_names(cfg.YOLO.CLASSES) 34 | self.num_classes = len(self.classes) 35 | self.anchor_per_scale = cfg.YOLO.ANCHOR_PER_SCALE 36 | self.max_bbox_per_scale = 150 37 | 38 | self.annotations = self.load_annotations() 39 | self.num_samples = len(self.annotations) 40 | self.num_batchs = int(np.ceil(self.num_samples / self.batch_size)) 41 | self.batch_count = 0 42 | 43 | def load_annotations(self): 44 | with open(self.annot_path, "r") as f: 45 | txt = f.readlines() 46 | if self.dataset_type == "converted_coco": 47 | annotations = [ 48 | line.strip() 49 | for line in txt 50 | if len(line.strip().split()[1:]) != 0 51 | ] 52 | elif self.dataset_type == "yolo": 53 | annotations = [] 54 | for line in txt: 55 | image_path = line.strip() 56 | root, _ = os.path.splitext(image_path) 57 | with open(root + ".txt") as fd: 58 | boxes = fd.readlines() 59 | string = "" 60 | for box in boxes: 61 | box = box.strip() 62 | box = box.split() 63 | class_num = int(box[0]) 64 | center_x = float(box[1]) 65 | center_y = float(box[2]) 66 | half_width = float(box[3]) / 2 67 | half_height = float(box[4]) / 2 68 | string += " {},{},{},{},{}".format( 69 | center_x - half_width, 70 | center_y - half_height, 71 | center_x + half_width, 72 | center_y + half_height, 73 | class_num, 74 | ) 75 | annotations.append(image_path + string) 76 | 77 | np.random.shuffle(annotations) 78 | return annotations 79 | 80 | def __iter__(self): 81 | return self 82 | 83 | def __next__(self): 84 | with tf.device("/cpu:0"): 85 | # self.train_input_size = random.choice(self.train_input_sizes) 86 | self.train_input_size = cfg.TRAIN.INPUT_SIZE 87 | self.train_output_sizes = self.train_input_size // self.strides 88 | 89 | batch_image = np.zeros( 90 | ( 91 | self.batch_size, 92 | self.train_input_size, 93 | self.train_input_size, 94 | 3, 95 | ), 96 | dtype=np.float32, 97 | ) 98 | 99 | batch_label_sbbox = np.zeros( 100 | ( 101 | self.batch_size, 102 | self.train_output_sizes[0], 103 | self.train_output_sizes[0], 104 | self.anchor_per_scale, 105 | 5 + self.num_classes, 106 | ), 107 | dtype=np.float32, 108 | ) 109 | batch_label_mbbox = np.zeros( 110 | ( 111 | self.batch_size, 112 | self.train_output_sizes[1], 113 | self.train_output_sizes[1], 114 | self.anchor_per_scale, 115 | 5 + self.num_classes, 116 | ), 117 | dtype=np.float32, 118 | ) 119 | batch_label_lbbox = np.zeros( 120 | ( 121 | self.batch_size, 122 | self.train_output_sizes[2], 123 | self.train_output_sizes[2], 124 | self.anchor_per_scale, 125 | 5 + self.num_classes, 126 | ), 127 | dtype=np.float32, 128 | ) 129 | 130 | batch_sbboxes = np.zeros( 131 | (self.batch_size, self.max_bbox_per_scale, 4), dtype=np.float32 132 | ) 133 | batch_mbboxes = np.zeros( 134 | (self.batch_size, self.max_bbox_per_scale, 4), dtype=np.float32 135 | ) 136 | batch_lbboxes = np.zeros( 137 | (self.batch_size, self.max_bbox_per_scale, 4), dtype=np.float32 138 | ) 139 | 140 | num = 0 141 | if self.batch_count < self.num_batchs: 142 | while num < self.batch_size: 143 | index = self.batch_count * self.batch_size + num 144 | if index >= self.num_samples: 145 | index -= self.num_samples 146 | annotation = self.annotations[index] 147 | image, bboxes = self.parse_annotation(annotation) 148 | ( 149 | label_sbbox, 150 | label_mbbox, 151 | label_lbbox, 152 | sbboxes, 153 | mbboxes, 154 | lbboxes, 155 | ) = self.preprocess_true_boxes(bboxes) 156 | 157 | batch_image[num, :, :, :] = image 158 | batch_label_sbbox[num, :, :, :, :] = label_sbbox 159 | batch_label_mbbox[num, :, :, :, :] = label_mbbox 160 | batch_label_lbbox[num, :, :, :, :] = label_lbbox 161 | batch_sbboxes[num, :, :] = sbboxes 162 | batch_mbboxes[num, :, :] = mbboxes 163 | batch_lbboxes[num, :, :] = lbboxes 164 | num += 1 165 | self.batch_count += 1 166 | batch_smaller_target = batch_label_sbbox, batch_sbboxes 167 | batch_medium_target = batch_label_mbbox, batch_mbboxes 168 | batch_larger_target = batch_label_lbbox, batch_lbboxes 169 | 170 | return ( 171 | batch_image, 172 | ( 173 | batch_smaller_target, 174 | batch_medium_target, 175 | batch_larger_target, 176 | ), 177 | ) 178 | else: 179 | self.batch_count = 0 180 | np.random.shuffle(self.annotations) 181 | raise StopIteration 182 | 183 | def random_horizontal_flip(self, image, bboxes): 184 | if random.random() < 0.5: 185 | _, w, _ = image.shape 186 | image = image[:, ::-1, :] 187 | bboxes[:, [0, 2]] = w - bboxes[:, [2, 0]] 188 | 189 | return image, bboxes 190 | 191 | def random_crop(self, image, bboxes): 192 | if random.random() < 0.5: 193 | h, w, _ = image.shape 194 | max_bbox = np.concatenate( 195 | [ 196 | np.min(bboxes[:, 0:2], axis=0), 197 | np.max(bboxes[:, 2:4], axis=0), 198 | ], 199 | axis=-1, 200 | ) 201 | 202 | max_l_trans = max_bbox[0] 203 | max_u_trans = max_bbox[1] 204 | max_r_trans = w - max_bbox[2] 205 | max_d_trans = h - max_bbox[3] 206 | 207 | crop_xmin = max( 208 | 0, int(max_bbox[0] - random.uniform(0, max_l_trans)) 209 | ) 210 | crop_ymin = max( 211 | 0, int(max_bbox[1] - random.uniform(0, max_u_trans)) 212 | ) 213 | crop_xmax = max( 214 | w, int(max_bbox[2] + random.uniform(0, max_r_trans)) 215 | ) 216 | crop_ymax = max( 217 | h, int(max_bbox[3] + random.uniform(0, max_d_trans)) 218 | ) 219 | 220 | image = image[crop_ymin:crop_ymax, crop_xmin:crop_xmax] 221 | 222 | bboxes[:, [0, 2]] = bboxes[:, [0, 2]] - crop_xmin 223 | bboxes[:, [1, 3]] = bboxes[:, [1, 3]] - crop_ymin 224 | 225 | return image, bboxes 226 | 227 | def random_translate(self, image, bboxes): 228 | if random.random() < 0.5: 229 | h, w, _ = image.shape 230 | max_bbox = np.concatenate( 231 | [ 232 | np.min(bboxes[:, 0:2], axis=0), 233 | np.max(bboxes[:, 2:4], axis=0), 234 | ], 235 | axis=-1, 236 | ) 237 | 238 | max_l_trans = max_bbox[0] 239 | max_u_trans = max_bbox[1] 240 | max_r_trans = w - max_bbox[2] 241 | max_d_trans = h - max_bbox[3] 242 | 243 | tx = random.uniform(-(max_l_trans - 1), (max_r_trans - 1)) 244 | ty = random.uniform(-(max_u_trans - 1), (max_d_trans - 1)) 245 | 246 | M = np.array([[1, 0, tx], [0, 1, ty]]) 247 | image = cv2.warpAffine(image, M, (w, h)) 248 | 249 | bboxes[:, [0, 2]] = bboxes[:, [0, 2]] + tx 250 | bboxes[:, [1, 3]] = bboxes[:, [1, 3]] + ty 251 | 252 | return image, bboxes 253 | 254 | def parse_annotation(self, annotation): 255 | line = annotation.split() 256 | image_path = line[0] 257 | if not os.path.exists(image_path): 258 | raise KeyError("%s does not exist ... " % image_path) 259 | image = cv2.imread(image_path) 260 | if self.dataset_type == "converted_coco": 261 | bboxes = np.array( 262 | [list(map(int, box.split(","))) for box in line[1:]] 263 | ) 264 | elif self.dataset_type == "yolo": 265 | height, width, _ = image.shape 266 | bboxes = np.array( 267 | [list(map(float, box.split(","))) for box in line[1:]] 268 | ) 269 | bboxes = bboxes * np.array([width, height, width, height, 1]) 270 | bboxes = bboxes.astype(np.int64) 271 | 272 | if self.data_aug: 273 | image, bboxes = self.random_horizontal_flip( 274 | np.copy(image), np.copy(bboxes) 275 | ) 276 | image, bboxes = self.random_crop(np.copy(image), np.copy(bboxes)) 277 | image, bboxes = self.random_translate( 278 | np.copy(image), np.copy(bboxes) 279 | ) 280 | 281 | image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 282 | image, bboxes = utils.image_preprocess( 283 | np.copy(image), 284 | [self.train_input_size, self.train_input_size], 285 | np.copy(bboxes), 286 | ) 287 | return image, bboxes 288 | 289 | 290 | def preprocess_true_boxes(self, bboxes): 291 | label = [ 292 | np.zeros( 293 | ( 294 | self.train_output_sizes[i], 295 | self.train_output_sizes[i], 296 | self.anchor_per_scale, 297 | 5 + self.num_classes, 298 | ) 299 | ) 300 | for i in range(3) 301 | ] 302 | bboxes_xywh = [np.zeros((self.max_bbox_per_scale, 4)) for _ in range(3)] 303 | bbox_count = np.zeros((3,)) 304 | 305 | for bbox in bboxes: 306 | bbox_coor = bbox[:4] 307 | bbox_class_ind = bbox[4] 308 | 309 | onehot = np.zeros(self.num_classes, dtype=np.float) 310 | onehot[bbox_class_ind] = 1.0 311 | uniform_distribution = np.full( 312 | self.num_classes, 1.0 / self.num_classes 313 | ) 314 | deta = 0.01 315 | smooth_onehot = onehot * (1 - deta) + deta * uniform_distribution 316 | 317 | bbox_xywh = np.concatenate( 318 | [ 319 | (bbox_coor[2:] + bbox_coor[:2]) * 0.5, 320 | bbox_coor[2:] - bbox_coor[:2], 321 | ], 322 | axis=-1, 323 | ) 324 | bbox_xywh_scaled = ( 325 | 1.0 * bbox_xywh[np.newaxis, :] / self.strides[:, np.newaxis] 326 | ) 327 | 328 | iou = [] 329 | exist_positive = False 330 | for i in range(3): 331 | anchors_xywh = np.zeros((self.anchor_per_scale, 4)) 332 | anchors_xywh[:, 0:2] = ( 333 | np.floor(bbox_xywh_scaled[i, 0:2]).astype(np.int32) + 0.5 334 | ) 335 | anchors_xywh[:, 2:4] = self.anchors[i] 336 | 337 | iou_scale = utils.bbox_iou( 338 | bbox_xywh_scaled[i][np.newaxis, :], anchors_xywh 339 | ) 340 | iou.append(iou_scale) 341 | iou_mask = iou_scale > 0.3 342 | 343 | if np.any(iou_mask): 344 | xind, yind = np.floor(bbox_xywh_scaled[i, 0:2]).astype( 345 | np.int32 346 | ) 347 | 348 | label[i][yind, xind, iou_mask, :] = 0 349 | label[i][yind, xind, iou_mask, 0:4] = bbox_xywh 350 | label[i][yind, xind, iou_mask, 4:5] = 1.0 351 | label[i][yind, xind, iou_mask, 5:] = smooth_onehot 352 | 353 | bbox_ind = int(bbox_count[i] % self.max_bbox_per_scale) 354 | bboxes_xywh[i][bbox_ind, :4] = bbox_xywh 355 | bbox_count[i] += 1 356 | 357 | exist_positive = True 358 | 359 | if not exist_positive: 360 | best_anchor_ind = np.argmax(np.array(iou).reshape(-1), axis=-1) 361 | best_detect = int(best_anchor_ind / self.anchor_per_scale) 362 | best_anchor = int(best_anchor_ind % self.anchor_per_scale) 363 | xind, yind = np.floor( 364 | bbox_xywh_scaled[best_detect, 0:2] 365 | ).astype(np.int32) 366 | 367 | label[best_detect][yind, xind, best_anchor, :] = 0 368 | label[best_detect][yind, xind, best_anchor, 0:4] = bbox_xywh 369 | label[best_detect][yind, xind, best_anchor, 4:5] = 1.0 370 | label[best_detect][yind, xind, best_anchor, 5:] = smooth_onehot 371 | 372 | bbox_ind = int( 373 | bbox_count[best_detect] % self.max_bbox_per_scale 374 | ) 375 | bboxes_xywh[best_detect][bbox_ind, :4] = bbox_xywh 376 | bbox_count[best_detect] += 1 377 | label_sbbox, label_mbbox, label_lbbox = label 378 | sbboxes, mbboxes, lbboxes = bboxes_xywh 379 | return label_sbbox, label_mbbox, label_lbbox, sbboxes, mbboxes, lbboxes 380 | 381 | def __len__(self): 382 | return self.num_batchs 383 | -------------------------------------------------------------------------------- /core/utils.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import random 3 | import colorsys 4 | import numpy as np 5 | import tensorflow as tf 6 | from core.config import cfg 7 | 8 | def load_freeze_layer(model='yolov4', tiny=False): 9 | if tiny: 10 | if model == 'yolov3': 11 | freeze_layouts = ['conv2d_9', 'conv2d_12'] 12 | else: 13 | freeze_layouts = ['conv2d_17', 'conv2d_20'] 14 | else: 15 | if model == 'yolov3': 16 | freeze_layouts = ['conv2d_58', 'conv2d_66', 'conv2d_74'] 17 | else: 18 | freeze_layouts = ['conv2d_93', 'conv2d_101', 'conv2d_109'] 19 | return freeze_layouts 20 | 21 | def load_weights(model, weights_file, model_name='yolov4', is_tiny=False): 22 | if is_tiny: 23 | if model_name == 'yolov3': 24 | layer_size = 13 25 | output_pos = [9, 12] 26 | else: 27 | layer_size = 21 28 | output_pos = [17, 20] 29 | else: 30 | if model_name == 'yolov3': 31 | layer_size = 75 32 | output_pos = [58, 66, 74] 33 | else: 34 | layer_size = 110 35 | output_pos = [93, 101, 109] 36 | wf = open(weights_file, 'rb') 37 | major, minor, revision, seen, _ = np.fromfile(wf, dtype=np.int32, count=5) 38 | 39 | j = 0 40 | for i in range(layer_size): 41 | conv_layer_name = 'conv2d_%d' %i if i > 0 else 'conv2d' 42 | bn_layer_name = 'batch_normalization_%d' %j if j > 0 else 'batch_normalization' 43 | 44 | conv_layer = model.get_layer(conv_layer_name) 45 | filters = conv_layer.filters 46 | k_size = conv_layer.kernel_size[0] 47 | in_dim = conv_layer.input_shape[-1] 48 | 49 | if i not in output_pos: 50 | # darknet weights: [beta, gamma, mean, variance] 51 | bn_weights = np.fromfile(wf, dtype=np.float32, count=4 * filters) 52 | # tf weights: [gamma, beta, mean, variance] 53 | bn_weights = bn_weights.reshape((4, filters))[[1, 0, 2, 3]] 54 | bn_layer = model.get_layer(bn_layer_name) 55 | j += 1 56 | else: 57 | conv_bias = np.fromfile(wf, dtype=np.float32, count=filters) 58 | 59 | # darknet shape (out_dim, in_dim, height, width) 60 | conv_shape = (filters, in_dim, k_size, k_size) 61 | conv_weights = np.fromfile(wf, dtype=np.float32, count=np.product(conv_shape)) 62 | # tf shape (height, width, in_dim, out_dim) 63 | conv_weights = conv_weights.reshape(conv_shape).transpose([2, 3, 1, 0]) 64 | 65 | if i not in output_pos: 66 | conv_layer.set_weights([conv_weights]) 67 | bn_layer.set_weights(bn_weights) 68 | else: 69 | conv_layer.set_weights([conv_weights, conv_bias]) 70 | 71 | # assert len(wf.read()) == 0, 'failed to read all data' 72 | wf.close() 73 | 74 | 75 | def read_class_names(class_file_name): 76 | names = {} 77 | with open(class_file_name, 'r') as data: 78 | for ID, name in enumerate(data): 79 | names[ID] = name.strip('\n') 80 | return names 81 | 82 | def load_config(FLAGS): 83 | if FLAGS.tiny: 84 | STRIDES = np.array(cfg.YOLO.STRIDES_TINY) 85 | ANCHORS = get_anchors(cfg.YOLO.ANCHORS_TINY, FLAGS.tiny) 86 | XYSCALE = cfg.YOLO.XYSCALE_TINY if FLAGS.model == 'yolov4' else [1, 1] 87 | else: 88 | STRIDES = np.array(cfg.YOLO.STRIDES) 89 | if FLAGS.model == 'yolov4': 90 | ANCHORS = get_anchors(cfg.YOLO.ANCHORS, FLAGS.tiny) 91 | elif FLAGS.model == 'yolov3': 92 | ANCHORS = get_anchors(cfg.YOLO.ANCHORS_V3, FLAGS.tiny) 93 | XYSCALE = cfg.YOLO.XYSCALE if FLAGS.model == 'yolov4' else [1, 1, 1] 94 | NUM_CLASS = len(read_class_names(cfg.YOLO.CLASSES)) 95 | 96 | return STRIDES, ANCHORS, NUM_CLASS, XYSCALE 97 | 98 | def get_anchors(anchors_path, tiny=False): 99 | anchors = np.array(anchors_path) 100 | if tiny: 101 | return anchors.reshape(2, 3, 2) 102 | else: 103 | return anchors.reshape(3, 3, 2) 104 | 105 | def image_preprocess(image, target_size, gt_boxes=None): 106 | 107 | ih, iw = target_size 108 | h, w, _ = image.shape 109 | 110 | scale = min(iw/w, ih/h) 111 | nw, nh = int(scale * w), int(scale * h) 112 | image_resized = cv2.resize(image, (nw, nh)) 113 | 114 | image_paded = np.full(shape=[ih, iw, 3], fill_value=128.0) 115 | dw, dh = (iw - nw) // 2, (ih-nh) // 2 116 | image_paded[dh:nh+dh, dw:nw+dw, :] = image_resized 117 | image_paded = image_paded / 255. 118 | 119 | if gt_boxes is None: 120 | return image_paded 121 | 122 | else: 123 | gt_boxes[:, [0, 2]] = gt_boxes[:, [0, 2]] * scale + dw 124 | gt_boxes[:, [1, 3]] = gt_boxes[:, [1, 3]] * scale + dh 125 | return image_paded, gt_boxes 126 | 127 | def draw_bbox(image, bboxes, classes=read_class_names(cfg.YOLO.CLASSES), show_label=True): 128 | num_classes = len(classes) 129 | image_h, image_w, _ = image.shape 130 | hsv_tuples = [(1.0 * x / num_classes, 1., 1.) for x in range(num_classes)] 131 | colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) 132 | colors = list(map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors)) 133 | 134 | random.seed(0) 135 | random.shuffle(colors) 136 | random.seed(None) 137 | 138 | out_boxes, out_scores, out_classes, num_boxes = bboxes 139 | for i in range(num_boxes[0]): 140 | if int(out_classes[0][i]) < 0 or int(out_classes[0][i]) > num_classes: continue 141 | coor = out_boxes[0][i] 142 | coor[0] = int(coor[0] * image_h) 143 | coor[2] = int(coor[2] * image_h) 144 | coor[1] = int(coor[1] * image_w) 145 | coor[3] = int(coor[3] * image_w) 146 | 147 | fontScale = 0.5 148 | score = out_scores[0][i] 149 | class_ind = int(out_classes[0][i]) 150 | bbox_color = colors[class_ind] 151 | bbox_thick = int(0.6 * (image_h + image_w) / 600) 152 | c1, c2 = (coor[1], coor[0]), (coor[3], coor[2]) 153 | cv2.rectangle(image, c1, c2, bbox_color, bbox_thick) 154 | 155 | if show_label: 156 | bbox_mess = '%s: %.2f' % (classes[class_ind], score) 157 | t_size = cv2.getTextSize(bbox_mess, 0, fontScale, thickness=bbox_thick // 2)[0] 158 | c3 = (c1[0] + t_size[0], c1[1] - t_size[1] - 3) 159 | cv2.rectangle(image, c1, (np.float32(c3[0]), np.float32(c3[1])), bbox_color, -1) #filled 160 | 161 | cv2.putText(image, bbox_mess, (c1[0], np.float32(c1[1] - 2)), cv2.FONT_HERSHEY_SIMPLEX, 162 | fontScale, (0, 0, 0), bbox_thick // 2, lineType=cv2.LINE_AA) 163 | return image 164 | 165 | def bbox_iou(bboxes1, bboxes2): 166 | """ 167 | @param bboxes1: (a, b, ..., 4) 168 | @param bboxes2: (A, B, ..., 4) 169 | x:X is 1:n or n:n or n:1 170 | @return (max(a,A), max(b,B), ...) 171 | ex) (4,):(3,4) -> (3,) 172 | (2,1,4):(2,3,4) -> (2,3) 173 | """ 174 | bboxes1_area = bboxes1[..., 2] * bboxes1[..., 3] 175 | bboxes2_area = bboxes2[..., 2] * bboxes2[..., 3] 176 | 177 | bboxes1_coor = tf.concat( 178 | [ 179 | bboxes1[..., :2] - bboxes1[..., 2:] * 0.5, 180 | bboxes1[..., :2] + bboxes1[..., 2:] * 0.5, 181 | ], 182 | axis=-1, 183 | ) 184 | bboxes2_coor = tf.concat( 185 | [ 186 | bboxes2[..., :2] - bboxes2[..., 2:] * 0.5, 187 | bboxes2[..., :2] + bboxes2[..., 2:] * 0.5, 188 | ], 189 | axis=-1, 190 | ) 191 | 192 | left_up = tf.maximum(bboxes1_coor[..., :2], bboxes2_coor[..., :2]) 193 | right_down = tf.minimum(bboxes1_coor[..., 2:], bboxes2_coor[..., 2:]) 194 | 195 | inter_section = tf.maximum(right_down - left_up, 0.0) 196 | inter_area = inter_section[..., 0] * inter_section[..., 1] 197 | 198 | union_area = bboxes1_area + bboxes2_area - inter_area 199 | 200 | iou = tf.math.divide_no_nan(inter_area, union_area) 201 | 202 | return iou 203 | 204 | 205 | def bbox_giou(bboxes1, bboxes2): 206 | """ 207 | Generalized IoU 208 | @param bboxes1: (a, b, ..., 4) 209 | @param bboxes2: (A, B, ..., 4) 210 | x:X is 1:n or n:n or n:1 211 | @return (max(a,A), max(b,B), ...) 212 | ex) (4,):(3,4) -> (3,) 213 | (2,1,4):(2,3,4) -> (2,3) 214 | """ 215 | bboxes1_area = bboxes1[..., 2] * bboxes1[..., 3] 216 | bboxes2_area = bboxes2[..., 2] * bboxes2[..., 3] 217 | 218 | bboxes1_coor = tf.concat( 219 | [ 220 | bboxes1[..., :2] - bboxes1[..., 2:] * 0.5, 221 | bboxes1[..., :2] + bboxes1[..., 2:] * 0.5, 222 | ], 223 | axis=-1, 224 | ) 225 | bboxes2_coor = tf.concat( 226 | [ 227 | bboxes2[..., :2] - bboxes2[..., 2:] * 0.5, 228 | bboxes2[..., :2] + bboxes2[..., 2:] * 0.5, 229 | ], 230 | axis=-1, 231 | ) 232 | 233 | left_up = tf.maximum(bboxes1_coor[..., :2], bboxes2_coor[..., :2]) 234 | right_down = tf.minimum(bboxes1_coor[..., 2:], bboxes2_coor[..., 2:]) 235 | 236 | inter_section = tf.maximum(right_down - left_up, 0.0) 237 | inter_area = inter_section[..., 0] * inter_section[..., 1] 238 | 239 | union_area = bboxes1_area + bboxes2_area - inter_area 240 | 241 | iou = tf.math.divide_no_nan(inter_area, union_area) 242 | 243 | enclose_left_up = tf.minimum(bboxes1_coor[..., :2], bboxes2_coor[..., :2]) 244 | enclose_right_down = tf.maximum( 245 | bboxes1_coor[..., 2:], bboxes2_coor[..., 2:] 246 | ) 247 | 248 | enclose_section = enclose_right_down - enclose_left_up 249 | enclose_area = enclose_section[..., 0] * enclose_section[..., 1] 250 | 251 | giou = iou - tf.math.divide_no_nan(enclose_area - union_area, enclose_area) 252 | 253 | return giou 254 | 255 | 256 | def bbox_ciou(bboxes1, bboxes2): 257 | """ 258 | Complete IoU 259 | @param bboxes1: (a, b, ..., 4) 260 | @param bboxes2: (A, B, ..., 4) 261 | x:X is 1:n or n:n or n:1 262 | @return (max(a,A), max(b,B), ...) 263 | ex) (4,):(3,4) -> (3,) 264 | (2,1,4):(2,3,4) -> (2,3) 265 | """ 266 | bboxes1_area = bboxes1[..., 2] * bboxes1[..., 3] 267 | bboxes2_area = bboxes2[..., 2] * bboxes2[..., 3] 268 | 269 | bboxes1_coor = tf.concat( 270 | [ 271 | bboxes1[..., :2] - bboxes1[..., 2:] * 0.5, 272 | bboxes1[..., :2] + bboxes1[..., 2:] * 0.5, 273 | ], 274 | axis=-1, 275 | ) 276 | bboxes2_coor = tf.concat( 277 | [ 278 | bboxes2[..., :2] - bboxes2[..., 2:] * 0.5, 279 | bboxes2[..., :2] + bboxes2[..., 2:] * 0.5, 280 | ], 281 | axis=-1, 282 | ) 283 | 284 | left_up = tf.maximum(bboxes1_coor[..., :2], bboxes2_coor[..., :2]) 285 | right_down = tf.minimum(bboxes1_coor[..., 2:], bboxes2_coor[..., 2:]) 286 | 287 | inter_section = tf.maximum(right_down - left_up, 0.0) 288 | inter_area = inter_section[..., 0] * inter_section[..., 1] 289 | 290 | union_area = bboxes1_area + bboxes2_area - inter_area 291 | 292 | iou = tf.math.divide_no_nan(inter_area, union_area) 293 | 294 | enclose_left_up = tf.minimum(bboxes1_coor[..., :2], bboxes2_coor[..., :2]) 295 | enclose_right_down = tf.maximum( 296 | bboxes1_coor[..., 2:], bboxes2_coor[..., 2:] 297 | ) 298 | 299 | enclose_section = enclose_right_down - enclose_left_up 300 | 301 | c_2 = enclose_section[..., 0] ** 2 + enclose_section[..., 1] ** 2 302 | 303 | center_diagonal = bboxes2[..., :2] - bboxes1[..., :2] 304 | 305 | rho_2 = center_diagonal[..., 0] ** 2 + center_diagonal[..., 1] ** 2 306 | 307 | diou = iou - tf.math.divide_no_nan(rho_2, c_2) 308 | 309 | v = ( 310 | ( 311 | tf.math.atan( 312 | tf.math.divide_no_nan(bboxes1[..., 2], bboxes1[..., 3]) 313 | ) 314 | - tf.math.atan( 315 | tf.math.divide_no_nan(bboxes2[..., 2], bboxes2[..., 3]) 316 | ) 317 | ) 318 | * 2 319 | / np.pi 320 | ) ** 2 321 | 322 | alpha = tf.math.divide_no_nan(v, 1 - iou + v) 323 | 324 | ciou = diou - alpha * v 325 | 326 | return ciou 327 | 328 | def nms(bboxes, iou_threshold, sigma=0.3, method='nms'): 329 | """ 330 | :param bboxes: (xmin, ymin, xmax, ymax, score, class) 331 | 332 | Note: soft-nms, https://arxiv.org/pdf/1704.04503.pdf 333 | https://github.com/bharatsingh430/soft-nms 334 | """ 335 | classes_in_img = list(set(bboxes[:, 5])) 336 | best_bboxes = [] 337 | 338 | for cls in classes_in_img: 339 | cls_mask = (bboxes[:, 5] == cls) 340 | cls_bboxes = bboxes[cls_mask] 341 | 342 | while len(cls_bboxes) > 0: 343 | max_ind = np.argmax(cls_bboxes[:, 4]) 344 | best_bbox = cls_bboxes[max_ind] 345 | best_bboxes.append(best_bbox) 346 | cls_bboxes = np.concatenate([cls_bboxes[: max_ind], cls_bboxes[max_ind + 1:]]) 347 | iou = bbox_iou(best_bbox[np.newaxis, :4], cls_bboxes[:, :4]) 348 | weight = np.ones((len(iou),), dtype=np.float32) 349 | 350 | assert method in ['nms', 'soft-nms'] 351 | 352 | if method == 'nms': 353 | iou_mask = iou > iou_threshold 354 | weight[iou_mask] = 0.0 355 | 356 | if method == 'soft-nms': 357 | weight = np.exp(-(1.0 * iou ** 2 / sigma)) 358 | 359 | cls_bboxes[:, 4] = cls_bboxes[:, 4] * weight 360 | score_mask = cls_bboxes[:, 4] > 0. 361 | cls_bboxes = cls_bboxes[score_mask] 362 | 363 | return best_bboxes 364 | 365 | def freeze_all(model, frozen=True): 366 | model.trainable = not frozen 367 | if isinstance(model, tf.keras.Model): 368 | for l in model.layers: 369 | freeze_all(l, frozen) 370 | def unfreeze_all(model, frozen=False): 371 | model.trainable = not frozen 372 | if isinstance(model, tf.keras.Model): 373 | for l in model.layers: 374 | unfreeze_all(l, frozen) 375 | 376 | -------------------------------------------------------------------------------- /core/yolov4.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding=utf-8 3 | 4 | import numpy as np 5 | import tensorflow as tf 6 | import core.utils as utils 7 | import core.common as common 8 | import core.backbone as backbone 9 | from core.config import cfg 10 | 11 | # NUM_CLASS = len(utils.read_class_names(cfg.YOLO.CLASSES)) 12 | # STRIDES = np.array(cfg.YOLO.STRIDES) 13 | # IOU_LOSS_THRESH = cfg.YOLO.IOU_LOSS_THRESH 14 | # XYSCALE = cfg.YOLO.XYSCALE 15 | # ANCHORS = utils.get_anchors(cfg.YOLO.ANCHORS) 16 | 17 | def YOLO(input_layer, NUM_CLASS, model='yolov4', is_tiny=False): 18 | if is_tiny: 19 | if model == 'yolov4': 20 | return YOLOv4_tiny(input_layer, NUM_CLASS) 21 | elif model == 'yolov3': 22 | return YOLOv3_tiny(input_layer, NUM_CLASS) 23 | else: 24 | if model == 'yolov4': 25 | return YOLOv4(input_layer, NUM_CLASS) 26 | elif model == 'yolov3': 27 | return YOLOv3(input_layer, NUM_CLASS) 28 | 29 | def YOLOv3(input_layer, NUM_CLASS): 30 | route_1, route_2, conv = backbone.darknet53(input_layer) 31 | 32 | conv = common.convolutional(conv, (1, 1, 1024, 512)) 33 | conv = common.convolutional(conv, (3, 3, 512, 1024)) 34 | conv = common.convolutional(conv, (1, 1, 1024, 512)) 35 | conv = common.convolutional(conv, (3, 3, 512, 1024)) 36 | conv = common.convolutional(conv, (1, 1, 1024, 512)) 37 | 38 | conv_lobj_branch = common.convolutional(conv, (3, 3, 512, 1024)) 39 | conv_lbbox = common.convolutional(conv_lobj_branch, (1, 1, 1024, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 40 | 41 | conv = common.convolutional(conv, (1, 1, 512, 256)) 42 | conv = common.upsample(conv) 43 | 44 | conv = tf.concat([conv, route_2], axis=-1) 45 | 46 | conv = common.convolutional(conv, (1, 1, 768, 256)) 47 | conv = common.convolutional(conv, (3, 3, 256, 512)) 48 | conv = common.convolutional(conv, (1, 1, 512, 256)) 49 | conv = common.convolutional(conv, (3, 3, 256, 512)) 50 | conv = common.convolutional(conv, (1, 1, 512, 256)) 51 | 52 | conv_mobj_branch = common.convolutional(conv, (3, 3, 256, 512)) 53 | conv_mbbox = common.convolutional(conv_mobj_branch, (1, 1, 512, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 54 | 55 | conv = common.convolutional(conv, (1, 1, 256, 128)) 56 | conv = common.upsample(conv) 57 | 58 | conv = tf.concat([conv, route_1], axis=-1) 59 | 60 | conv = common.convolutional(conv, (1, 1, 384, 128)) 61 | conv = common.convolutional(conv, (3, 3, 128, 256)) 62 | conv = common.convolutional(conv, (1, 1, 256, 128)) 63 | conv = common.convolutional(conv, (3, 3, 128, 256)) 64 | conv = common.convolutional(conv, (1, 1, 256, 128)) 65 | 66 | conv_sobj_branch = common.convolutional(conv, (3, 3, 128, 256)) 67 | conv_sbbox = common.convolutional(conv_sobj_branch, (1, 1, 256, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 68 | 69 | return [conv_sbbox, conv_mbbox, conv_lbbox] 70 | 71 | def YOLOv4(input_layer, NUM_CLASS): 72 | route_1, route_2, conv = backbone.cspdarknet53(input_layer) 73 | 74 | route = conv 75 | conv = common.convolutional(conv, (1, 1, 512, 256)) 76 | conv = common.upsample(conv) 77 | route_2 = common.convolutional(route_2, (1, 1, 512, 256)) 78 | conv = tf.concat([route_2, conv], axis=-1) 79 | 80 | conv = common.convolutional(conv, (1, 1, 512, 256)) 81 | conv = common.convolutional(conv, (3, 3, 256, 512)) 82 | conv = common.convolutional(conv, (1, 1, 512, 256)) 83 | conv = common.convolutional(conv, (3, 3, 256, 512)) 84 | conv = common.convolutional(conv, (1, 1, 512, 256)) 85 | 86 | route_2 = conv 87 | conv = common.convolutional(conv, (1, 1, 256, 128)) 88 | conv = common.upsample(conv) 89 | route_1 = common.convolutional(route_1, (1, 1, 256, 128)) 90 | conv = tf.concat([route_1, conv], axis=-1) 91 | 92 | conv = common.convolutional(conv, (1, 1, 256, 128)) 93 | conv = common.convolutional(conv, (3, 3, 128, 256)) 94 | conv = common.convolutional(conv, (1, 1, 256, 128)) 95 | conv = common.convolutional(conv, (3, 3, 128, 256)) 96 | conv = common.convolutional(conv, (1, 1, 256, 128)) 97 | 98 | route_1 = conv 99 | conv = common.convolutional(conv, (3, 3, 128, 256)) 100 | conv_sbbox = common.convolutional(conv, (1, 1, 256, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 101 | 102 | conv = common.convolutional(route_1, (3, 3, 128, 256), downsample=True) 103 | conv = tf.concat([conv, route_2], axis=-1) 104 | 105 | conv = common.convolutional(conv, (1, 1, 512, 256)) 106 | conv = common.convolutional(conv, (3, 3, 256, 512)) 107 | conv = common.convolutional(conv, (1, 1, 512, 256)) 108 | conv = common.convolutional(conv, (3, 3, 256, 512)) 109 | conv = common.convolutional(conv, (1, 1, 512, 256)) 110 | 111 | route_2 = conv 112 | conv = common.convolutional(conv, (3, 3, 256, 512)) 113 | conv_mbbox = common.convolutional(conv, (1, 1, 512, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 114 | 115 | conv = common.convolutional(route_2, (3, 3, 256, 512), downsample=True) 116 | conv = tf.concat([conv, route], axis=-1) 117 | 118 | conv = common.convolutional(conv, (1, 1, 1024, 512)) 119 | conv = common.convolutional(conv, (3, 3, 512, 1024)) 120 | conv = common.convolutional(conv, (1, 1, 1024, 512)) 121 | conv = common.convolutional(conv, (3, 3, 512, 1024)) 122 | conv = common.convolutional(conv, (1, 1, 1024, 512)) 123 | 124 | conv = common.convolutional(conv, (3, 3, 512, 1024)) 125 | conv_lbbox = common.convolutional(conv, (1, 1, 1024, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 126 | 127 | return [conv_sbbox, conv_mbbox, conv_lbbox] 128 | 129 | def YOLOv4_tiny(input_layer, NUM_CLASS): 130 | route_1, conv = backbone.cspdarknet53_tiny(input_layer) 131 | 132 | conv = common.convolutional(conv, (1, 1, 512, 256)) 133 | 134 | conv_lobj_branch = common.convolutional(conv, (3, 3, 256, 512)) 135 | conv_lbbox = common.convolutional(conv_lobj_branch, (1, 1, 512, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 136 | 137 | conv = common.convolutional(conv, (1, 1, 256, 128)) 138 | conv = common.upsample(conv) 139 | conv = tf.concat([conv, route_1], axis=-1) 140 | 141 | conv_mobj_branch = common.convolutional(conv, (3, 3, 128, 256)) 142 | conv_mbbox = common.convolutional(conv_mobj_branch, (1, 1, 256, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 143 | 144 | return [conv_mbbox, conv_lbbox] 145 | 146 | def YOLOv3_tiny(input_layer, NUM_CLASS): 147 | route_1, conv = backbone.darknet53_tiny(input_layer) 148 | 149 | conv = common.convolutional(conv, (1, 1, 1024, 256)) 150 | 151 | conv_lobj_branch = common.convolutional(conv, (3, 3, 256, 512)) 152 | conv_lbbox = common.convolutional(conv_lobj_branch, (1, 1, 512, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 153 | 154 | conv = common.convolutional(conv, (1, 1, 256, 128)) 155 | conv = common.upsample(conv) 156 | conv = tf.concat([conv, route_1], axis=-1) 157 | 158 | conv_mobj_branch = common.convolutional(conv, (3, 3, 128, 256)) 159 | conv_mbbox = common.convolutional(conv_mobj_branch, (1, 1, 256, 3 * (NUM_CLASS + 5)), activate=False, bn=False) 160 | 161 | return [conv_mbbox, conv_lbbox] 162 | 163 | def decode(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE=[1,1,1], FRAMEWORK='tf'): 164 | if FRAMEWORK == 'trt': 165 | return decode_trt(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=i, XYSCALE=XYSCALE) 166 | elif FRAMEWORK == 'tflite': 167 | return decode_tflite(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=i, XYSCALE=XYSCALE) 168 | else: 169 | return decode_tf(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=i, XYSCALE=XYSCALE) 170 | 171 | def decode_train(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1, 1, 1]): 172 | conv_output = tf.reshape(conv_output, 173 | (tf.shape(conv_output)[0], output_size, output_size, 3, 5 + NUM_CLASS)) 174 | 175 | conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), 176 | axis=-1) 177 | 178 | xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size)) 179 | xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2] 180 | xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [tf.shape(conv_output)[0], 1, 1, 3, 1]) 181 | 182 | xy_grid = tf.cast(xy_grid, tf.float32) 183 | 184 | pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \ 185 | STRIDES[i] 186 | pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i]) 187 | pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1) 188 | 189 | pred_conf = tf.sigmoid(conv_raw_conf) 190 | pred_prob = tf.sigmoid(conv_raw_prob) 191 | 192 | return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1) 193 | 194 | def decode_tf(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1, 1, 1]): 195 | batch_size = tf.shape(conv_output)[0] 196 | conv_output = tf.reshape(conv_output, 197 | (batch_size, output_size, output_size, 3, 5 + NUM_CLASS)) 198 | 199 | conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), 200 | axis=-1) 201 | 202 | xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size)) 203 | xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2] 204 | xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [batch_size, 1, 1, 3, 1]) 205 | 206 | xy_grid = tf.cast(xy_grid, tf.float32) 207 | 208 | pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \ 209 | STRIDES[i] 210 | pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i]) 211 | pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1) 212 | 213 | pred_conf = tf.sigmoid(conv_raw_conf) 214 | pred_prob = tf.sigmoid(conv_raw_prob) 215 | 216 | pred_prob = pred_conf * pred_prob 217 | pred_prob = tf.reshape(pred_prob, (batch_size, -1, NUM_CLASS)) 218 | pred_xywh = tf.reshape(pred_xywh, (batch_size, -1, 4)) 219 | 220 | return pred_xywh, pred_prob 221 | # return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1) 222 | 223 | def decode_tflite(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1,1,1]): 224 | conv_raw_dxdy_0, conv_raw_dwdh_0, conv_raw_score_0,\ 225 | conv_raw_dxdy_1, conv_raw_dwdh_1, conv_raw_score_1,\ 226 | conv_raw_dxdy_2, conv_raw_dwdh_2, conv_raw_score_2 = tf.split(conv_output, (2, 2, 1+NUM_CLASS, 2, 2, 1+NUM_CLASS, 227 | 2, 2, 1+NUM_CLASS), axis=-1) 228 | 229 | conv_raw_score = [conv_raw_score_0, conv_raw_score_1, conv_raw_score_2] 230 | for idx, score in enumerate(conv_raw_score): 231 | score = tf.sigmoid(score) 232 | score = score[:, :, :, 0:1] * score[:, :, :, 1:] 233 | conv_raw_score[idx] = tf.reshape(score, (1, -1, NUM_CLASS)) 234 | pred_prob = tf.concat(conv_raw_score, axis=1) 235 | 236 | conv_raw_dwdh = [conv_raw_dwdh_0, conv_raw_dwdh_1, conv_raw_dwdh_2] 237 | for idx, dwdh in enumerate(conv_raw_dwdh): 238 | dwdh = tf.exp(dwdh) * ANCHORS[i][idx] 239 | conv_raw_dwdh[idx] = tf.reshape(dwdh, (1, -1, 2)) 240 | pred_wh = tf.concat(conv_raw_dwdh, axis=1) 241 | 242 | xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size)) 243 | xy_grid = tf.stack(xy_grid, axis=-1) # [gx, gy, 2] 244 | xy_grid = tf.expand_dims(xy_grid, axis=0) 245 | xy_grid = tf.cast(xy_grid, tf.float32) 246 | 247 | conv_raw_dxdy = [conv_raw_dxdy_0, conv_raw_dxdy_1, conv_raw_dxdy_2] 248 | for idx, dxdy in enumerate(conv_raw_dxdy): 249 | dxdy = ((tf.sigmoid(dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \ 250 | STRIDES[i] 251 | conv_raw_dxdy[idx] = tf.reshape(dxdy, (1, -1, 2)) 252 | pred_xy = tf.concat(conv_raw_dxdy, axis=1) 253 | pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1) 254 | return pred_xywh, pred_prob 255 | # return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1) 256 | 257 | def decode_trt(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1,1,1]): 258 | batch_size = tf.shape(conv_output)[0] 259 | conv_output = tf.reshape(conv_output, (batch_size, output_size, output_size, 3, 5 + NUM_CLASS)) 260 | 261 | conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), axis=-1) 262 | 263 | xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size)) 264 | xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2] 265 | xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [batch_size, 1, 1, 3, 1]) 266 | 267 | # x = tf.tile(tf.expand_dims(tf.range(output_size, dtype=tf.float32), axis=0), [output_size, 1]) 268 | # y = tf.tile(tf.expand_dims(tf.range(output_size, dtype=tf.float32), axis=1), [1, output_size]) 269 | # xy_grid = tf.expand_dims(tf.stack([x, y], axis=-1), axis=2) # [gx, gy, 1, 2] 270 | # xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [tf.shape(conv_output)[0], 1, 1, 3, 1]) 271 | 272 | xy_grid = tf.cast(xy_grid, tf.float32) 273 | 274 | # pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \ 275 | # STRIDES[i] 276 | pred_xy = (tf.reshape(tf.sigmoid(conv_raw_dxdy), (-1, 2)) * XYSCALE[i] - 0.5 * (XYSCALE[i] - 1) + tf.reshape(xy_grid, (-1, 2))) * STRIDES[i] 277 | pred_xy = tf.reshape(pred_xy, (batch_size, output_size, output_size, 3, 2)) 278 | pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i]) 279 | pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1) 280 | 281 | pred_conf = tf.sigmoid(conv_raw_conf) 282 | pred_prob = tf.sigmoid(conv_raw_prob) 283 | 284 | pred_prob = pred_conf * pred_prob 285 | 286 | pred_prob = tf.reshape(pred_prob, (batch_size, -1, NUM_CLASS)) 287 | pred_xywh = tf.reshape(pred_xywh, (batch_size, -1, 4)) 288 | return pred_xywh, pred_prob 289 | # return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1) 290 | 291 | 292 | def filter_boxes(box_xywh, scores, score_threshold=0.4, input_shape = tf.constant([416,416])): 293 | scores_max = tf.math.reduce_max(scores, axis=-1) 294 | 295 | mask = scores_max >= score_threshold 296 | class_boxes = tf.boolean_mask(box_xywh, mask) 297 | pred_conf = tf.boolean_mask(scores, mask) 298 | class_boxes = tf.reshape(class_boxes, [tf.shape(scores)[0], -1, tf.shape(class_boxes)[-1]]) 299 | pred_conf = tf.reshape(pred_conf, [tf.shape(scores)[0], -1, tf.shape(pred_conf)[-1]]) 300 | 301 | box_xy, box_wh = tf.split(class_boxes, (2, 2), axis=-1) 302 | 303 | input_shape = tf.cast(input_shape, dtype=tf.float32) 304 | 305 | box_yx = box_xy[..., ::-1] 306 | box_hw = box_wh[..., ::-1] 307 | 308 | box_mins = (box_yx - (box_hw / 2.)) / input_shape 309 | box_maxes = (box_yx + (box_hw / 2.)) / input_shape 310 | boxes = tf.concat([ 311 | box_mins[..., 0:1], # y_min 312 | box_mins[..., 1:2], # x_min 313 | box_maxes[..., 0:1], # y_max 314 | box_maxes[..., 1:2] # x_max 315 | ], axis=-1) 316 | # return tf.concat([boxes, pred_conf], axis=-1) 317 | return (boxes, pred_conf) 318 | 319 | 320 | def compute_loss(pred, conv, label, bboxes, STRIDES, NUM_CLASS, IOU_LOSS_THRESH, i=0): 321 | conv_shape = tf.shape(conv) 322 | batch_size = conv_shape[0] 323 | output_size = conv_shape[1] 324 | input_size = STRIDES[i] * output_size 325 | conv = tf.reshape(conv, (batch_size, output_size, output_size, 3, 5 + NUM_CLASS)) 326 | 327 | conv_raw_conf = conv[:, :, :, :, 4:5] 328 | conv_raw_prob = conv[:, :, :, :, 5:] 329 | 330 | pred_xywh = pred[:, :, :, :, 0:4] 331 | pred_conf = pred[:, :, :, :, 4:5] 332 | 333 | label_xywh = label[:, :, :, :, 0:4] 334 | respond_bbox = label[:, :, :, :, 4:5] 335 | label_prob = label[:, :, :, :, 5:] 336 | 337 | giou = tf.expand_dims(utils.bbox_giou(pred_xywh, label_xywh), axis=-1) 338 | input_size = tf.cast(input_size, tf.float32) 339 | 340 | bbox_loss_scale = 2.0 - 1.0 * label_xywh[:, :, :, :, 2:3] * label_xywh[:, :, :, :, 3:4] / (input_size ** 2) 341 | giou_loss = respond_bbox * bbox_loss_scale * (1- giou) 342 | 343 | iou = utils.bbox_iou(pred_xywh[:, :, :, :, np.newaxis, :], bboxes[:, np.newaxis, np.newaxis, np.newaxis, :, :]) 344 | max_iou = tf.expand_dims(tf.reduce_max(iou, axis=-1), axis=-1) 345 | 346 | respond_bgd = (1.0 - respond_bbox) * tf.cast( max_iou < IOU_LOSS_THRESH, tf.float32 ) 347 | 348 | conf_focal = tf.pow(respond_bbox - pred_conf, 2) 349 | 350 | conf_loss = conf_focal * ( 351 | respond_bbox * tf.nn.sigmoid_cross_entropy_with_logits(labels=respond_bbox, logits=conv_raw_conf) 352 | + 353 | respond_bgd * tf.nn.sigmoid_cross_entropy_with_logits(labels=respond_bbox, logits=conv_raw_conf) 354 | ) 355 | 356 | prob_loss = respond_bbox * tf.nn.sigmoid_cross_entropy_with_logits(labels=label_prob, logits=conv_raw_prob) 357 | 358 | giou_loss = tf.reduce_mean(tf.reduce_sum(giou_loss, axis=[1,2,3,4])) 359 | conf_loss = tf.reduce_mean(tf.reduce_sum(conf_loss, axis=[1,2,3,4])) 360 | prob_loss = tf.reduce_mean(tf.reduce_sum(prob_loss, axis=[1,2,3,4])) 361 | 362 | return giou_loss, conf_loss, prob_loss 363 | 364 | 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /data/anchors/basline_anchors.txt: -------------------------------------------------------------------------------- 1 | 1.25,1.625, 2.0,3.75, 4.125,2.875, 1.875,3.8125, 3.875,2.8125, 3.6875,7.4375, 3.625,2.8125, 4.875,6.1875, 11.65625,10.1875 2 | -------------------------------------------------------------------------------- /data/anchors/basline_tiny_anchors.txt: -------------------------------------------------------------------------------- 1 | 23,27, 37,58, 81,82, 81,82, 135,169, 344,319 -------------------------------------------------------------------------------- /data/anchors/yolov3_anchors.txt: -------------------------------------------------------------------------------- 1 | 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 -------------------------------------------------------------------------------- /data/anchors/yolov4_anchors.txt: -------------------------------------------------------------------------------- 1 | 12,16, 19,36, 40,28, 36,75, 76,55, 72,146, 142,110, 192,243, 459,401 2 | -------------------------------------------------------------------------------- /data/classes/coco.names: -------------------------------------------------------------------------------- 1 | person 2 | bicycle 3 | car 4 | motorbike 5 | aeroplane 6 | bus 7 | train 8 | truck 9 | boat 10 | traffic light 11 | fire hydrant 12 | stop sign 13 | parking meter 14 | bench 15 | bird 16 | cat 17 | dog 18 | horse 19 | sheep 20 | cow 21 | elephant 22 | bear 23 | zebra 24 | giraffe 25 | backpack 26 | umbrella 27 | handbag 28 | tie 29 | suitcase 30 | frisbee 31 | skis 32 | snowboard 33 | sports ball 34 | kite 35 | baseball bat 36 | baseball glove 37 | skateboard 38 | surfboard 39 | tennis racket 40 | bottle 41 | wine glass 42 | cup 43 | fork 44 | knife 45 | spoon 46 | bowl 47 | banana 48 | apple 49 | sandwich 50 | orange 51 | broccoli 52 | carrot 53 | hot dog 54 | pizza 55 | donut 56 | cake 57 | chair 58 | sofa 59 | potted plant 60 | bed 61 | dining table 62 | toilet 63 | tvmonitor 64 | laptop 65 | mouse 66 | remote 67 | keyboard 68 | cell phone 69 | microwave 70 | oven 71 | toaster 72 | sink 73 | refrigerator 74 | book 75 | clock 76 | vase 77 | scissors 78 | teddy bear 79 | hair drier 80 | toothbrush 81 | -------------------------------------------------------------------------------- /data/classes/license.names: -------------------------------------------------------------------------------- 1 | license_plate 2 | -------------------------------------------------------------------------------- /data/classes/logo.names: -------------------------------------------------------------------------------- 1 | suzuki 2 | hyundai 3 | toyota 4 | mahindra -------------------------------------------------------------------------------- /data/classes/voc.names: -------------------------------------------------------------------------------- 1 | aeroplane 2 | bicycle 3 | bird 4 | boat 5 | bottle 6 | bus 7 | car 8 | cat 9 | chair 10 | cow 11 | diningtable 12 | dog 13 | horse 14 | motorbike 15 | person 16 | pottedplant 17 | sheep 18 | sofa 19 | train 20 | tvmonitor -------------------------------------------------------------------------------- /data/classes/yymnist.names: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | -------------------------------------------------------------------------------- /data/logo.names: -------------------------------------------------------------------------------- 1 | suzuki 2 | hyundai 3 | toyota 4 | mahindra -------------------------------------------------------------------------------- /data/ss/dataOutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/dataOutput.png -------------------------------------------------------------------------------- /data/ss/result14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result14.jpg -------------------------------------------------------------------------------- /data/ss/result15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result15.jpg -------------------------------------------------------------------------------- /data/ss/result16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result16.jpg -------------------------------------------------------------------------------- /data/ss/result5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result5.png -------------------------------------------------------------------------------- /data/ss/result6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result6.jpg -------------------------------------------------------------------------------- /data/ss/result7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result7.jpg -------------------------------------------------------------------------------- /data/ss/result8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-File/Vehicle-Identification-Speed-Detection/a6f95c9f35fcb1adf81596a1dc6f08ec9564e42f/data/ss/result8.jpg -------------------------------------------------------------------------------- /detect.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | physical_devices = tf.config.experimental.list_physical_devices('GPU') 3 | if len(physical_devices) > 0: 4 | tf.config.experimental.set_memory_growth(physical_devices[0], True) 5 | from absl import app, flags, logging 6 | from absl.flags import FLAGS 7 | import core.utils as utils 8 | from core.yolov4 import filter_boxes 9 | from tensorflow.python.saved_model import tag_constants 10 | from PIL import Image 11 | import cv2 12 | import numpy as np 13 | from tensorflow.compat.v1 import ConfigProto 14 | from tensorflow.compat.v1 import InteractiveSession 15 | 16 | flags.DEFINE_string('framework', 'tf', '(tf, tflite, trt') 17 | flags.DEFINE_string('weights', './checkpoints/yolov4-416', 18 | 'path to weights file') 19 | flags.DEFINE_integer('size', 416, 'resize images to') 20 | flags.DEFINE_boolean('tiny', False, 'yolo or yolo-tiny') 21 | flags.DEFINE_string('model', 'yolov4', 'yolov3 or yolov4') 22 | flags.DEFINE_list('images', './data/images/kite.jpg', 'path to input image') 23 | flags.DEFINE_string('output', './detections/', 'path to output folder') 24 | flags.DEFINE_float('iou', 0.45, 'iou threshold') 25 | flags.DEFINE_float('score', 0.25, 'score threshold') 26 | flags.DEFINE_boolean('dont_show', False, 'dont show image output') 27 | 28 | def main(_argv): 29 | config = ConfigProto() 30 | config.gpu_options.allow_growth = True 31 | session = InteractiveSession(config=config) 32 | STRIDES, ANCHORS, NUM_CLASS, XYSCALE = utils.load_config(FLAGS) 33 | input_size = FLAGS.size 34 | images = FLAGS.images 35 | 36 | # load model 37 | if FLAGS.framework == 'tflite': 38 | interpreter = tf.lite.Interpreter(model_path=FLAGS.weights) 39 | else: 40 | saved_model_loaded = tf.saved_model.load(FLAGS.weights, tags=[tag_constants.SERVING]) 41 | 42 | # loop through images in list and run Yolov4 model on each 43 | for count, image_path in enumerate(images, 1): 44 | original_image = cv2.imread(image_path) 45 | original_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB) 46 | 47 | image_data = cv2.resize(original_image, (input_size, input_size)) 48 | image_data = image_data / 255. 49 | 50 | images_data = [] 51 | for i in range(1): 52 | images_data.append(image_data) 53 | images_data = np.asarray(images_data).astype(np.float32) 54 | 55 | if FLAGS.framework == 'tflite': 56 | interpreter.allocate_tensors() 57 | input_details = interpreter.get_input_details() 58 | output_details = interpreter.get_output_details() 59 | print(input_details) 60 | print(output_details) 61 | interpreter.set_tensor(input_details[0]['index'], images_data) 62 | interpreter.invoke() 63 | pred = [interpreter.get_tensor(output_details[i]['index']) for i in range(len(output_details))] 64 | if FLAGS.model == 'yolov3' and FLAGS.tiny == True: 65 | boxes, pred_conf = filter_boxes(pred[1], pred[0], score_threshold=0.25, input_shape=tf.constant([input_size, input_size])) 66 | else: 67 | boxes, pred_conf = filter_boxes(pred[0], pred[1], score_threshold=0.25, input_shape=tf.constant([input_size, input_size])) 68 | else: 69 | infer = saved_model_loaded.signatures['serving_default'] 70 | batch_data = tf.constant(images_data) 71 | pred_bbox = infer(batch_data) 72 | for key, value in pred_bbox.items(): 73 | boxes = value[:, :, 0:4] 74 | pred_conf = value[:, :, 4:] 75 | 76 | boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression( 77 | boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)), 78 | scores=tf.reshape( 79 | pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])), 80 | max_output_size_per_class=50, 81 | max_total_size=50, 82 | iou_threshold=FLAGS.iou, 83 | score_threshold=FLAGS.score 84 | ) 85 | pred_bbox = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()] 86 | image = utils.draw_bbox(original_image, pred_bbox) 87 | # image = utils.draw_bbox(image_data*255, pred_bbox) 88 | image = Image.fromarray(image.astype(np.uint8)) 89 | if not FLAGS.dont_show: 90 | image.show() 91 | image = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB) 92 | cv2.imwrite(FLAGS.output + 'detection' + str(count) + '.png', image) 93 | 94 | if __name__ == '__main__': 95 | try: 96 | app.run(main) 97 | except SystemExit: 98 | pass 99 | -------------------------------------------------------------------------------- /detect_flask.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import argparse 3 | import time 4 | import cv2 5 | import os 6 | from flask import Flask, request, Response, jsonify 7 | import jsonpickle 8 | #import binascii 9 | import io as StringIO 10 | import base64 11 | from io import BytesIO 12 | import io 13 | import json 14 | from PIL import Image 15 | 16 | # construct the argument parse and parse the arguments 17 | 18 | confthres = 0.3 19 | nmsthres = 0.1 20 | yolo_path = './' 21 | 22 | 23 | def get_labels(labels_path): 24 | # load the COCO class labels our YOLO model was trained on 25 | #labelsPath = os.path.sep.join([yolo_path, "yolo_v3/coco.names"]) 26 | lpath = os.path.sep.join([yolo_path, labels_path]) 27 | LABELS = open(lpath).read().strip().split("\n") 28 | return LABELS 29 | 30 | 31 | def get_colors(LABELS): 32 | # initialize a list of colors to represent each possible class label 33 | np.random.seed(42) 34 | COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8") 35 | return COLORS 36 | 37 | 38 | def get_weights(weights_path): 39 | # derive the paths to the YOLO weights and model configuration 40 | weightsPath = os.path.sep.join([yolo_path, weights_path]) 41 | return weightsPath 42 | 43 | 44 | def get_config(config_path): 45 | configPath = os.path.sep.join([yolo_path, config_path]) 46 | return configPath 47 | 48 | 49 | def load_model(configpath, weightspath): 50 | # load our YOLO object detector trained on COCO dataset (80 classes) 51 | print("[INFO] loading YOLO from disk...") 52 | net = cv2.dnn.readNetFromDarknet(configpath, weightspath) 53 | return net 54 | 55 | 56 | def image_to_byte_array(image: Image): 57 | imgByteArr = io.BytesIO() 58 | image.save(imgByteArr, format='PNG') 59 | imgByteArr = imgByteArr.getvalue() 60 | return imgByteArr 61 | 62 | 63 | def get_prediction(image, net, LABELS, COLORS): 64 | (H, W) = image.shape[:2] 65 | 66 | # determine only the *output* layer names that we need from YOLO 67 | ln = net.getLayerNames() 68 | ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()] 69 | 70 | # construct a blob from the input image and then perform a forward 71 | # pass of the YOLO object detector, giving us our bounding boxes and 72 | # associated probabilities 73 | blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), 74 | swapRB=True, crop=False) 75 | net.setInput(blob) 76 | start = time.time() 77 | layerOutputs = net.forward(ln) 78 | print(layerOutputs) 79 | end = time.time() 80 | 81 | # show timing information on YOLO 82 | print("[INFO] YOLO took {:.6f} seconds".format(end - start)) 83 | 84 | # initialize our lists of detected bounding boxes, confidences, and 85 | # class IDs, respectively 86 | boxes = [] 87 | confidences = [] 88 | classIDs = [] 89 | print('******************',layerOutputs) 90 | # loop over each of the layer outputs 91 | for output in layerOutputs: 92 | # loop over each of the detections 93 | for detection in output: 94 | # extract the class ID and confidence (i.e., probability) of 95 | # the current object detection 96 | scores = detection[5:] 97 | # print(scores) 98 | classID = np.argmax(scores) 99 | # print(classID) 100 | confidence = scores[classID] 101 | 102 | # filter out weak predictions by ensuring the detected 103 | # probability is greater than the minimum probability 104 | if confidence > confthres: 105 | # scale the bounding box coordinates back relative to the 106 | # size of the image, keeping in mind that YOLO actually 107 | # returns the center (x, y)-coordinates of the bounding 108 | # box followed by the boxes' width and height 109 | box = detection[0:4] * np.array([W, H, W, H]) 110 | (centerX, centerY, width, height) = box.astype("int") 111 | 112 | # use the center (x, y)-coordinates to derive the top and 113 | # and left corner of the bounding box 114 | x = int(centerX - (width / 2)) 115 | y = int(centerY - (height / 2)) 116 | 117 | # update our list of bounding box coordinates, confidences, 118 | # and class IDs 119 | boxes.append([x, y, int(width), int(height)]) 120 | confidences.append(float(confidence)) 121 | classIDs.append(classID) 122 | 123 | # apply non-maxima suppression to suppress weak, overlapping bounding 124 | # boxes 125 | idxs = cv2.dnn.NMSBoxes(boxes, confidences, confthres, 126 | nmsthres) 127 | print(len(COLORS)) 128 | # ensure at least one detection exists 129 | if len(idxs) > 0: 130 | # loop over the indexes we are keeping 131 | for i in idxs.flatten(): 132 | # extract the bounding box coordinates 133 | (x, y) = (boxes[i][0], boxes[i][1]) 134 | (w, h) = (boxes[i][2], boxes[i][3]) 135 | 136 | # draw a bounding box rectangle and label on the image 137 | color = [int(c) for c in COLORS[classIDs[i]]] 138 | cv2.rectangle(image, (x, y), (x + w, y + h), color, 2) 139 | text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i]) 140 | print(boxes) 141 | print(classIDs) 142 | cv2.putText(image, text, (x, y - 5), 143 | cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) 144 | return image 145 | 146 | 147 | labelsPath = "data/classes/coco.names" 148 | cfgpath = "data/yolov4.cfg" 149 | wpath = "data/yolov4.weights" 150 | Lables = get_labels(labelsPath) 151 | CFG = get_config(cfgpath) 152 | Weights = get_weights(wpath) 153 | nets = load_model(CFG, Weights) 154 | Colors = get_colors(Lables) 155 | app = Flask(__name__) 156 | 157 | @app.route('/api/test', methods=['POST']) 158 | def main(): 159 | img = request.files["image"].read() 160 | img = Image.open(io.BytesIO(img)) 161 | npimg = np.array(img) 162 | image = npimg.copy() 163 | image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 164 | res = get_prediction(image, nets, Lables, Colors) 165 | # image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB) 166 | # show the output image 167 | #cv2.imshow("Image", res) 168 | # cv2.waitKey() 169 | image = cv2.cvtColor(res, cv2.COLOR_BGR2RGB) 170 | np_img = Image.fromarray(image) 171 | img_encoded = image_to_byte_array(np_img) 172 | return Response(response=img_encoded, status=200, mimetype="image/jpeg") 173 | 174 | # start flask app 175 | if __name__ == '__main__': 176 | app.run(debug=True, host='0.0.0.0') 177 | -------------------------------------------------------------------------------- /detect_object.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | physical_devices = tf.config.experimental.list_physical_devices('GPU') 3 | if len(physical_devices) > 0: 4 | tf.config.experimental.set_memory_growth(physical_devices[0], True) 5 | from absl import app, flags, logging 6 | from absl.flags import FLAGS 7 | import core.utils as utils 8 | from core.yolov4 import filter_boxes 9 | from tensorflow.python.saved_model import tag_constants 10 | from PIL import Image 11 | import cv2 12 | import numpy as np 13 | from shutil import copyfile 14 | import shutil 15 | import os, glob 16 | from tensorflow.compat.v1 import ConfigProto 17 | from tensorflow.compat.v1 import InteractiveSession 18 | 19 | 20 | framework="tf" #tf, tflite, trt 21 | model="yolov4" #yolov3 or yolov4 22 | tiny=True #yolo or yolo-tiny 23 | iou=0.45 #iou threshold 24 | score=0.25 #score threshold 25 | output='./detections/' #path to output folder 26 | 27 | #def main(): 28 | def glass_detector(image_name): 29 | image_size=416 30 | imput_image=image_name 31 | config = ConfigProto() 32 | config.gpu_options.allow_growth = True 33 | session = InteractiveSession(config=config) 34 | STRIDES, ANCHORS, NUM_CLASS, XYSCALE = utils.load_config(FLAGS) 35 | input_size = image_size 36 | images = [imput_image] 37 | 38 | # load model 39 | weights_loaded="./checkpoints/yolo-tiny-416" 40 | if framework == 'tflite': 41 | interpreter = tf.lite.Interpreter(model_path=weights_loaded) 42 | else: 43 | saved_model_loaded = tf.saved_model.load(weights_loaded, tags=[tag_constants.SERVING]) 44 | 45 | # loop through images in list and run Yolov4 model on each 46 | for count, image_path in enumerate(images, 1): 47 | original_image = cv2.imread(image_path) 48 | original_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB) 49 | 50 | image_data = cv2.resize(original_image, (input_size, input_size)) 51 | image_data = image_data / 255. 52 | 53 | images_data = [] 54 | for i in range(1): 55 | images_data.append(image_data) 56 | images_data = np.asarray(images_data).astype(np.float32) 57 | 58 | if framework == 'tflite': 59 | interpreter.allocate_tensors() 60 | input_details = interpreter.get_input_details() 61 | output_details = interpreter.get_output_details() 62 | print(input_details) 63 | print(output_details) 64 | interpreter.set_tensor(input_details[0]['index'], images_data) 65 | interpreter.invoke() 66 | pred = [interpreter.get_tensor(output_details[i]['index']) for i in range(len(output_details))] 67 | if model == 'yolov3' and tiny == True: 68 | boxes, pred_conf = filter_boxes(pred[1], pred[0], score_threshold=0.25, input_shape=tf.constant([input_size, input_size])) 69 | else: 70 | boxes, pred_conf = filter_boxes(pred[0], pred[1], score_threshold=0.25, input_shape=tf.constant([input_size, input_size])) 71 | else: 72 | infer = saved_model_loaded.signatures['serving_default'] 73 | batch_data = tf.constant(images_data) 74 | pred_bbox = infer(batch_data) 75 | for key, value in pred_bbox.items(): 76 | boxes = value[:, :, 0:4] 77 | pred_conf = value[:, :, 4:] 78 | 79 | boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression( 80 | boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)), 81 | scores=tf.reshape( 82 | pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])), 83 | max_output_size_per_class=50, 84 | max_total_size=50, 85 | iou_threshold=iou, 86 | score_threshold=score 87 | ) 88 | pred_bbox = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()] 89 | #image = utils.draw_bbox(original_image, pred_bbox) 90 | cropped_image = utils.draw_bbox(original_image, pred_bbox) 91 | # image = utils.draw_bbox(image_data*255, pred_bbox) 92 | image = Image.fromarray(cropped_image.astype(np.uint8)) 93 | #if not FLAGS.dont_show: 94 | #image.show() 95 | image = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB) 96 | 97 | cv2.imwrite(output + 'DetectedGlass' + str(count) + '.jpg', image) 98 | return image -------------------------------------------------------------------------------- /detect_video.py: -------------------------------------------------------------------------------- 1 | import time 2 | import tensorflow as tf 3 | physical_devices = tf.config.experimental.list_physical_devices('GPU') 4 | if len(physical_devices) > 0: 5 | tf.config.experimental.set_memory_growth(physical_devices[0], True) 6 | from absl import app, flags, logging 7 | from absl.flags import FLAGS 8 | import core.utils as utils 9 | from core.yolov4 import filter_boxes 10 | from tensorflow.python.saved_model import tag_constants 11 | from PIL import Image 12 | import cv2 13 | import numpy as np 14 | from tensorflow.compat.v1 import ConfigProto 15 | from tensorflow.compat.v1 import InteractiveSession 16 | 17 | flags.DEFINE_string('framework', 'tf', '(tf, tflite, trt') 18 | flags.DEFINE_string('weights', './checkpoints/yolov4-416', 19 | 'path to weights file') 20 | flags.DEFINE_integer('size', 416, 'resize images to') 21 | flags.DEFINE_boolean('tiny', False, 'yolo or yolo-tiny') 22 | flags.DEFINE_string('model', 'yolov4', 'yolov3 or yolov4') 23 | flags.DEFINE_string('video', './data/video/video.mp4', 'path to input video or set to 0 for webcam') 24 | flags.DEFINE_string('output', None, 'path to output video') 25 | flags.DEFINE_string('output_format', 'XVID', 'codec used in VideoWriter when saving video to file') 26 | flags.DEFINE_float('iou', 0.45, 'iou threshold') 27 | flags.DEFINE_float('score', 0.25, 'score threshold') 28 | flags.DEFINE_boolean('dont_show', False, 'dont show video output') 29 | 30 | def main(_argv): 31 | config = ConfigProto() 32 | config.gpu_options.allow_growth = True 33 | session = InteractiveSession(config=config) 34 | STRIDES, ANCHORS, NUM_CLASS, XYSCALE = utils.load_config(FLAGS) 35 | input_size = FLAGS.size 36 | video_path = FLAGS.video 37 | 38 | if FLAGS.framework == 'tflite': 39 | interpreter = tf.lite.Interpreter(model_path=FLAGS.weights) 40 | interpreter.allocate_tensors() 41 | input_details = interpreter.get_input_details() 42 | output_details = interpreter.get_output_details() 43 | print(input_details) 44 | print(output_details) 45 | else: 46 | saved_model_loaded = tf.saved_model.load(FLAGS.weights, tags=[tag_constants.SERVING]) 47 | infer = saved_model_loaded.signatures['serving_default'] 48 | 49 | # begin video capture 50 | try: 51 | vid = cv2.VideoCapture(int(video_path)) 52 | except: 53 | vid = cv2.VideoCapture(video_path) 54 | 55 | out = None 56 | 57 | if FLAGS.output: 58 | # by default VideoCapture returns float instead of int 59 | width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)) 60 | height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)) 61 | fps = int(vid.get(cv2.CAP_PROP_FPS)) 62 | codec = cv2.VideoWriter_fourcc(*FLAGS.output_format) 63 | out = cv2.VideoWriter(FLAGS.output, codec, fps, (width, height)) 64 | 65 | while True: 66 | return_value, frame = vid.read() 67 | if return_value: 68 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 69 | image = Image.fromarray(frame) 70 | else: 71 | print('Video has ended or failed, try a different video format!') 72 | break 73 | 74 | frame_size = frame.shape[:2] 75 | image_data = cv2.resize(frame, (input_size, input_size)) 76 | image_data = image_data / 255. 77 | image_data = image_data[np.newaxis, ...].astype(np.float32) 78 | start_time = time.time() 79 | 80 | if FLAGS.framework == 'tflite': 81 | interpreter.set_tensor(input_details[0]['index'], image_data) 82 | interpreter.invoke() 83 | pred = [interpreter.get_tensor(output_details[i]['index']) for i in range(len(output_details))] 84 | if FLAGS.model == 'yolov3' and FLAGS.tiny == True: 85 | boxes, pred_conf = filter_boxes(pred[1], pred[0], score_threshold=0.25, 86 | input_shape=tf.constant([input_size, input_size])) 87 | else: 88 | boxes, pred_conf = filter_boxes(pred[0], pred[1], score_threshold=0.25, 89 | input_shape=tf.constant([input_size, input_size])) 90 | else: 91 | batch_data = tf.constant(image_data) 92 | pred_bbox = infer(batch_data) 93 | for key, value in pred_bbox.items(): 94 | boxes = value[:, :, 0:4] 95 | pred_conf = value[:, :, 4:] 96 | 97 | boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression( 98 | boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)), 99 | scores=tf.reshape( 100 | pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])), 101 | max_output_size_per_class=50, 102 | max_total_size=50, 103 | iou_threshold=FLAGS.iou, 104 | score_threshold=FLAGS.score 105 | ) 106 | pred_bbox = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()] 107 | image = utils.draw_bbox(frame, pred_bbox) 108 | fps = 1.0 / (time.time() - start_time) 109 | print("FPS: %.2f" % fps) 110 | result = np.asarray(image) 111 | cv2.namedWindow("result", cv2.WINDOW_AUTOSIZE) 112 | result = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) 113 | 114 | if not FLAGS.dont_show: 115 | cv2.imshow("result", result) 116 | 117 | if FLAGS.output: 118 | out.write(result) 119 | if cv2.waitKey(1) & 0xFF == ord('q'): break 120 | cv2.destroyAllWindows() 121 | 122 | if __name__ == '__main__': 123 | try: 124 | app.run(main) 125 | except SystemExit: 126 | pass 127 | -------------------------------------------------------------------------------- /evaluate.py: -------------------------------------------------------------------------------- 1 | from absl import app, flags, logging 2 | from absl.flags import FLAGS 3 | import cv2 4 | import os 5 | import shutil 6 | import numpy as np 7 | import tensorflow as tf 8 | from core.yolov4 import filter_boxes 9 | from tensorflow.python.saved_model import tag_constants 10 | import core.utils as utils 11 | from core.config import cfg 12 | 13 | flags.DEFINE_string('weights', './checkpoints/yolov4-416', 14 | 'path to weights file') 15 | flags.DEFINE_string('framework', 'tf', 'select model type in (tf, tflite, trt)' 16 | 'path to weights file') 17 | flags.DEFINE_string('model', 'yolov4', 'yolov3 or yolov4') 18 | flags.DEFINE_boolean('tiny', False, 'yolov3 or yolov3-tiny') 19 | flags.DEFINE_integer('size', 416, 'resize images to') 20 | flags.DEFINE_string('annotation_path', "./data/dataset/val2017.txt", 'annotation path') 21 | flags.DEFINE_string('write_image_path', "./data/detection/", 'write image path') 22 | flags.DEFINE_float('iou', 0.5, 'iou threshold') 23 | flags.DEFINE_float('score', 0.25, 'score threshold') 24 | 25 | def main(_argv): 26 | INPUT_SIZE = FLAGS.size 27 | STRIDES, ANCHORS, NUM_CLASS, XYSCALE = utils.load_config(FLAGS) 28 | CLASSES = utils.read_class_names(cfg.YOLO.CLASSES) 29 | 30 | predicted_dir_path = './mAP/predicted' 31 | ground_truth_dir_path = './mAP/ground-truth' 32 | if os.path.exists(predicted_dir_path): shutil.rmtree(predicted_dir_path) 33 | if os.path.exists(ground_truth_dir_path): shutil.rmtree(ground_truth_dir_path) 34 | if os.path.exists(cfg.TEST.DECTECTED_IMAGE_PATH): shutil.rmtree(cfg.TEST.DECTECTED_IMAGE_PATH) 35 | 36 | os.mkdir(predicted_dir_path) 37 | os.mkdir(ground_truth_dir_path) 38 | os.mkdir(cfg.TEST.DECTECTED_IMAGE_PATH) 39 | 40 | # Build Model 41 | if FLAGS.framework == 'tflite': 42 | interpreter = tf.lite.Interpreter(model_path=FLAGS.weights) 43 | interpreter.allocate_tensors() 44 | input_details = interpreter.get_input_details() 45 | output_details = interpreter.get_output_details() 46 | print(input_details) 47 | print(output_details) 48 | else: 49 | saved_model_loaded = tf.saved_model.load(FLAGS.weights, tags=[tag_constants.SERVING]) 50 | infer = saved_model_loaded.signatures['serving_default'] 51 | 52 | num_lines = sum(1 for line in open(FLAGS.annotation_path)) 53 | with open(cfg.TEST.ANNOT_PATH, 'r') as annotation_file: 54 | for num, line in enumerate(annotation_file): 55 | annotation = line.strip().split() 56 | image_path = annotation[0] 57 | image_name = image_path.split('/')[-1] 58 | image = cv2.imread(image_path) 59 | image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 60 | bbox_data_gt = np.array([list(map(int, box.split(','))) for box in annotation[1:]]) 61 | 62 | if len(bbox_data_gt) == 0: 63 | bboxes_gt = [] 64 | classes_gt = [] 65 | else: 66 | bboxes_gt, classes_gt = bbox_data_gt[:, :4], bbox_data_gt[:, 4] 67 | ground_truth_path = os.path.join(ground_truth_dir_path, str(num) + '.txt') 68 | 69 | print('=> ground truth of %s:' % image_name) 70 | num_bbox_gt = len(bboxes_gt) 71 | with open(ground_truth_path, 'w') as f: 72 | for i in range(num_bbox_gt): 73 | class_name = CLASSES[classes_gt[i]] 74 | xmin, ymin, xmax, ymax = list(map(str, bboxes_gt[i])) 75 | bbox_mess = ' '.join([class_name, xmin, ymin, xmax, ymax]) + '\n' 76 | f.write(bbox_mess) 77 | print('\t' + str(bbox_mess).strip()) 78 | print('=> predict result of %s:' % image_name) 79 | predict_result_path = os.path.join(predicted_dir_path, str(num) + '.txt') 80 | # Predict Process 81 | image_size = image.shape[:2] 82 | # image_data = utils.image_preprocess(np.copy(image), [INPUT_SIZE, INPUT_SIZE]) 83 | image_data = cv2.resize(np.copy(image), (INPUT_SIZE, INPUT_SIZE)) 84 | image_data = image_data / 255. 85 | image_data = image_data[np.newaxis, ...].astype(np.float32) 86 | 87 | if FLAGS.framework == 'tflite': 88 | interpreter.set_tensor(input_details[0]['index'], image_data) 89 | interpreter.invoke() 90 | pred = [interpreter.get_tensor(output_details[i]['index']) for i in range(len(output_details))] 91 | if FLAGS.model == 'yolov4' and FLAGS.tiny == True: 92 | boxes, pred_conf = filter_boxes(pred[1], pred[0], score_threshold=0.25) 93 | else: 94 | boxes, pred_conf = filter_boxes(pred[0], pred[1], score_threshold=0.25) 95 | else: 96 | batch_data = tf.constant(image_data) 97 | pred_bbox = infer(batch_data) 98 | for key, value in pred_bbox.items(): 99 | boxes = value[:, :, 0:4] 100 | pred_conf = value[:, :, 4:] 101 | 102 | boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression( 103 | boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)), 104 | scores=tf.reshape( 105 | pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])), 106 | max_output_size_per_class=50, 107 | max_total_size=50, 108 | iou_threshold=FLAGS.iou, 109 | score_threshold=FLAGS.score 110 | ) 111 | boxes, scores, classes, valid_detections = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()] 112 | 113 | # if cfg.TEST.DECTECTED_IMAGE_PATH is not None: 114 | # image_result = utils.draw_bbox(np.copy(image), [boxes, scores, classes, valid_detections]) 115 | # cv2.imwrite(cfg.TEST.DECTECTED_IMAGE_PATH + image_name, image_result) 116 | 117 | with open(predict_result_path, 'w') as f: 118 | image_h, image_w, _ = image.shape 119 | for i in range(valid_detections[0]): 120 | if int(classes[0][i]) < 0 or int(classes[0][i]) > NUM_CLASS: continue 121 | coor = boxes[0][i] 122 | coor[0] = int(coor[0] * image_h) 123 | coor[2] = int(coor[2] * image_h) 124 | coor[1] = int(coor[1] * image_w) 125 | coor[3] = int(coor[3] * image_w) 126 | 127 | score = scores[0][i] 128 | class_ind = int(classes[0][i]) 129 | class_name = CLASSES[class_ind] 130 | score = '%.4f' % score 131 | ymin, xmin, ymax, xmax = list(map(str, coor)) 132 | bbox_mess = ' '.join([class_name, score, xmin, ymin, xmax, ymax]) + '\n' 133 | f.write(bbox_mess) 134 | print('\t' + str(bbox_mess).strip()) 135 | print(num, num_lines) 136 | 137 | if __name__ == '__main__': 138 | try: 139 | app.run(main) 140 | except SystemExit: 141 | pass 142 | 143 | 144 | -------------------------------------------------------------------------------- /mAP/extra/intersect-gt-and-pred.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import glob 4 | 5 | ## This script ensures same number of files in ground-truth and predicted folder. 6 | ## When you encounter file not found error, it's usually because you have 7 | ## mismatched numbers of ground-truth and predicted files. 8 | ## You can use this script to move ground-truth and predicted files that are 9 | ## not in the intersection into a backup folder (backup_no_matches_found). 10 | ## This will retain only files that have the same name in both folders. 11 | 12 | # change directory to the one with the files to be changed 13 | path_to_gt = '../ground-truth' 14 | path_to_pred = '../predicted' 15 | backup_folder = 'backup_no_matches_found' # must end without slash 16 | 17 | os.chdir(path_to_gt) 18 | gt_files = glob.glob('*.txt') 19 | if len(gt_files) == 0: 20 | print("Error: no .txt files found in", path_to_gt) 21 | sys.exit() 22 | os.chdir(path_to_pred) 23 | pred_files = glob.glob('*.txt') 24 | if len(pred_files) == 0: 25 | print("Error: no .txt files found in", path_to_pred) 26 | sys.exit() 27 | 28 | gt_files = set(gt_files) 29 | pred_files = set(pred_files) 30 | print('total ground-truth files:', len(gt_files)) 31 | print('total predicted files:', len(pred_files)) 32 | print() 33 | 34 | gt_backup = gt_files - pred_files 35 | pred_backup = pred_files - gt_files 36 | 37 | 38 | def backup(src_folder, backup_files, backup_folder): 39 | # non-intersection files (txt format) will be moved to a backup folder 40 | if not backup_files: 41 | print('No backup required for', src_folder) 42 | return 43 | os.chdir(src_folder) 44 | ## create the backup dir if it doesn't exist already 45 | if not os.path.exists(backup_folder): 46 | os.makedirs(backup_folder) 47 | for file in backup_files: 48 | os.rename(file, backup_folder + '/' + file) 49 | 50 | 51 | backup(path_to_gt, gt_backup, backup_folder) 52 | backup(path_to_pred, pred_backup, backup_folder) 53 | if gt_backup: 54 | print('total ground-truth backup files:', len(gt_backup)) 55 | if pred_backup: 56 | print('total predicted backup files:', len(pred_backup)) 57 | 58 | intersection = gt_files & pred_files 59 | print('total intersected files:', len(intersection)) 60 | print("Intersection completed!") -------------------------------------------------------------------------------- /mAP/extra/remove_space.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import glob 4 | import argparse 5 | 6 | # this script will load class_list.txt and find class names with spaces 7 | # then replace spaces with delimiters inside ground-truth/ and predicted/ 8 | 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument('-d', '--delimiter', type=str, help="delimiter to replace space (default: '-')", default='-') 11 | parser.add_argument('-y', '--yes', action='store_true', help="force yes confirmation on yes/no query (default: False)", default=False) 12 | args = parser.parse_args() 13 | 14 | def query_yes_no(question, default="yes", bypass=False): 15 | """Ask a yes/no question via raw_input() and return their answer. 16 | 17 | "question" is a string that is presented to the user. 18 | "default" is the presumed answer if the user just hitsAdd instructions here
7 | 8 | {% endblock %} -------------------------------------------------------------------------------- /templates/data_done.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} {% block content %} 2 |Speed Detection completed successfully.
9 | Download .csv 10 | {% endif %} 11 | 33 | 39 |Data Extraction completed successfully.
9 | Download .csv 10 | {% endif %} 11 | 33 | 39 |Data Extraction completed successfully.
31 | Download .csv 32 | {% endif %} 33 | 34 | 35 |