Zengyf-CVer commited on
Commit
c9aac43
1 Parent(s): e2b482e

app update

Browse files
.gitignore ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 图片格式
2
+ *.jpg
3
+ *.jpeg
4
+ *.png
5
+ *.svg
6
+ *.gif
7
+
8
+ # 视频格式
9
+ *.mp4
10
+ *.avi
11
+ .ipynb_checkpoints
12
+ */__pycache__
13
+
14
+ # 日志格式
15
+ *.log
16
+ *.datas
17
+ *.txt
18
+
19
+ # 生成文件
20
+ *.pdf
21
+ *.xlsx
22
+ *.csv
23
+
24
+ # 参数文件
25
+ *.yaml
26
+ *.json
27
+
28
+ # 压缩文件格式
29
+ *.zip
30
+ *.tar
31
+ *.tar.gz
32
+ *.rar
33
+
34
+ # 字体格式
35
+ *.ttc
36
+ *.ttf
37
+ *.otf
38
+
39
+ # 模型文件
40
+ *.pt
41
+ *.db
42
+
43
+ test.py
44
+ test*.py
45
+
46
+ /flagged
47
+ /run
48
+ !requirements.txt
49
+ !cls_name/*
50
+ !model_config/*
51
+ !img_example/*
52
+ !packages.txt
53
+
54
+ app copy.py
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Gradio YOLOv5 Det V5
3
- emoji: 💻
4
  colorFrom: red
5
- colorTo: pink
6
  sdk: gradio
7
  sdk_version: 3.1.1
8
  app_file: app.py
 
1
  ---
2
  title: Gradio YOLOv5 Det V5
3
+ emoji: 🚀
4
  colorFrom: red
5
+ colorTo: red
6
  sdk: gradio
7
  sdk_version: 3.1.1
8
  app_file: app.py
__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __author__ = "曾逸夫(Zeng Yifu)"
2
+ __email__ = "[email protected]"
app.py ADDED
@@ -0,0 +1,834 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gradio YOLOv5 Det v0.5
2
+ # author: Zeng Yifu(曾逸夫)
3
+ # creation time: 2022-07-22
4
+ # email: [email protected]
5
+ # project homepage: https://gitee.com/CV_Lab/gradio_yolov5_det
6
+
7
+ import os
8
+ import argparse
9
+ import csv
10
+ import sys
11
+
12
+ csv.field_size_limit(sys.maxsize)
13
+
14
+ import gc
15
+ import json
16
+ from collections import Counter
17
+ from pathlib import Path
18
+
19
+ import cv2
20
+ import gradio as gr
21
+ import matplotlib.pyplot as plt
22
+ import numpy as np
23
+ import pandas as pd
24
+ import plotly.express as px
25
+ from matplotlib import font_manager
26
+ from matplotlib.ticker import MaxNLocator
27
+
28
+ ROOT_PATH = sys.path[0] # 项目根目录
29
+
30
+ # --------------------- 字体库 ---------------------
31
+ SimSun_path = f"{ROOT_PATH}/fonts/SimSun.ttf" # 宋体文件路径
32
+ TimesNesRoman_path = f"{ROOT_PATH}/fonts/TimesNewRoman.ttf" # 新罗马字体文件路径
33
+ # 宋体
34
+ SimSun = font_manager.FontProperties(fname=SimSun_path, size=12)
35
+ # 新罗马字体
36
+ TimesNesRoman = font_manager.FontProperties(fname=TimesNesRoman_path, size=12)
37
+
38
+ import torch
39
+ import yaml
40
+ from PIL import Image, ImageDraw, ImageFont
41
+
42
+ from util.fonts_opt import is_fonts
43
+ from util.pdf_opt import pdf_generate
44
+
45
+ ROOT_PATH = sys.path[0] # 根目录
46
+
47
+ # yolov5路径
48
+ yolov5_path = "ultralytics/yolov5"
49
+
50
+ # 本地模型路径
51
+ local_model_path = f"{ROOT_PATH}/models"
52
+
53
+ # Gradio YOLOv5 Det版本
54
+ GYD_VERSION = "Gradio YOLOv5 Det v0.5"
55
+
56
+ # 模型名称临时变量
57
+ model_name_tmp = ""
58
+
59
+ # 设备临时变量
60
+ device_tmp = ""
61
+
62
+ # 文件后缀
63
+ suffix_list = [".csv", ".yaml"]
64
+
65
+ # 字体大小
66
+ FONTSIZE = 25
67
+
68
+ # 目标尺寸
69
+ obj_style = ["小目标", "中目标", "大目标"]
70
+
71
+
72
+ def parse_args(known=False):
73
+ parser = argparse.ArgumentParser(description="Gradio YOLOv5 Det v0.5")
74
+ parser.add_argument("--source", "-src", default="upload", type=str, help="image input source")
75
+ parser.add_argument("--source_video", "-src_v", default="upload", type=str, help="video input source")
76
+ parser.add_argument("--img_tool", "-it", default="editor", type=str, help="input image tool")
77
+ parser.add_argument("--model_name", "-mn", default="yolov5s", type=str, help="model name")
78
+ parser.add_argument(
79
+ "--model_cfg",
80
+ "-mc",
81
+ default="./model_config/model_name_p5_p6_all.yaml",
82
+ type=str,
83
+ help="model config",
84
+ )
85
+ parser.add_argument(
86
+ "--cls_name",
87
+ "-cls",
88
+ default="./cls_name/cls_name_zh.yaml",
89
+ type=str,
90
+ help="cls name",
91
+ )
92
+ parser.add_argument(
93
+ "--nms_conf",
94
+ "-conf",
95
+ default=0.5,
96
+ type=float,
97
+ help="model NMS confidence threshold",
98
+ )
99
+ parser.add_argument("--nms_iou", "-iou", default=0.45, type=float, help="model NMS IoU threshold")
100
+ parser.add_argument(
101
+ "--device",
102
+ "-dev",
103
+ default="cuda:0",
104
+ type=str,
105
+ help="cuda or cpu",
106
+ )
107
+ parser.add_argument("--inference_size", "-isz", default=640, type=int, help="model inference size")
108
+ parser.add_argument("--max_detnum", "-mdn", default=50, type=float, help="model max det num")
109
+ parser.add_argument("--slider_step", "-ss", default=0.05, type=float, help="slider step")
110
+ parser.add_argument(
111
+ "--is_login",
112
+ "-isl",
113
+ action="store_true",
114
+ default=False,
115
+ help="is login",
116
+ )
117
+ parser.add_argument('--usr_pwd',
118
+ "-up",
119
+ nargs='+',
120
+ type=str,
121
+ default=["admin", "admin"],
122
+ help="user & password for login")
123
+ parser.add_argument(
124
+ "--is_share",
125
+ "-is",
126
+ action="store_true",
127
+ default=False,
128
+ help="is login",
129
+ )
130
+
131
+ args = parser.parse_known_args()[0] if known else parser.parse_args()
132
+ return args
133
+
134
+
135
+ # yaml文件解析
136
+ def yaml_parse(file_path):
137
+ return yaml.safe_load(open(file_path, encoding="utf-8").read())
138
+
139
+
140
+ # yaml csv 文件解析
141
+ def yaml_csv(file_path, file_tag):
142
+ file_suffix = Path(file_path).suffix
143
+ if file_suffix == suffix_list[0]:
144
+ # 模型名称
145
+ file_names = [i[0] for i in list(csv.reader(open(file_path)))] # csv版
146
+ elif file_suffix == suffix_list[1]:
147
+ # 模型名称
148
+ file_names = yaml_parse(file_path).get(file_tag) # yaml版
149
+ else:
150
+ print(f"{file_path}格式不正确!程序退出!")
151
+ sys.exit()
152
+
153
+ return file_names
154
+
155
+
156
+ # 模型加载
157
+ def model_loading(model_name, device, opt=[]):
158
+
159
+ # 加载本地模型
160
+ try:
161
+ torch.hub._validate_not_a_forked_repo = lambda a, b, c: True
162
+ model = torch.hub.load(
163
+ yolov5_path,
164
+ "custom",
165
+ path=f"{local_model_path}/{model_name}",
166
+ device=device,
167
+ force_reload=[True if "refresh_yolov5" in opt else False][0],
168
+ _verbose=True,
169
+ )
170
+ except Exception as e:
171
+ print("模型加载失败!")
172
+ print(e)
173
+ return False
174
+ else:
175
+ print(f"🚀 欢��使用{GYD_VERSION},{model_name}加载成功!")
176
+
177
+ return model
178
+
179
+
180
+ # 检测信息
181
+ def export_json(results, img_size):
182
+
183
+ return [[{
184
+ "ID": i,
185
+ "CLASS": int(result[i][5]),
186
+ "CLASS_NAME": model_cls_name_cp[int(result[i][5])],
187
+ "BOUNDING_BOX": {
188
+ "XMIN": round(result[i][:4].tolist()[0], 6),
189
+ "YMIN": round(result[i][:4].tolist()[1], 6),
190
+ "XMAX": round(result[i][:4].tolist()[2], 6),
191
+ "YMAX": round(result[i][:4].tolist()[3], 6),},
192
+ "CONF": round(float(result[i][4]), 2),
193
+ "FPS": round(1000 / float(results.t[1]), 2),
194
+ "IMG_WIDTH": img_size[0],
195
+ "IMG_HEIGHT": img_size[1],} for i in range(len(result))] for result in results.xyxyn]
196
+
197
+
198
+ # 标签和边界框颜色设置
199
+ def color_set(cls_num):
200
+ color_list = []
201
+ for i in range(cls_num):
202
+ color = tuple(np.random.choice(range(256), size=3))
203
+ # color = ["#"+''.join([random.choice('0123456789ABCDEF') for j in range(6)])]
204
+ color_list.append(color)
205
+
206
+ return color_list
207
+
208
+
209
+ # 检测绘制
210
+ def pil_draw(img, score_l, bbox_l, cls_l, cls_index_l, textFont, color_list, opt):
211
+
212
+ img_pil = ImageDraw.Draw(img)
213
+ id = 0
214
+
215
+ for score, (xmin, ymin, xmax, ymax), label, cls_index in zip(score_l, bbox_l, cls_l, cls_index_l):
216
+
217
+ img_pil.rectangle([xmin, ymin, xmax, ymax], fill=None, outline=color_list[cls_index], width=2) # 边界框
218
+ countdown_msg = f"{id}-{label} {score:.2f}"
219
+ text_w, text_h = textFont.getsize(countdown_msg) # 标签尺寸
220
+ if "label" in opt:
221
+ # 标签背景
222
+ img_pil.rectangle(
223
+ (xmin, ymin, xmin + text_w, ymin + text_h),
224
+ fill=color_list[cls_index],
225
+ outline=color_list[cls_index],
226
+ )
227
+
228
+ # 标签
229
+ img_pil.multiline_text(
230
+ (xmin, ymin),
231
+ countdown_msg,
232
+ fill=(255, 255, 255),
233
+ font=textFont,
234
+ align="center",
235
+ )
236
+
237
+ id += 1
238
+
239
+ return img
240
+
241
+
242
+ # YOLOv5图片检测函数
243
+ def yolo_det_img(img, device, model_name, infer_size, conf, iou, max_num, model_cls, opt):
244
+
245
+ global model, model_name_tmp, device_tmp
246
+
247
+ if img is None or img == "":
248
+ # 判断是否有图片存在
249
+ print("图片不存在!")
250
+ return None, None, None, None, None, None, None
251
+
252
+ det_img = img.copy()
253
+ # 目标尺寸个数
254
+ s_obj, m_obj, l_obj = 0, 0, 0
255
+
256
+ area_obj_all = [] # 目标面积
257
+
258
+ score_det_stat = [] # 置信度统计
259
+ bbox_det_stat = [] # 边界框统计
260
+ cls_det_stat = [] # 类别数量统计
261
+ cls_index_det_stat = [] # 类别索引统计
262
+
263
+ pdf_csv_xlsx = [] # 文件生成列表
264
+
265
+ if model_name_tmp != model_name:
266
+ # 模型判断,避免反复加载
267
+ model_name_tmp = model_name
268
+ print(f"正在加载模型{model_name_tmp}......")
269
+ model = model_loading(model_name_tmp, device, opt)
270
+ elif device_tmp != device:
271
+ # 设备判断,避免反复加载
272
+ device_tmp = device
273
+ print(f"正在加载模型{model_name_tmp}......")
274
+ model = model_loading(model_name_tmp, device, opt)
275
+ else:
276
+ print(f"正在加载模型{model_name_tmp}......")
277
+ model = model_loading(model_name_tmp, device, opt)
278
+
279
+ # ----------- 模型调参 -----------
280
+ model.conf = conf # NMS 置信度阈值
281
+ model.iou = iou # NMS IoU阈值
282
+ model.max_det = int(max_num) # 最大检测框数
283
+ model.classes = model_cls # 模型类别
284
+
285
+ color_list = color_set(len(model_cls_name_cp)) # 设置颜色
286
+
287
+ img_size = img.size # 帧尺寸
288
+
289
+ results = model(img, size=infer_size) # 检测
290
+ # 判断检测对象是否为空
291
+ # 参考:https://gitee.com/CV_Lab/face-labeling/blob/master/face_labeling.py
292
+ is_results_null = results.xyxyn[0].shape == torch.Size([0, 6])
293
+
294
+ if not is_results_null:
295
+
296
+ # ---------------- 目标裁剪 ----------------
297
+ crops = results.crop(save=False)
298
+ img_crops = []
299
+ for i in range(len(crops)):
300
+ img_crops.append(crops[i]["im"][..., ::-1])
301
+
302
+ # 数据表
303
+ dataframe = results.pandas().xyxy[0].round(2)
304
+
305
+ report = "./Det_Report.pdf"
306
+ det_csv = "./Det_Report.csv"
307
+ det_excel = "./Det_Report.xlsx"
308
+
309
+ if "csv" in opt:
310
+ dataframe.to_csv(det_csv, index=False)
311
+ pdf_csv_xlsx.append(det_csv)
312
+ else:
313
+ det_csv = None
314
+
315
+ if "excel" in opt:
316
+ dataframe.to_excel(det_excel, sheet_name='sheet1', index=False)
317
+ pdf_csv_xlsx.append(det_excel)
318
+ else:
319
+ det_excel = None
320
+
321
+ # ---------------- 加载字体 ----------------
322
+ yaml_index = cls_name.index(".yaml")
323
+ cls_name_lang = cls_name[yaml_index - 2:yaml_index]
324
+
325
+ if cls_name_lang == "zh":
326
+ # 中文
327
+ textFont = ImageFont.truetype(str(f"{ROOT_PATH}/fonts/SimSun.ttf"), size=FONTSIZE)
328
+ elif cls_name_lang in ["en", "ru", "es", "ar"]:
329
+ # 英文、俄语、西班牙语、阿拉伯语
330
+ textFont = ImageFont.truetype(str(f"{ROOT_PATH}/fonts/TimesNewRoman.ttf"), size=FONTSIZE)
331
+ elif cls_name_lang == "ko":
332
+ # 韩语
333
+ textFont = ImageFont.truetype(str(f"{ROOT_PATH}/fonts/malgun.ttf"), size=FONTSIZE)
334
+
335
+ for result in results.xyxyn:
336
+ for i in range(len(result)):
337
+ # id = int(i) # 实例ID
338
+ obj_cls_index = int(result[i][5]) # 类别索引
339
+ cls_index_det_stat.append(obj_cls_index)
340
+
341
+ obj_cls = model_cls_name_cp[obj_cls_index] # 类别
342
+ cls_det_stat.append(obj_cls)
343
+
344
+ # ------------ 边框坐标 ------------
345
+ x0 = float(result[i][:4].tolist()[0])
346
+ y0 = float(result[i][:4].tolist()[1])
347
+ x1 = float(result[i][:4].tolist()[2])
348
+ y1 = float(result[i][:4].tolist()[3])
349
+
350
+ # ------------ 边框实际坐标 ------------
351
+ x0 = int(img_size[0] * x0)
352
+ y0 = int(img_size[1] * y0)
353
+ x1 = int(img_size[0] * x1)
354
+ y1 = int(img_size[1] * y1)
355
+ bbox_det_stat.append((x0, y0, x1, y1))
356
+
357
+ conf = float(result[i][4]) # 置信度
358
+ score_det_stat.append(conf)
359
+
360
+ # fps = f"{(1000 / float(results.t[1])):.2f}" # FPS
361
+
362
+ # ---------- 加入目标尺寸 ----------
363
+ w_obj = x1 - x0
364
+ h_obj = y1 - y0
365
+ area_obj = w_obj * h_obj
366
+ area_obj_all.append(area_obj)
367
+
368
+ det_img = pil_draw(img, score_det_stat, bbox_det_stat, cls_det_stat, cls_index_det_stat, textFont, color_list,
369
+ opt)
370
+ # ------------ JSON生成 ------------
371
+ det_json = export_json(results, img.size)[0] # 检测信息
372
+ det_json_format = json.dumps(det_json, sort_keys=False, indent=4, separators=(",", ":"),
373
+ ensure_ascii=False) # JSON格式化
374
+ if "json" not in opt:
375
+ det_json = None
376
+
377
+ # -------------- PDF生成 --------------
378
+ if "pdf" in opt:
379
+ pdf_generate(f"{det_json_format}", report, GYD_VERSION)
380
+ pdf_csv_xlsx.append(report)
381
+ else:
382
+ report = None
383
+
384
+ # -------------- 目标尺寸计算 --------------
385
+ for i in range(len(area_obj_all)):
386
+ if (0 < area_obj_all[i] <= 32 ** 2):
387
+ s_obj = s_obj + 1
388
+ elif (32 ** 2 < area_obj_all[i] <= 96 ** 2):
389
+ m_obj = m_obj + 1
390
+ elif (area_obj_all[i] > 96 ** 2):
391
+ l_obj = l_obj + 1
392
+
393
+ sml_obj_total = s_obj + m_obj + l_obj
394
+ objSize_dict = {}
395
+ objSize_dict = {obj_style[i]: [s_obj, m_obj, l_obj][i] / sml_obj_total for i in range(3)}
396
+
397
+ # ------------ 类别统计 ------------
398
+ clsRatio_dict = {}
399
+ clsDet_dict = Counter(cls_det_stat)
400
+ clsDet_dict_sum = sum(clsDet_dict.values())
401
+ for k, v in clsDet_dict.items():
402
+ clsRatio_dict[k] = v / clsDet_dict_sum
403
+
404
+ return det_img, img_crops, objSize_dict, clsRatio_dict, dataframe, det_json, pdf_csv_xlsx
405
+ else:
406
+ print("图片目标不存在!")
407
+ return None, None, None, None, None, None, None
408
+
409
+
410
+ # YOLOv5视频检测函数
411
+ def yolo_det_video(video, device, model_name, infer_size, conf, iou, max_num, model_cls, opt, draw_style):
412
+
413
+ global model, model_name_tmp, device_tmp
414
+
415
+ if video is None or video == "":
416
+ # 判断是否有图片存在
417
+ print("视频不存在!")
418
+ return None, None, None
419
+
420
+ # 目标尺寸个数
421
+ s_obj, m_obj, l_obj = 0, 0, 0
422
+
423
+ area_obj_all = [] # 目标面积
424
+ s_list, m_list, l_list = [], [], []
425
+
426
+ score_det_stat = [] # 置信度统计
427
+ bbox_det_stat = [] # 边界框统计
428
+ cls_det_stat = [] # 类别数量统计
429
+ cls_index_det_stat = [] # 类别索引统计
430
+
431
+ fps_list = []
432
+
433
+ frame_count = 0 # 帧数
434
+ fps = 0 # FPS
435
+
436
+ os.system("""
437
+ if [ -e './output.mp4' ]; then
438
+ rm ./output.mp4
439
+ fi
440
+ """)
441
+
442
+ if model_name_tmp != model_name:
443
+ # 模型判断,避免反复加载
444
+ model_name_tmp = model_name
445
+ print(f"正在加载模型{model_name_tmp}......")
446
+ model = model_loading(model_name_tmp, device, opt)
447
+ elif device_tmp != device:
448
+ # 设备判断,避免反复加载
449
+ device_tmp = device
450
+ print(f"正在加载模型{model_name_tmp}......")
451
+ model = model_loading(model_name_tmp, device, opt)
452
+ else:
453
+ print(f"正在加载模型{model_name_tmp}......")
454
+ model = model_loading(model_name_tmp, device, opt)
455
+
456
+ # ----------- 模型调参 -----------
457
+ model.conf = conf # NMS 置信度阈值
458
+ model.iou = iou # NMS IOU阈值
459
+ model.max_det = int(max_num) # 最大检测框数
460
+ model.classes = model_cls # 模型类别
461
+
462
+ color_list = color_set(len(model_cls_name_cp)) # 设置颜色
463
+
464
+ # ---------------- 加载字体 ----------------
465
+ yaml_index = cls_name.index(".yaml")
466
+ cls_name_lang = cls_name[yaml_index - 2:yaml_index]
467
+
468
+ if cls_name_lang == "zh":
469
+ # 中文
470
+ textFont = ImageFont.truetype(str(f"{ROOT_PATH}/fonts/SimSun.ttf"), size=FONTSIZE)
471
+ elif cls_name_lang in ["en", "ru", "es", "ar"]:
472
+ # 英文、俄语、西班牙语、阿拉伯语
473
+ textFont = ImageFont.truetype(str(f"{ROOT_PATH}/fonts/TimesNewRoman.ttf"), size=FONTSIZE)
474
+ elif cls_name_lang == "ko":
475
+ # 韩语
476
+ textFont = ImageFont.truetype(str(f"{ROOT_PATH}/fonts/malgun.ttf"), size=FONTSIZE)
477
+
478
+ # video->frame
479
+ gc.collect()
480
+ output_video_path = "./output.avi"
481
+ cap = cv2.VideoCapture(video)
482
+ fourcc = cv2.VideoWriter_fourcc(*"I420") # 编码器
483
+
484
+ out = cv2.VideoWriter(output_video_path, fourcc, 30.0, (int(cap.get(3)), int(cap.get(4))))
485
+ if cap.isOpened():
486
+ while cap.isOpened():
487
+ ret, frame = cap.read()
488
+ # 判断空帧
489
+ if not ret:
490
+ break
491
+
492
+ frame_count += 1 # 帧数自增
493
+
494
+ results = model(frame, size=infer_size) # 检测
495
+
496
+ h, w, _ = frame.shape # 帧尺寸
497
+ img_size = (w, h) # 帧尺寸
498
+
499
+ for result in results.xyxyn:
500
+ for i in range(len(result)):
501
+ # id = int(i) # 实例ID
502
+ obj_cls_index = int(result[i][5]) # 类别索引
503
+ cls_index_det_stat.append(obj_cls_index)
504
+
505
+ obj_cls = model_cls_name_cp[obj_cls_index] # 类别
506
+ cls_det_stat.append(obj_cls)
507
+
508
+ # ------------边框坐标------------
509
+ x0 = float(result[i][:4].tolist()[0])
510
+ y0 = float(result[i][:4].tolist()[1])
511
+ x1 = float(result[i][:4].tolist()[2])
512
+ y1 = float(result[i][:4].tolist()[3])
513
+
514
+ # ------------边框实际坐标------------
515
+ x0 = int(img_size[0] * x0)
516
+ y0 = int(img_size[1] * y0)
517
+ x1 = int(img_size[0] * x1)
518
+ y1 = int(img_size[1] * y1)
519
+ bbox_det_stat.append((x0, y0, x1, y1))
520
+
521
+ conf = float(result[i][4]) # 置信度
522
+ score_det_stat.append(conf)
523
+
524
+ fps = f"{(1000 / float(results.t[1])):.2f}" # FPS
525
+
526
+ # ---------- 加入目标尺寸 ----------
527
+ w_obj = x1 - x0
528
+ h_obj = y1 - y0
529
+ area_obj = w_obj * h_obj
530
+ area_obj_all.append(area_obj)
531
+
532
+ # 判断检测对象是否为空
533
+ # 参考:https://gitee.com/CV_Lab/face-labeling/blob/master/face_labeling.py
534
+ is_results_null = results.xyxyn[0].shape == torch.Size([0, 6])
535
+ if not is_results_null:
536
+ fps_list.append(float(fps))
537
+ else:
538
+ fps_list.append(0.0)
539
+
540
+ frame = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
541
+ frame = pil_draw(frame, score_det_stat, bbox_det_stat, cls_det_stat, cls_index_det_stat, textFont,
542
+ color_list, opt)
543
+ frame = cv2.cvtColor(np.asarray(frame), cv2.COLOR_RGB2BGR)
544
+
545
+ # frame->video
546
+ out.write(frame)
547
+
548
+ # ----- 清空统计列表 -----
549
+ score_det_stat = []
550
+ bbox_det_stat = []
551
+ cls_det_stat = []
552
+ cls_index_det_stat = []
553
+
554
+ # -------------- 目标尺寸计算 --------------
555
+ for i in range(len(area_obj_all)):
556
+ if (0 < area_obj_all[i] <= 32 ** 2):
557
+ s_obj = s_obj + 1
558
+ elif (32 ** 2 < area_obj_all[i] <= 96 ** 2):
559
+ m_obj = m_obj + 1
560
+ elif (area_obj_all[i] > 96 ** 2):
561
+ l_obj = l_obj + 1
562
+
563
+ s_list.append(s_obj)
564
+ m_list.append(m_obj)
565
+ l_list.append(l_obj)
566
+
567
+ # 目标尺寸个数
568
+ s_obj, m_obj, l_obj = 0, 0, 0
569
+ # 目标面积
570
+ area_obj_all = []
571
+
572
+ out.release()
573
+ cap.release()
574
+ # cv2.destroyAllWindows()
575
+
576
+ df_objSize = pd.DataFrame({"fID": list(range(frame_count))})
577
+ df_objSize[obj_style[0]] = tuple(s_list)
578
+ df_objSize[obj_style[1]] = tuple(m_list)
579
+ df_objSize[obj_style[2]] = tuple(l_list)
580
+ print(df_objSize)
581
+
582
+ if draw_style == "Plotly":
583
+ # -------------------- 帧数-目标尺寸数图 --------------------
584
+ fig_objSize = px.scatter(df_objSize, x="fID", y=obj_style) # 散点图
585
+ # fig_objSize = px.line(df_objSize, x="fID", y=obj_style, markers=True) # 折线图
586
+ fig_objSize.update_layout(title="帧数-目标尺寸数", xaxis_title="帧数", yaxis_title="目标尺寸数")
587
+
588
+ # -------------------- 帧数-FPS图 --------------------
589
+ fig_fps = px.scatter(df_objSize, x="fID", y=fps_list)
590
+ # fig_fps = px.line(df_objSize, x="fID", y=fps_list, markers=True)
591
+ fig_fps.update_layout(title="帧数-FPS", xaxis_title="帧数", yaxis_title="FPS")
592
+
593
+ elif draw_style == "Matplotlib":
594
+ # -------------------- 帧数-目标尺寸数图 --------------------
595
+ fig_objSize = plt.figure()
596
+
597
+ # -------------------- 散点图 --------------------
598
+ plt.scatter(df_objSize['fID'], df_objSize[obj_style[0]])
599
+ plt.scatter(df_objSize['fID'], df_objSize[obj_style[1]])
600
+ plt.scatter(df_objSize['fID'], df_objSize[obj_style[2]])
601
+ # plt.plot(df_objSize['fID'], df_objSize[obj_style]) # 折线图
602
+ plt.title("帧数-目标尺寸数图", fontsize=12, fontproperties=SimSun)
603
+ plt.xlabel("帧数", fontsize=12, fontproperties=SimSun)
604
+ plt.ylabel("目标尺寸数", fontsize=12, fontproperties=SimSun)
605
+ plt.legend(obj_style, prop=SimSun, fontsize=12, loc="best")
606
+
607
+ # -------------------- 帧数-FPS图 --------------------
608
+ fig_fps = plt.figure()
609
+
610
+ plt.scatter(df_objSize['fID'], fps_list)
611
+ # plt.plot(df_objSize['fID'], df_objSize[obj_style]) # 折线图
612
+ plt.title("帧数-FPS", fontsize=12, fontproperties=SimSun)
613
+ plt.xlabel("帧数", fontsize=12, fontproperties=SimSun)
614
+ plt.ylabel("FPS", fontsize=12, fontproperties=SimSun)
615
+
616
+ return output_video_path, fig_objSize, fig_fps
617
+
618
+ else:
619
+ print("视频加载失败!")
620
+ return None, None, None
621
+
622
+
623
+ def main(args):
624
+ gr.close_all()
625
+
626
+ global model, model_cls_name_cp, cls_name
627
+
628
+ source = args.source
629
+ source_video = args.source_video
630
+ img_tool = args.img_tool
631
+ nms_conf = args.nms_conf
632
+ nms_iou = args.nms_iou
633
+ model_name = args.model_name
634
+ model_cfg = args.model_cfg
635
+ cls_name = args.cls_name
636
+ device = args.device
637
+ inference_size = args.inference_size
638
+ max_detnum = args.max_detnum
639
+ slider_step = args.slider_step
640
+ is_login = args.is_login
641
+ usr_pwd = args.usr_pwd
642
+ is_share = args.is_share
643
+
644
+ is_fonts(f"{ROOT_PATH}/fonts") # 检查字体文件
645
+
646
+ # 模型加载
647
+ model = model_loading(model_name, device)
648
+
649
+ model_names = yaml_csv(model_cfg, "model_names") # 模型名称
650
+ model_cls_name = yaml_csv(cls_name, "model_cls_name") # 类别名称
651
+
652
+ model_cls_name_cp = model_cls_name.copy() # 类别名称
653
+
654
+ # ------------------- 图片模式输入组件 -------------------
655
+ inputs_img = gr.Image(image_mode="RGB", source=source, tool=img_tool, type="pil", label="原始图片")
656
+ inputs_device01 = gr.Radio(choices=["cuda:0", "cpu"], value=device, label="设备")
657
+ inputs_model01 = gr.Dropdown(choices=model_names, value=model_name, type="value", label="模型")
658
+ inputs_size01 = gr.Slider(384, 1536, step=128, value=inference_size, label="推理尺寸")
659
+ input_conf01 = gr.Slider(0, 1, step=slider_step, value=nms_conf, label="置信度阈值")
660
+ inputs_iou01 = gr.Slider(0, 1, step=slider_step, value=nms_iou, label="IoU 阈值")
661
+ inputs_maxnum01 = gr.Number(value=max_detnum, label="最大检测数")
662
+ inputs_clsName01 = gr.CheckboxGroup(choices=model_cls_name, value=model_cls_name, type="index", label="类别")
663
+ inputs_opt01 = gr.CheckboxGroup(choices=["refresh_yolov5", "label", "pdf", "json", "csv", "excel"],
664
+ value=["label", "pdf"],
665
+ type="value",
666
+ label="操作")
667
+
668
+ # ------------------- 视频模式输入组件 -------------------
669
+ inputs_video = gr.Video(format="mp4", source=source_video, mirror_webcam=False, label="原始视频") # webcam
670
+ inputs_device02 = gr.Radio(choices=["cuda:0", "cpu"], value=device, label="设备")
671
+ inputs_model02 = gr.Dropdown(choices=model_names, value=model_name, type="value", label="模型")
672
+ inputs_size02 = gr.Slider(384, 1536, step=128, value=inference_size, label="推理尺寸")
673
+ input_conf02 = gr.Slider(0, 1, step=slider_step, value=nms_conf, label="置信度阈值")
674
+ inputs_iou02 = gr.Slider(0, 1, step=slider_step, value=nms_iou, label="IoU 阈值")
675
+ inputs_maxnum02 = gr.Number(value=max_detnum, label="最大检测数")
676
+ inputs_clsName02 = gr.CheckboxGroup(choices=model_cls_name, value=model_cls_name, type="index", label="类别")
677
+ inputs_opt02 = gr.CheckboxGroup(choices=["refresh_yolov5", "label"], value=["label"], type="value", label="操作")
678
+ inputs_draw02 = gr.Radio(choices=["Matplotlib", "Plotly"], value="Matplotlib", label="绘图")
679
+
680
+ # ------------------- 图片模式输入参数 -------------------
681
+ inputs_img_list = [
682
+ inputs_img, # 输入图片
683
+ inputs_device01, # 设备
684
+ inputs_model01, # 模型
685
+ inputs_size01, # 推理尺寸
686
+ input_conf01, # 置信度阈值
687
+ inputs_iou01, # IoU阈值
688
+ inputs_maxnum01, # 最大检测数
689
+ inputs_clsName01, # 类别
690
+ inputs_opt01, # 检测操作
691
+ ]
692
+
693
+ # ------------------- 视频模式输入参数 -------------------
694
+ inputs_video_list = [
695
+ inputs_video, # 输入图片
696
+ inputs_device02, # 设备
697
+ inputs_model02, # 模型
698
+ inputs_size02, # 推理尺寸
699
+ input_conf02, # 置信度阈值
700
+ inputs_iou02, # IoU阈值
701
+ inputs_maxnum02, # 最大检测数
702
+ inputs_clsName02, # 类别
703
+ inputs_opt02, # 检测操作
704
+ inputs_draw02, # 绘图操作
705
+ ]
706
+
707
+ # ------------------- 图片模式输出组件 -------------------
708
+ outputs_img = gr.Image(type="pil", label="检测图片")
709
+ outputs_df = gr.Dataframe(max_rows=5, overflow_row_behaviour="paginate", type="pandas", label="检测信息列表")
710
+ outputs_crops = gr.Gallery(label="目标裁剪")
711
+ outputs_objSize = gr.Label(label="目标尺寸占比统计")
712
+ outputs_clsSize = gr.Label(label="类别检测占比统计")
713
+ outputs_json = gr.JSON(label="检测信息")
714
+ outputs_pdf = gr.File(label="检测报告")
715
+
716
+ # ------------------- 视频模式输出组件 -------------------
717
+ outputs_video = gr.Video(format='mp4', label="检测视频")
718
+ outputs_frame_objSize_plot = gr.Plot(label="帧数-目标尺寸数")
719
+ outputs_frame_fps_plot = gr.Plot(label="帧数-FPS")
720
+
721
+ # ------------------- 图片模式输出参数 -------------------
722
+ outputs_img_list = [
723
+ outputs_img, outputs_crops, outputs_objSize, outputs_clsSize, outputs_df, outputs_json, outputs_pdf]
724
+
725
+ # ------------------- 视频模式输出参数 -------------------
726
+ outputs_video_list = [outputs_video, outputs_frame_objSize_plot, outputs_frame_fps_plot]
727
+
728
+ # 标题
729
+ title = "Gradio YOLOv5 Det v0.5"
730
+
731
+ # 描述
732
+ description = "<div align='center'>可自定义目标检测模型、安装简单、使用方便</div>"
733
+ # article="https://gitee.com/CV_Lab/gradio_yolov5_det"
734
+
735
+ # 示例图片
736
+ examples = [
737
+ [
738
+ "./img_examples/bus.jpg",
739
+ "cpu",
740
+ "yolov5s",
741
+ 640,
742
+ 0.6,
743
+ 0.5,
744
+ 10,
745
+ ["人", "公交车"],
746
+ ["label", "pdf"],],
747
+ [
748
+ "./img_examples/giraffe.jpg",
749
+ "cuda:0",
750
+ "yolov5l",
751
+ 320,
752
+ 0.5,
753
+ 0.45,
754
+ 12,
755
+ ["长颈鹿"],
756
+ ["label", "pdf"],],
757
+ [
758
+ "./img_examples/zidane.jpg",
759
+ "cuda:0",
760
+ "yolov5m",
761
+ 640,
762
+ 0.6,
763
+ 0.5,
764
+ 15,
765
+ ["人", "领带"],
766
+ ["pdf", "json"],],
767
+ [
768
+ "./img_examples/Millenial-at-work.jpg",
769
+ "cuda:0",
770
+ "yolov5s6",
771
+ 1280,
772
+ 0.5,
773
+ 0.5,
774
+ 20,
775
+ ["人", "椅子", "杯子", "笔记本电脑"],
776
+ ["label", "pdf", "csv", "excel"],],]
777
+
778
+ # 接口
779
+ gyd_img = gr.Interface(
780
+ fn=yolo_det_img,
781
+ inputs=inputs_img_list,
782
+ outputs=outputs_img_list,
783
+ title=title,
784
+ description=description,
785
+ # article=article,
786
+ examples=examples,
787
+ # theme="seafoam",
788
+ # live=True, # 实时变更输出
789
+ flagging_dir="run", # 输出目录
790
+ # allow_flagging="manual",
791
+ # flagging_options=["good", "generally", "bad"],
792
+ )
793
+
794
+ gyd_video = gr.Interface(
795
+ fn=yolo_det_video,
796
+ inputs=inputs_video_list,
797
+ outputs=outputs_video_list,
798
+ title=title,
799
+ description=description,
800
+ # article=article,
801
+ # examples=examples,
802
+ # theme="seafoam",
803
+ # live=True, # 实时变更输出
804
+ flagging_dir="run", # 输出目录
805
+ allow_flagging="never",
806
+ # flagging_options=["good", "generally", "bad"],
807
+ )
808
+
809
+ gyd = gr.TabbedInterface(interface_list=[gyd_img, gyd_video], tab_names=["图片模式", "视频模式"])
810
+
811
+ if not is_login:
812
+ gyd.launch(
813
+ inbrowser=True, # 自动打开默认浏览器
814
+ show_tips=True, # 自动显示gradio最新功能
815
+ share=is_share, # 项目共享,其他设备可以访问
816
+ favicon_path="./icon/logo.ico", # 网页图标
817
+ show_error=True, # 在浏览器控制台中显示错误信息
818
+ quiet=True, # 禁止大多数打印语句
819
+ )
820
+ else:
821
+ gyd.launch(
822
+ inbrowser=True, # 自动打开默认浏览器
823
+ show_tips=True, # 自动显示gradio最新功能
824
+ auth=usr_pwd, # 登录界面
825
+ share=is_share, # 项目共享,其他设备可以访问
826
+ favicon_path="./icon/logo.ico", # 网页图标
827
+ show_error=True, # 在浏览器控制台中显示错误信息
828
+ quiet=True, # 禁止大多数打印语句
829
+ )
830
+
831
+
832
+ if __name__ == "__main__":
833
+ args = parse_args()
834
+ main(args)
cls_name/cls_name.csv ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ 自行车
3
+ 汽车
4
+ 摩托车
5
+ 飞机
6
+ 公交车
7
+ 火车
8
+ 卡车
9
+
10
+ 红绿灯
11
+ 消防栓
12
+ 停止标志
13
+ 停车收费表
14
+ 长凳
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+ 斑马
24
+ 长颈鹿
25
+ 背包
26
+ 雨伞
27
+ 手提包
28
+ 领带
29
+ 手提箱
30
+ 飞盘
31
+ 滑雪板
32
+ 单板滑雪
33
+ 运动球
34
+ 风筝
35
+ 棒球棒
36
+ 棒球手套
37
+ 滑板
38
+ 冲浪板
39
+ 网球拍
40
+ 瓶子
41
+ 红酒杯
42
+ 杯子
43
+ 叉子
44
+
45
+
46
+
47
+ 香蕉
48
+ 苹果
49
+ 三明治
50
+ 橙子
51
+ 西兰花
52
+ 胡萝卜
53
+ 热狗
54
+ 比萨
55
+ 甜甜圈
56
+ 蛋糕
57
+ 椅子
58
+ 长椅
59
+ 盆栽
60
+
61
+ 餐桌
62
+ 马桶
63
+ 电视
64
+ 笔记本电脑
65
+ 鼠标
66
+ 遥控器
67
+ 键盘
68
+ 手机
69
+ 微波炉
70
+ 烤箱
71
+ 烤面包机
72
+ 洗碗槽
73
+ 冰箱
74
+
75
+ 时钟
76
+ 花瓶
77
+ 剪刀
78
+ 泰迪熊
79
+ 吹风机
80
+ 牙刷
cls_name/cls_name.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ model_cls_name: ['人', '自行车', '汽车', '摩托车', '飞机', '公交车', '火车', '卡车', '船', '红绿灯', '消防栓', '停止标志',
2
+ '停车收费表', '长凳', '鸟', '猫', '狗', '马', '羊', '牛', '象', '熊', '斑马', '长颈鹿', '背包', '雨伞', '手提包', '领带',
3
+ '手提箱', '飞盘', '滑雪板', '单板滑雪', '运动球', '风筝', '棒球棒', '棒球手套', '滑板', '冲浪板', '网球拍', '瓶子', '红酒杯',
4
+ '杯子', '叉子', '刀', '勺', '碗', '香蕉', '苹果', '三明治', '橙子', '西兰花', '胡萝卜', '热狗', '比萨', '甜甜圈', '蛋糕',
5
+ '椅子', '长椅', '盆栽', '床', '餐桌', '马桶', '电视', '笔记本电脑', '鼠标', '遥控器', '键盘', '手机', '微波炉', '烤箱',
6
+ '烤面包机', '洗碗槽', '冰箱', '书', '时钟', '花瓶', '剪刀', '泰迪熊', '吹风机', '牙刷'
7
+ ]
cls_name/cls_name_ar.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ model_cls_name: [" الناس " , " الدراجات " , " السيارات " , " الدراجات النارية " , " الطائرات " , " الحافلات " , " القطارات " , " الشاحنات " , " السفن " , " إشارات المرور " ,
2
+ " صنبور " , " علامة " , " موقف سيارات " , " الجدول " , " مقعد " , " الطيور " , " القط " , " الكلب " , " الحصان " , " الأغنام " , " الثور " , " الفيل " ,
3
+ " الدب " , " حمار وحشي " , " الزرافة " , " حقيبة " , " مظلة " , " حقيبة يد " , " ربطة عنق " , " حقيبة " , " الفريسبي " , " الزلاجات " , " الزلاجات " ,
4
+ " الكرة الرياضية " , " طائرة ورقية " , " مضرب بيسبول " , " قفازات البيسبول " , " لوح التزلج " , " ركوب الأمواج " , " مضرب تنس " , " زجاجة " ,
5
+ " كأس " , " كأس " , " شوكة " , " سكين " , " ملعقة " , " وعاء " , " الموز " , " التفاح " , " ساندويتش " , " البرتقال " , " القرنبيط " ,
6
+ " الجزر " , " الكلاب الساخنة " , " البيتزا " , " دونات " , " كعكة " , " كرسي " , " أريكة " , " بوعاء " , " السرير " , " طاولة الطعام " , " المرحاض " ,
7
+ التلفزيون , الكمبيوتر المحمول , الفأرة , وحدة تحكم عن بعد , لوحة المفاتيح , الهاتف المحمول , فرن الميكروويف , محمصة خبز كهربائية , بالوعة , ثلاجة ,
8
+ " كتاب " , " ساعة " , " زهرية " , " مقص " , " دمية دب " , " مجفف الشعر " , " فرشاة الأسنان "
9
+ ]
cls_name/cls_name_en.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ model_cls_name: ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
2
+ 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant',
3
+ 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
4
+ 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle',
5
+ 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli',
6
+ 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet',
7
+ 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator',
8
+ 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'
9
+ ]
cls_name/cls_name_es.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ model_cls_name: ['persona', 'bicicleta', 'coche', 'motocicleta', 'avión', 'autobús', 'tren', 'camión', 'barco', 'semáforo',
2
+ 'boca de incendios', 'señal de alto', 'parquímetro', 'banco', 'pájaro', 'gato', 'perro', 'caballo', 'oveja', 'vaca', 'elefante',
3
+ 'oso', 'cebra', 'jirafa', 'mochila', 'paraguas', 'bolso', 'corbata', 'maleta', 'frisbee', 'esquís', 'snowboard',
4
+ 'pelota deportiva', 'cometa', 'bate de béisbol', 'guante de béisbol', 'monopatín', 'tabla de surf', 'raqueta de tenis', 'botella',
5
+ 'copa de vino', 'taza', 'tenedor', 'cuchillo', 'cuchara', 'tazón', 'plátano', 'manzana', 'sándwich', 'naranja', 'brócoli',
6
+ 'zanahoria', 'perrito caliente', 'pizza', 'rosquilla', 'pastel', 'silla', 'sofá', 'planta en maceta', 'cama', 'mesa de comedor', 'inodoro',
7
+ 'tv', 'laptop', 'ratón', 'control remoto', 'teclado', 'celular', 'microondas', 'horno', 'tostadora', 'fregadero', 'nevera',
8
+ 'libro', 'reloj', 'jarrón', 'tijeras', 'oso de peluche', 'secador de pelo', 'cepillo de dientes'
9
+ ]
cls_name/cls_name_ko.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ model_cls_name: ['사람', '자전거', '자동차', '오토바이', '비행기', '버스', '기차', '트럭', '보트', '신호등',
2
+ '소화전', '정지 신호', '주차 미터기', '벤치', '새', '고양이', '개', '말', '양', '소', '코끼리',
3
+ '곰', '얼룩말', '기린', '배낭', '우산', '핸드백', '타이', '여행가방', '프리스비', '스키', '스노우보드',
4
+ '스포츠 공', '연', '야구 방망이', '야구 글러브', '스케이트보드', '서프보드', '테니스 라켓', '병',
5
+ '와인잔', '컵', '포크', '나이프', '숟가락', '그릇', '바나나', '사과', '샌드위치', '오렌지', '브로콜리',
6
+ '당근', '핫도그', '피자', '도넛', '케이크', '의자', '소파', '화분', '침대', '식탁', '화장실',
7
+ 'tv', '노트북', '마우스', '리모컨', '키보드', '휴대전화', '전자레인지', '오븐', '토스터', '싱크대', '냉장고',
8
+ '책', '시계', '꽃병', '가위', '테디베어', '드라이기', '칫솔'
9
+ ]
cls_name/cls_name_ru.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ model_cls_name: ['человек', 'велосипед', 'автомобиль', 'мотоцикл', 'самолет', 'автобус', 'поезд', 'грузовик', 'лодка', 'светофор',
2
+ 'пожарный гидрант', 'стоп', 'паркомат', 'скамейка', 'птица', 'кошка', 'собака', 'лошадь', 'овца', 'корова', 'слон',
3
+ 'медведь', 'зебра', 'жираф', 'рюкзак', 'зонт', 'сумочка', 'галстук', 'чемодан', 'фрисби', 'лыжи', 'сноуборд',
4
+ 'спортивный мяч', 'воздушный змей', 'бейсбольная бита', 'бейсбольная перчатка', 'скейтборд', 'доска для серфинга', 'теннисная ракетка', 'бутылка',
5
+ 'бокал', 'чашка', 'вилка', 'нож', 'ложка', 'миска', 'банан', 'яблоко', 'бутерброд', 'апельсин', 'брокколи',
6
+ 'морковь', 'хот-дог', 'пицца', 'пончик', 'торт', 'стул', 'диван', 'растение в горшке', 'кровать', 'обеденный стол', 'туалет',
7
+ 'телевизор', 'ноутбук', 'мышь', 'пульт', 'клавиатура', 'мобильный телефон', 'микроволновая печь', 'духовка', 'тостер', 'раковина', 'холодильник',
8
+ 'книга', 'часы', 'ваза', 'ножницы', 'плюшевый мишка', 'фен', 'зубная щетка'
9
+ ]
cls_name/cls_name_zh.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ model_cls_name: ['人', '自行车', '汽车', '摩托车', '飞机', '公交车', '火车', '卡车', '船', '红绿灯', '消防栓', '停止标志',
2
+ '停车收费表', '长凳', '鸟', '猫', '狗', '马', '羊', '牛', '象', '熊', '斑马', '长颈鹿', '背包', '雨伞', '手提包', '领带',
3
+ '手提箱', '飞盘', '滑雪板', '单板滑雪', '运动球', '风筝', '棒球棒', '棒球手套', '滑板', '冲浪板', '网球拍', '瓶子', '红酒杯',
4
+ '杯子', '叉子', '刀', '勺', '碗', '香蕉', '苹果', '三明治', '橙子', '西兰花', '胡萝卜', '热狗', '比萨', '甜甜圈', '蛋糕',
5
+ '椅子', '长椅', '盆栽', '床', '餐桌', '马桶', '电视', '笔记本电脑', '鼠标', '遥控器', '键盘', '手机', '微波炉', '烤箱',
6
+ '烤面包机', '洗碗槽', '冰箱', '书', '时钟', '花瓶', '剪刀', '泰迪熊', '吹风机', '牙刷'
7
+ ]
img_example/Millenial-at-work.jpg ADDED
img_example/bus.jpg ADDED
img_example/giraffe.jpg ADDED
img_example/read.txt ADDED
File without changes
img_example/zidane.jpg ADDED
model_config/model_name_p5_all.csv ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ yolov5n
2
+ yolov5s
3
+ yolov5m
4
+ yolov5l
5
+ yolov5x
model_config/model_name_p5_all.yaml ADDED
@@ -0,0 +1 @@
 
 
1
+ model_names: ["yolov5n", "yolov5s", "yolov5m", "yolov5l", "yolov5x"]
model_config/model_name_p5_n.csv ADDED
@@ -0,0 +1 @@
 
 
1
+ yolov5n
model_config/model_name_p5_n.yaml ADDED
@@ -0,0 +1 @@
 
 
1
+ model_names: ["yolov5n"]
model_config/model_name_p5_p6_all.yaml ADDED
@@ -0,0 +1 @@
 
 
1
+ model_names: ["yolov5n", "yolov5s", "yolov5m", "yolov5l", "yolov5x", "yolov5n6", "yolov5s6", "yolov5m6", "yolov5l6", "yolov5x6"]
model_config/model_name_p6_all.csv ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ yolov5n6
2
+ yolov5s6
3
+ yolov5m6
4
+ yolov5l6
5
+ yolov5x6
model_config/model_name_p6_all.yaml ADDED
@@ -0,0 +1 @@
 
 
1
+ model_names: ["yolov5n6", "yolov5s6", "yolov5m6", "yolov5l6", "yolov5x6"]
model_download/yolov5_model_p5_all.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ cd ./yolov5
2
+
3
+ # 下载YOLOv5模型
4
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5n.pt
5
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5s.pt
6
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5m.pt
7
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5l.pt
8
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5x.pt
model_download/yolov5_model_p5_n.sh ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ cd ./yolov5
2
+
3
+ # 下载YOLOv5模型
4
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5n.pt
model_download/yolov5_model_p6_all.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ cd ./yolov5
2
+
3
+ # 下载YOLOv5模型
4
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5n6.pt
5
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5s6.pt
6
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5m6.pt
7
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5l6.pt
8
+ wget -c -t 0 https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5x6.pt
requirements.txt ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Base ----------------------------------------
2
+ matplotlib>=3.2.2
3
+ numpy>=1.22.3
4
+ opencv-python-headless>=4.5.5.64
5
+ Pillow>=7.1.2
6
+ PyYAML>=5.3.1
7
+ requests>=2.23.0
8
+ scipy>=1.4.1 # Google Colab version
9
+ torch>=1.7.0
10
+ torchvision>=0.8.1
11
+ tqdm>=4.41.0
12
+
13
+ # Gradio YOLOv5 Det ----------------------------------------
14
+ gradio>=3.0.3
15
+ wget>=3.2
16
+ rich>=12.2.0
17
+ fpdf>=1.7.2
18
+ plotly>=5.7.0
19
+ bokeh>=2.4.2
20
+ openpyxl>=3.0.10
21
+
22
+ # Logging -------------------------------------
23
+ tensorboard>=2.4.1
24
+ # wandb
25
+
26
+ # Plotting ------------------------------------
27
+ pandas>=1.1.4
28
+ seaborn>=0.11.0
29
+
30
+ # Export --------------------------------------
31
+ # coremltools>=4.1 # CoreML export
32
+ # onnx>=1.9.0 # ONNX export
33
+ # onnx-simplifier>=0.3.6 # ONNX simplifier
34
+ # scikit-learn==0.19.2 # CoreML quantization
35
+ # tensorflow>=2.4.1 # TFLite export
36
+ # tensorflowjs>=3.9.0 # TF.js export
37
+ # openvino-dev # OpenVINO export
38
+
39
+ # Extras --------------------------------------
40
+ ipython # interactive notebook
41
+ psutil # system utilization
42
+ thop # FLOPs computation
43
+ # albumentations>=1.0.3
44
+ # pycocotools>=2.0 # COCO mAP
45
+ # roboflow
util/fonts_opt.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # font management
2
+ # author: Zeng Yifu(曾逸夫)
3
+ # creation time: 2022-05-01
4
+ # email: [email protected]
5
+ # project homepage: https://gitee.com/CV_Lab/gradio_yolov5_det
6
+
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import wget
12
+ from rich.console import Console
13
+
14
+ ROOT_PATH = sys.path[0] # Project root directory
15
+
16
+ # Chinese, English, Russian, Spanish, Arabic, Korean
17
+ fonts_list = ["SimSun.ttf", "TimesNewRoman.ttf", "malgun.ttf"] # font list
18
+ fonts_suffix = ["ttc", "ttf", "otf"] # font suffix
19
+
20
+ data_url_dict = {
21
+ "SimSun.ttf": "https://gitee.com/CV_Lab/gradio_yolov5_det/attach_files/1053539/download/SimSun.ttf",
22
+ "TimesNewRoman.ttf": "https://gitee.com/CV_Lab/gradio_yolov5_det/attach_files/1053537/download/TimesNewRoman.ttf",
23
+ "malgun.ttf": "https://gitee.com/CV_Lab/gradio_yolov5_det/attach_files/1053538/download/malgun.ttf",}
24
+
25
+ console = Console()
26
+
27
+
28
+ # create font library
29
+ def add_fronts(font_diff):
30
+
31
+ global font_name
32
+
33
+ for k, v in data_url_dict.items():
34
+ if k in font_diff:
35
+ font_name = v.split("/")[-1] # font name
36
+ Path(f"{ROOT_PATH}/fonts").mkdir(parents=True, exist_ok=True) # Create a directory
37
+
38
+ file_path = f"{ROOT_PATH}/fonts/{font_name}" # font path
39
+
40
+ try:
41
+ # Download font file
42
+ wget.download(v, file_path)
43
+ except Exception as e:
44
+ print("Path error! Program ended!")
45
+ print(e)
46
+ sys.exit()
47
+ else:
48
+ print()
49
+ console.print(f"{font_name} [bold green]font file download complete![/bold green] has been saved to: {file_path}")
50
+
51
+
52
+ # Determine the font file
53
+ def is_fonts(fonts_dir):
54
+ if os.path.isdir(fonts_dir):
55
+ # if the font library exists
56
+ f_list = os.listdir(fonts_dir) # local font library
57
+
58
+ font_diff = list(set(fonts_list).difference(set(f_list)))
59
+
60
+ if font_diff != []:
61
+ # font does not exist
62
+ console.print("[bold red] font does not exist, loading...[/bold red]")
63
+ add_fronts(font_diff) # Create a font library
64
+ else:
65
+ console.print(f"{fonts_list}[bold green]font already exists![/bold green]")
66
+ else:
67
+ # The font library does not exist, create a font library
68
+ console.print("[bold red]font library does not exist, creating...[/bold red]")
69
+ add_fronts(fonts_list) # Create a font library
util/pdf_opt.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PDF management
2
+ # author: Zeng Yifu
3
+ # creation time: 2022-05-05
4
+
5
+ from fpdf import FPDF
6
+
7
+
8
+ # PDF generation class
9
+ class PDF(FPDF):
10
+ # Reference: https://pyfpdf.readthedocs.io/en/latest/Tutorial/index.html
11
+ def header(self):
12
+ # Set Chinese font
13
+ self.add_font("SimSun", "", "./fonts/SimSun.ttf", uni=True)
14
+ self.set_font("SimSun", "", 16)
15
+ # Calculate width of title and position
16
+ w = self.get_string_width(title) + 6
17
+ self.set_x((210 - w) / 2)
18
+ # Colors of frame, background and text
19
+ self.set_draw_color(255, 255, 255)
20
+ self.set_fill_color(255, 255, 255)
21
+ self.set_text_color(0, 0, 0)
22
+ # Thickness of frame (1 mm)
23
+ # self.set_line_width(1)
24
+ # Title
25
+ self.cell(w, 9, title, 1, 1, "C", 1)
26
+ # Line break
27
+ self.ln(10)
28
+
29
+ def footer(self):
30
+ # Position at 1.5 cm from bottom
31
+ self.set_y(-15)
32
+ # Set Chinese font
33
+ self.add_font("SimSun", "", "./fonts/SimSun.ttf", uni=True)
34
+ self.set_font("SimSun", "", 12)
35
+ # Text color in gray
36
+ self.set_text_color(128)
37
+ # Page number
38
+ self.cell(0, 10, "Page " + str(self.page_no()), 0, 0, "C")
39
+
40
+ def chapter_title(self, num, label):
41
+ # Set Chinese font
42
+ self.add_font("SimSun", "", "./fonts/SimSun.ttf", uni=True)
43
+ self.set_font("SimSun", "", 12)
44
+ # Background color
45
+ self.set_fill_color(200, 220, 255)
46
+ # Title
47
+ # self.cell(0, 6, 'Chapter %d : %s' % (num, label), 0, 1, 'L', 1)
48
+ self.cell(0, 6, "Detection Result:", 0, 1, "L", 1)
49
+ # Line break
50
+ self.ln(4)
51
+
52
+ def chapter_body(self, name):
53
+
54
+ # Set Chinese font
55
+ self.add_font("SimSun", "", "./fonts/SimSun.ttf", uni=True)
56
+ self.set_font("SimSun", "", 12)
57
+ # Output justified text
58
+ self.multi_cell(0, 5, name)
59
+ # Line break
60
+ self.ln()
61
+ self.cell(0, 5, "--------------------------------------")
62
+
63
+ def print_chapter(self, num, title, name):
64
+ self.add_page()
65
+ self.chapter_title(num, title)
66
+ self.chapter_body(name)
67
+
68
+
69
+ # pdf generation function
70
+ def pdf_generate(input_file, output_file, title_):
71
+ global title
72
+
73
+ title = title_
74
+ pdf = PDF()
75
+ pdf.set_title(title)
76
+ pdf.set_author("Zeng Yifu")
77
+ pdf.print_chapter(1, "A RUNAWAY REEF", input_file)
78
+ pdf.output(output_file)