Spaces:
Runtime error
Runtime error
Charalambos Georgiades
commited on
Commit
•
98ab999
1
Parent(s):
97672ff
Added files
Browse files- detector.py +113 -0
- packages.txt +2 -0
- requirements.txt +5 -0
detector.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
from pathlib import Path
|
4 |
+
|
5 |
+
|
6 |
+
class Detector():
|
7 |
+
def __init__(self, weights="yolov4-tiny.weights", config_file = "tiny-yolov4.cfg",
|
8 |
+
classes_file=Path(__file__).parent / 'cfg' / 'coco.names', conf_thresh=0.25, nms_thresh=0.4,
|
9 |
+
netsize=[416, 416]):
|
10 |
+
|
11 |
+
""" Detector class that implements yolo detector
|
12 |
+
Parameters
|
13 |
+
----------
|
14 |
+
weights : string
|
15 |
+
path to the weights file, eg. yolov4-tiny.weights
|
16 |
+
config_file : string
|
17 |
+
path to the configs file, eg. tiny-yolov4.cfg
|
18 |
+
classes_file : string
|
19 |
+
path to the classes file, eg. coco.names
|
20 |
+
conf_thresh : float
|
21 |
+
confidence threshold for the detection
|
22 |
+
nms_thresh : float
|
23 |
+
non maxima supression threshold for the detections
|
24 |
+
netsize : tuple
|
25 |
+
netwrork's config size eg. [416,416]
|
26 |
+
"""
|
27 |
+
self.weights = weights
|
28 |
+
self.config = config_file
|
29 |
+
self.classes_file = classes_file
|
30 |
+
# initialize the network
|
31 |
+
self.net = cv2.dnn.readNet(self.weights, self.config)
|
32 |
+
# self.net = cv2.dnn.readNetFromDarknet(self.config, self.weights)
|
33 |
+
# set the backend
|
34 |
+
self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
|
35 |
+
self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
|
36 |
+
|
37 |
+
ln = self.net.getLayerNames()
|
38 |
+
# an error checking due to OPENCV versions changes
|
39 |
+
try:
|
40 |
+
self.vers = 0
|
41 |
+
self.layers = [ln[i[0] - 1] for i in self.net.getUnconnectedOutLayers()]
|
42 |
+
except:
|
43 |
+
self.vers = 1
|
44 |
+
self.layers = [ln[i - 1] for i in self.net.getUnconnectedOutLayers()]
|
45 |
+
|
46 |
+
self.netsize = netsize
|
47 |
+
self.conf_thresh = conf_thresh
|
48 |
+
self.nms_thresh = nms_thresh
|
49 |
+
with open(self.classes_file, 'r') as f:
|
50 |
+
classes = [line.strip() for line in f.readlines()]
|
51 |
+
self.labels = np.array(classes, dtype=str)
|
52 |
+
self.model = cv2.dnn_DetectionModel(self.net)
|
53 |
+
self.model.setInputParams(size=(self.netsize[0], self.netsize[1]), scale=1 / 256)
|
54 |
+
self.COLORS = np.random.randint(0, 255, size=(len(self.labels), 3))
|
55 |
+
|
56 |
+
def detect(self, img_or):
|
57 |
+
|
58 |
+
# copy the original image
|
59 |
+
img = img_or.copy()
|
60 |
+
# do some pre-processing (eg. resizing)
|
61 |
+
image = self._preprocess(img)
|
62 |
+
try:
|
63 |
+
# detect the image
|
64 |
+
classes, scores, boxes = self.model.detect(image, self.conf_thresh,
|
65 |
+
self.nms_thresh)
|
66 |
+
except Exception as e:
|
67 |
+
print("[ERROR ]" + e)
|
68 |
+
if len(boxes)==0:
|
69 |
+
return img, [], [], []
|
70 |
+
|
71 |
+
# de-normalize the results
|
72 |
+
fixboxes = self.de_normalize(boxes,self.netsize, self.imgsize)
|
73 |
+
boxes = np.array(fixboxes,dtype=np.int32)
|
74 |
+
# draw the detections on the image
|
75 |
+
image_det = self.postprocess(classes, scores, boxes, img)
|
76 |
+
|
77 |
+
return image_det, classes, scores, boxes
|
78 |
+
|
79 |
+
def _preprocess(self, frame):
|
80 |
+
self.imgsize = [frame.shape[1], frame.shape[0]]
|
81 |
+
img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
82 |
+
return cv2.resize(img, (self.netsize[0], self.netsize[1]), interpolation=cv2.INTER_LINEAR)
|
83 |
+
|
84 |
+
def de_normalize(self, boxes,netsize,imgsize):
|
85 |
+
finBoxes = []
|
86 |
+
for i in range(len(boxes)):
|
87 |
+
box = boxes[i]
|
88 |
+
x,y,w,h= int((box[0] / netsize[0]) * imgsize[0]),int((box[1] / netsize[1]) * imgsize[1]),\
|
89 |
+
int((box[2] / netsize[0]) * imgsize[0]), int((box[3] / netsize[1]) * imgsize[1])
|
90 |
+
finBoxes.append((x,y,w,h))
|
91 |
+
return finBoxes
|
92 |
+
|
93 |
+
# drawing bounding boxes and their label on the detections
|
94 |
+
def postprocess(self, classes, scores, boxes, img):
|
95 |
+
for i in range(len(boxes)):
|
96 |
+
box = boxes[i]
|
97 |
+
if scores[i] > self.conf_thresh:
|
98 |
+
x,y,w,h = box
|
99 |
+
if self.vers == 1:
|
100 |
+
class_id = classes[i]
|
101 |
+
score = scores[i]
|
102 |
+
color = [int(c) for c in self.COLORS[class_id]]
|
103 |
+
else:
|
104 |
+
class_id = classes[i][0]
|
105 |
+
score = scores[i][0]
|
106 |
+
color = self.COLORS[class_id]
|
107 |
+
color = (int(color[0]), int(color[1]), int(color[2]))
|
108 |
+
cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
|
109 |
+
text = "{}: {:.4f}".format(self.labels[class_id], score)
|
110 |
+
cv2.putText(img, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,
|
111 |
+
0.5, color, 2)
|
112 |
+
return img
|
113 |
+
|
packages.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
python3-opencv
|
2 |
+
ffmpeg
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
opencv-python
|
2 |
+
ffmpeg-python
|
3 |
+
numpy
|
4 |
+
pandas
|
5 |
+
matplotlib
|