Update app.py
Browse files
app.py
CHANGED
@@ -1,157 +1,11 @@
|
|
1 |
-
import onnxruntime
|
2 |
-
import numpy as np
|
3 |
-
import cv2
|
4 |
-
import os
|
5 |
import gradio as gr
|
6 |
-
|
7 |
-
|
8 |
-
img_size = 640
|
9 |
-
|
10 |
-
class Object:
|
11 |
-
def __init__(self, rect: Tuple[int, int, int, int], label: int, prob: float):
|
12 |
-
self.rect = rect
|
13 |
-
self.label = label
|
14 |
-
self.prob = prob
|
15 |
-
|
16 |
-
def sigmoid(x):
|
17 |
-
return 1/(1+np.exp(-x))
|
18 |
-
|
19 |
-
def intersection_area(a: Object, b: Object) -> float:
|
20 |
-
x = max(a.rect[0], b.rect[0])
|
21 |
-
y = max(a.rect[1], b.rect[1])
|
22 |
-
w = min(a.rect[0] + a.rect[2], b.rect[0] + b.rect[2]) - x
|
23 |
-
h = min(a.rect[1] + a.rect[3], b.rect[1] + b.rect[3]) - y
|
24 |
-
if w < 0 or h < 0:
|
25 |
-
return 0
|
26 |
-
return w * h
|
27 |
-
|
28 |
-
def nms_sorted_bboxes(faceobjects: List[Object], nms_threshold: float) -> List[int]:
|
29 |
-
picked = []
|
30 |
-
n = len(faceobjects)
|
31 |
-
areas = [faceobjects[i].rect[2]*faceobjects[i].rect[3] for i in range(n)]
|
32 |
-
for i in range(n):
|
33 |
-
a = faceobjects[i]
|
34 |
-
keep = 1
|
35 |
-
for j in range(len(picked)):
|
36 |
-
b = faceobjects[picked[j]]
|
37 |
-
inter_area = intersection_area(a, b)
|
38 |
-
union_area = areas[i] + areas[picked[j]] - inter_area
|
39 |
-
if inter_area / union_area > nms_threshold:
|
40 |
-
keep = 0
|
41 |
-
if keep:
|
42 |
-
picked.append(i)
|
43 |
-
return picked
|
44 |
-
|
45 |
-
def generate_proposals(stride, feat, prob_threshold, letterbox_cols, letterbox_rows):
|
46 |
-
anchors = [10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90, 156, 198, 373, 326]
|
47 |
-
anchor_num = 3
|
48 |
-
feat_w = letterbox_cols // stride
|
49 |
-
feat_h = letterbox_rows // stride
|
50 |
-
cls_num = 45
|
51 |
-
anchor_group = 0
|
52 |
-
if stride == 8:
|
53 |
-
anchor_group = 1
|
54 |
-
if stride == 16:
|
55 |
-
anchor_group = 2
|
56 |
-
if stride == 32:
|
57 |
-
anchor_group = 3
|
58 |
-
objects = []
|
59 |
-
for h in range(feat_h):
|
60 |
-
for w in range(feat_w):
|
61 |
-
for a in range(anchor_num):
|
62 |
-
class_index = 0
|
63 |
-
class_score = float('-inf')
|
64 |
-
for s in range(cls_num):
|
65 |
-
score = feat[a * feat_w * feat_h * (cls_num + 5) + h * feat_w * (cls_num + 5) + w * (cls_num + 5) + s + 5]
|
66 |
-
# if score > class_score:
|
67 |
-
if np.max(score) > class_score:
|
68 |
-
class_index = s
|
69 |
-
class_score = np.max(score)
|
70 |
-
box_score = feat[a * feat_w * feat_h * (cls_num + 5) + (h * feat_w) * (cls_num + 5) + w * (cls_num + 5) + 4]
|
71 |
-
final_score = sigmoid(box_score) * sigmoid(class_score)
|
72 |
-
if final_score >= prob_threshold:
|
73 |
-
loc_idx = a * feat_h * feat_w * (cls_num + 5) + h * feat_w * (cls_num + 5) + w * (cls_num + 5)
|
74 |
-
dx = sigmoid(feat[loc_idx + 0])
|
75 |
-
dy = sigmoid(feat[loc_idx + 1])
|
76 |
-
dw = sigmoid(feat[loc_idx + 2])
|
77 |
-
dh = sigmoid(feat[loc_idx + 3])
|
78 |
-
pred_cx = (dx * 2.0 - 0.5 + w) * stride
|
79 |
-
pred_cy = (dy * 2.0 - 0.5 + h) * stride
|
80 |
-
anchor_w = anchors[(anchor_group - 1) * 6 + a * 2 + 0]
|
81 |
-
anchor_h = anchors[(anchor_group - 1) * 6 + a * 2 + 1]
|
82 |
-
pred_w = dw * dw * 4.0 * anchor_w
|
83 |
-
pred_h = dh * dh * 4.0 * anchor_h
|
84 |
-
x0 = pred_cx - pred_w * 0.5
|
85 |
-
y0 = pred_cy - pred_h * 0.5
|
86 |
-
x1 = pred_cx + pred_w * 0.5
|
87 |
-
y1 = pred_cy + pred_h * 0.5
|
88 |
-
obj = Object((x0, y0, x1 - x0, y1 - y0), class_index, final_score)
|
89 |
-
objects.append(obj)
|
90 |
-
return objects
|
91 |
-
|
92 |
-
def draw_objects(bgr, objects):
|
93 |
-
class_names = ["pl80", "p6", "p5", "pm55", "pl60", "ip", "p11", "i2r", "p23", "pg",
|
94 |
-
"il80", "ph4", "i4", "pl70", "pne", "ph4.5", "p12", "p3", "pl5", "w13",
|
95 |
-
"i4l", "pl30", "p10", "pn", "w55", "p26", "p13", "pr40", "pl20", "pm30",
|
96 |
-
"pl40", "i2", "pl120", "w32", "ph5", "il60", "w57", "pl100",
|
97 |
-
"w59", "il100", "p19", "pm20", "i5", "p27", "pl50"]
|
98 |
-
image = bgr.copy()
|
99 |
-
for i, obj in enumerate(objects):
|
100 |
-
print(f"{obj.label}: {obj.prob*100}%, {[obj.rect[0], obj.rect[1], obj.rect[0]+obj.rect[2], obj.rect[1]+obj.rect[3]]}, {class_names[obj.label]}")
|
101 |
-
cv2.rectangle(image, (int(obj.rect[0]), int(obj.rect[1])), (int(obj.rect[0]+obj.rect[2]), int(obj.rect[1]+obj.rect[3])), (255, 0, 0), 2)
|
102 |
-
label = f"{class_names[obj.label]} {obj.prob*100:.1f}%"
|
103 |
-
label_size, base_line = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
|
104 |
-
cv2.rectangle(image, (int(obj.rect[0]), int(obj.rect[1]-label_size[1])), (int(obj.rect[0])+label_size[0], int(obj.rect[1]+base_line)), (255, 255, 255), cv2.FILLED)
|
105 |
-
cv2.putText(image, label, (int(obj.rect[0]), int(obj.rect[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
|
106 |
-
return image
|
107 |
-
|
108 |
-
def preprocess(image_file: str, img_size: int = 640):
|
109 |
-
img = cv2.imread(image_file)
|
110 |
-
h, w, _ = img.shape
|
111 |
-
r = img_size / max(h, w)
|
112 |
-
nh, nw = int(r * h), int(r * w)
|
113 |
-
img = cv2.resize(img, (nw, nh))
|
114 |
-
img = cv2.copyMakeBorder(img, (img_size - nh) // 2, (img_size - nh) // 2,
|
115 |
-
(img_size - nw) // 2, (img_size - nw) // 2,
|
116 |
-
cv2.BORDER_CONSTANT, value=(114, 114, 114))
|
117 |
-
img = img.astype(np.float32) / 255.0
|
118 |
-
img = np.transpose(img, [2, 0, 1])
|
119 |
-
img = np.expand_dims(img, axis=0)
|
120 |
-
return img
|
121 |
-
|
122 |
-
def infer_main(image_file: str):
|
123 |
-
model_file = "./jtbz_best.onnx"
|
124 |
-
|
125 |
-
# load model
|
126 |
-
sess = onnxruntime.InferenceSession(model_file)
|
127 |
-
input_name = sess.get_inputs()[0].name
|
128 |
-
|
129 |
-
# preprocess
|
130 |
-
img = preprocess(image_file)
|
131 |
-
|
132 |
-
# inference
|
133 |
-
outputs = sess.run(None, {input_name: img})
|
134 |
-
|
135 |
-
# postprocess
|
136 |
-
prob_threshold = 0.27
|
137 |
-
nms_threshold = 0.45
|
138 |
-
proposals = []
|
139 |
-
for stride, feat in zip([8, 16, 32], outputs[:3]):
|
140 |
-
proposals.extend(generate_proposals(stride, feat[0], prob_threshold, img_size, img_size))
|
141 |
-
proposals.sort(key=lambda x: x.prob, reverse=True)
|
142 |
-
picked = nms_sorted_bboxes(proposals, nms_threshold)
|
143 |
-
|
144 |
-
# draw result
|
145 |
-
img = cv2.imread(image_file)
|
146 |
-
objects = [proposals[i] for i in picked]
|
147 |
-
result = draw_objects(img, objects)
|
148 |
|
149 |
-
|
|
|
|
|
|
|
150 |
|
151 |
-
|
152 |
-
iface
|
153 |
-
inputs=gr.components.Image(type="filepath"),
|
154 |
-
outputs=gr.components.Image(),
|
155 |
-
title="YOLOv5 Object Detection and classification",
|
156 |
-
description="Upload an image to see the detected objects and their classification.")
|
157 |
-
iface.launch()
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
import subprocess
|
3 |
+
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
def run_yolov5s(image):
|
6 |
+
image.save("input.jpg")
|
7 |
+
result = subprocess.run(["./yolov5s-tt100k", "-m", "./yolov5s_tt100k_opt_fp32.tmfile", "-i", "input.jpg"], capture_output=True, text=True)
|
8 |
+
return "yolov5s-tt100k.out.jpg", result.stdout
|
9 |
|
10 |
+
iface = gr.Interface(fn=run_yolov5s, inputs=gr.Image(), outputs=[gr.Image(type="filepath"), gr.Textbox()])
|
11 |
+
iface.launch()
|
|
|
|
|
|
|
|
|
|