Showing
91 changed files
with
3722 additions
and
1 deletions
code/yolo-RTMP/yolo.py
0 → 100644
1 | + | ||
2 | +# insert at 1, 0 is the script path (or '' in REPL) | ||
3 | +#sys.path.insert(1, '/yolov5-5.0.5') | ||
4 | + | ||
5 | + | ||
6 | +# import subprocess | ||
7 | +import os | ||
8 | + | ||
9 | +# # YOLO Setting | ||
10 | +# model_path = "./best.pt" # it automatically downloads yolov5s model to given path | ||
11 | +# device = "cpu" # or "cpu" | ||
12 | +# yolov5 = YOLOv5(model_path, device) | ||
13 | + | ||
14 | +# # ts file to mp4 file | ||
15 | +# ts_file = 'sample.ts' | ||
16 | +# mp4_file = 'sample.mp4' | ||
17 | +# subprocess.run(['ffmpeg', '-i', ts_file, mp4_file]) | ||
18 | + | ||
19 | +#!/usr/local/bin/python3 | ||
20 | +# -*- coding: utf-8 -*- | ||
21 | +import re | ||
22 | +import sys | ||
23 | +from yolo_module.yolov5.detect import main | ||
24 | +if __name__ == '__main__': | ||
25 | + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) | ||
26 | + sys.exit(main()) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
code/yolo-RTMP/yolo_module/LICENSE
0 → 100644
This diff is collapsed. Click to expand it.
code/yolo-RTMP/yolo_module/MANIFEST.in
0 → 100644
code/yolo-RTMP/yolo_module/PKG-INFO
0 → 100644
1 | +Metadata-Version: 2.1 | ||
2 | +Name: yolov5 | ||
3 | +Version: 5.0.5 | ||
4 | +Summary: Packaged version of the Yolov5 object detector | ||
5 | +Home-page: https://github.com/fcakyon/yolov5-pip | ||
6 | +Author: | ||
7 | +License: GPL | ||
8 | +Description: <h1 align="center"> | ||
9 | + packaged ultralytics/yolov5 | ||
10 | + </h1> | ||
11 | + | ||
12 | + <h4 align="center"> | ||
13 | + pip install yolov5 | ||
14 | + </h4> | ||
15 | + | ||
16 | + <div align="center"> | ||
17 | + <a href="https://badge.fury.io/py/yolov5"><img src="https://badge.fury.io/py/yolov5.svg" alt="pypi version"></a> | ||
18 | + <a href="https://pepy.tech/project/yolov5"><img src="https://pepy.tech/badge/yolov5/month" alt="downloads"></a> | ||
19 | + <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml"><img src="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml/badge.svg" alt="ci testing"></a> | ||
20 | + <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml"><img src="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml/badge.svg" alt="package testing"></a> | ||
21 | + </div> | ||
22 | + | ||
23 | + ## Overview | ||
24 | + | ||
25 | + You can finally install [YOLOv5 object detector](https://github.com/ultralytics/yolov5) using [pip](https://pypi.org/project/yolov5/) and integrate into your project easily. | ||
26 | + | ||
27 | + <img src="https://user-images.githubusercontent.com/26833433/114313216-f0a5e100-9af5-11eb-8445-c682b60da2e3.png" width="1000"> | ||
28 | + | ||
29 | + ## Installation | ||
30 | + | ||
31 | + - Install yolov5 using pip `(for Python >=3.7)`: | ||
32 | + | ||
33 | + ```console | ||
34 | + pip install yolov5 | ||
35 | + ``` | ||
36 | + | ||
37 | + - Install yolov5 using pip `(for Python 3.6)`: | ||
38 | + | ||
39 | + ```console | ||
40 | + pip install "numpy>=1.18.5,<1.20" "matplotlib>=3.2.2,<4" | ||
41 | + pip install yolov5 | ||
42 | + ``` | ||
43 | + | ||
44 | + ## Basic Usage | ||
45 | + | ||
46 | + ```python | ||
47 | + import yolov5 | ||
48 | + | ||
49 | + # model | ||
50 | + model = yolov5.load('yolov5s') | ||
51 | + | ||
52 | + # image | ||
53 | + img = 'https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg' | ||
54 | + | ||
55 | + # inference | ||
56 | + results = model(img) | ||
57 | + | ||
58 | + # inference with larger input size | ||
59 | + results = model(img, size=1280) | ||
60 | + | ||
61 | + # inference with test time augmentation | ||
62 | + results = model(img, augment=True) | ||
63 | + | ||
64 | + # show results | ||
65 | + results.show() | ||
66 | + | ||
67 | + # save results | ||
68 | + results.save(save_dir='results/') | ||
69 | + | ||
70 | + ``` | ||
71 | + | ||
72 | + ## Alternative Usage | ||
73 | + | ||
74 | + ```python | ||
75 | + from yolo_module.yolov5 import YOLOv5 | ||
76 | + | ||
77 | + # set model params | ||
78 | + model_path = "yolov5/weights/yolov5s.pt" # it automatically downloads yolov5s model to given path | ||
79 | + device = "cuda" # or "cpu" | ||
80 | + | ||
81 | + # init yolov5 model | ||
82 | + yolov5 = YOLOv5(model_path, device) | ||
83 | + | ||
84 | + # load images | ||
85 | + image1 = 'https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg' | ||
86 | + image2 = 'https://github.com/ultralytics/yolov5/blob/master/data/images/bus.jpg' | ||
87 | + | ||
88 | + # perform inference | ||
89 | + results = yolov5.predict(image1) | ||
90 | + | ||
91 | + # perform inference with larger input size | ||
92 | + results = yolov5.predict(image1, size=1280) | ||
93 | + | ||
94 | + # perform inference with test time augmentation | ||
95 | + results = yolov5.predict(image1, augment=True) | ||
96 | + | ||
97 | + # perform inference on multiple images | ||
98 | + results = yolov5.predict([image1, image2], size=1280, augment=True) | ||
99 | + | ||
100 | + # show detection bounding boxes on image | ||
101 | + results.show() | ||
102 | + | ||
103 | + # save results into "results/" folder | ||
104 | + results.save(save_dir='results/') | ||
105 | + ``` | ||
106 | + | ||
107 | + ## Scripts | ||
108 | + | ||
109 | + You can call yolo_train, yolo_detect and yolo_test commands after installing the package via `pip`: | ||
110 | + | ||
111 | + ### Training | ||
112 | + | ||
113 | + Run commands below to reproduce results on [COCO](https://github.com/ultralytics/yolov5/blob/master/data/scripts/get_coco.sh) dataset (dataset auto-downloads on first use). Training times for YOLOv5s/m/l/x are 2/4/6/8 days on a single V100 (multi-GPU times faster). Use the largest `--batch-size` your GPU allows (batch sizes shown for 16 GB devices). | ||
114 | + | ||
115 | + ```bash | ||
116 | + $ yolo_train --data coco.yaml --cfg yolov5s.yaml --weights '' --batch-size 64 | ||
117 | + yolov5m 40 | ||
118 | + yolov5l 24 | ||
119 | + yolov5x 16 | ||
120 | + ``` | ||
121 | + | ||
122 | + ### Inference | ||
123 | + | ||
124 | + yolo_detect command runs inference on a variety of sources, downloading models automatically from the [latest YOLOv5 release](https://github.com/ultralytics/yolov5/releases) and saving results to `runs/detect`. | ||
125 | + | ||
126 | + ```bash | ||
127 | + $ yolo_detect --source 0 # webcam | ||
128 | + file.jpg # image | ||
129 | + file.mp4 # video | ||
130 | + path/ # directory | ||
131 | + path/*.jpg # glob | ||
132 | + rtsp://170.93.143.139/rtplive/470011e600ef003a004ee33696235daa # rtsp stream | ||
133 | + rtmp://192.168.1.105/live/test # rtmp stream | ||
134 | + http://112.50.243.8/PLTV/88888888/224/3221225900/1.m3u8 # http stream | ||
135 | + ``` | ||
136 | + | ||
137 | + To run inference on example images in `yolov5/data/images`: | ||
138 | + | ||
139 | + ```bash | ||
140 | + $ yolo_detect --source yolov5/data/images --weights yolov5s.pt --conf 0.25 | ||
141 | + ``` | ||
142 | + | ||
143 | + ## Status | ||
144 | + | ||
145 | + Builds for the latest commit for `Windows/Linux/MacOS` with `Python3.6/3.7/3.8`: <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml"><img src="https://github.com/fcakyon/yolov5-python/workflows/CI%20CPU%20Testing/badge.svg" alt="CI CPU testing"></a> | ||
146 | + | ||
147 | + Status for the train/detect/test scripts: <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml"><img src="https://github.com/fcakyon/yolov5-python/workflows/Package%20CPU%20Testing/badge.svg" alt="Package CPU testing"></a> | ||
148 | + | ||
149 | +Keywords: machine-learning,deep-learning,ml,pytorch,YOLO,object-detection,vision,YOLOv3,YOLOv4,YOLOv5 | ||
150 | +Platform: UNKNOWN | ||
151 | +Classifier: Development Status :: 5 - Production/Stable | ||
152 | +Classifier: License :: OSI Approved :: GNU General Public License (GPL) | ||
153 | +Classifier: Operating System :: OS Independent | ||
154 | +Classifier: Intended Audience :: Developers | ||
155 | +Classifier: Intended Audience :: Science/Research | ||
156 | +Classifier: Programming Language :: Python :: 3 | ||
157 | +Classifier: Programming Language :: Python :: 3.6 | ||
158 | +Classifier: Programming Language :: Python :: 3.7 | ||
159 | +Classifier: Programming Language :: Python :: 3.8 | ||
160 | +Classifier: Topic :: Software Development :: Libraries | ||
161 | +Classifier: Topic :: Software Development :: Libraries :: Python Modules | ||
162 | +Classifier: Topic :: Education | ||
163 | +Classifier: Topic :: Scientific/Engineering | ||
164 | +Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence | ||
165 | +Classifier: Topic :: Scientific/Engineering :: Image Recognition | ||
166 | +Requires-Python: >=3.6 | ||
167 | +Description-Content-Type: text/markdown | ||
168 | +Provides-Extra: tests |
code/yolo-RTMP/yolo_module/README.md
0 → 100644
1 | +<h1 align="center"> | ||
2 | + packaged ultralytics/yolov5 | ||
3 | +</h1> | ||
4 | + | ||
5 | +<h4 align="center"> | ||
6 | + pip install yolov5 | ||
7 | +</h4> | ||
8 | + | ||
9 | +<div align="center"> | ||
10 | + <a href="https://badge.fury.io/py/yolov5"><img src="https://badge.fury.io/py/yolov5.svg" alt="pypi version"></a> | ||
11 | + <a href="https://pepy.tech/project/yolov5"><img src="https://pepy.tech/badge/yolov5/month" alt="downloads"></a> | ||
12 | + <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml"><img src="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml/badge.svg" alt="ci testing"></a> | ||
13 | + <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml"><img src="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml/badge.svg" alt="package testing"></a> | ||
14 | +</div> | ||
15 | + | ||
16 | +## Overview | ||
17 | + | ||
18 | +You can finally install [YOLOv5 object detector](https://github.com/ultralytics/yolov5) using [pip](https://pypi.org/project/yolov5/) and integrate into your project easily. | ||
19 | + | ||
20 | +<img src="https://user-images.githubusercontent.com/26833433/114313216-f0a5e100-9af5-11eb-8445-c682b60da2e3.png" width="1000"> | ||
21 | + | ||
22 | +## Installation | ||
23 | + | ||
24 | +- Install yolov5 using pip `(for Python >=3.7)`: | ||
25 | + | ||
26 | +```console | ||
27 | +pip install yolov5 | ||
28 | +``` | ||
29 | + | ||
30 | +- Install yolov5 using pip `(for Python 3.6)`: | ||
31 | + | ||
32 | +```console | ||
33 | +pip install "numpy>=1.18.5,<1.20" "matplotlib>=3.2.2,<4" | ||
34 | +pip install yolov5 | ||
35 | +``` | ||
36 | + | ||
37 | +## Basic Usage | ||
38 | + | ||
39 | +```python | ||
40 | +import yolov5 | ||
41 | + | ||
42 | +# model | ||
43 | +model = yolov5.load('yolov5s') | ||
44 | + | ||
45 | +# image | ||
46 | +img = 'https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg' | ||
47 | + | ||
48 | +# inference | ||
49 | +results = model(img) | ||
50 | + | ||
51 | +# inference with larger input size | ||
52 | +results = model(img, size=1280) | ||
53 | + | ||
54 | +# inference with test time augmentation | ||
55 | +results = model(img, augment=True) | ||
56 | + | ||
57 | +# show results | ||
58 | +results.show() | ||
59 | + | ||
60 | +# save results | ||
61 | +results.save(save_dir='results/') | ||
62 | + | ||
63 | +``` | ||
64 | + | ||
65 | +## Alternative Usage | ||
66 | + | ||
67 | +```python | ||
68 | +from yolo_module.yolov5 import YOLOv5 | ||
69 | + | ||
70 | +# set model params | ||
71 | +model_path = "yolov5/weights/yolov5s.pt" # it automatically downloads yolov5s model to given path | ||
72 | +device = "cuda" # or "cpu" | ||
73 | + | ||
74 | +# init yolov5 model | ||
75 | +yolov5 = YOLOv5(model_path, device) | ||
76 | + | ||
77 | +# load images | ||
78 | +image1 = 'https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg' | ||
79 | +image2 = 'https://github.com/ultralytics/yolov5/blob/master/data/images/bus.jpg' | ||
80 | + | ||
81 | +# perform inference | ||
82 | +results = yolov5.predict(image1) | ||
83 | + | ||
84 | +# perform inference with larger input size | ||
85 | +results = yolov5.predict(image1, size=1280) | ||
86 | + | ||
87 | +# perform inference with test time augmentation | ||
88 | +results = yolov5.predict(image1, augment=True) | ||
89 | + | ||
90 | +# perform inference on multiple images | ||
91 | +results = yolov5.predict([image1, image2], size=1280, augment=True) | ||
92 | + | ||
93 | +# show detection bounding boxes on image | ||
94 | +results.show() | ||
95 | + | ||
96 | +# save results into "results/" folder | ||
97 | +results.save(save_dir='results/') | ||
98 | +``` | ||
99 | + | ||
100 | +## Scripts | ||
101 | + | ||
102 | +You can call yolo_train, yolo_detect and yolo_test commands after installing the package via `pip`: | ||
103 | + | ||
104 | +### Training | ||
105 | + | ||
106 | +Run commands below to reproduce results on [COCO](https://github.com/ultralytics/yolov5/blob/master/data/scripts/get_coco.sh) dataset (dataset auto-downloads on first use). Training times for YOLOv5s/m/l/x are 2/4/6/8 days on a single V100 (multi-GPU times faster). Use the largest `--batch-size` your GPU allows (batch sizes shown for 16 GB devices). | ||
107 | + | ||
108 | +```bash | ||
109 | +$ yolo_train --data coco.yaml --cfg yolov5s.yaml --weights '' --batch-size 64 | ||
110 | + yolov5m 40 | ||
111 | + yolov5l 24 | ||
112 | + yolov5x 16 | ||
113 | +``` | ||
114 | + | ||
115 | +### Inference | ||
116 | + | ||
117 | +yolo_detect command runs inference on a variety of sources, downloading models automatically from the [latest YOLOv5 release](https://github.com/ultralytics/yolov5/releases) and saving results to `runs/detect`. | ||
118 | + | ||
119 | +```bash | ||
120 | +$ yolo_detect --source 0 # webcam | ||
121 | + file.jpg # image | ||
122 | + file.mp4 # video | ||
123 | + path/ # directory | ||
124 | + path/*.jpg # glob | ||
125 | + rtsp://170.93.143.139/rtplive/470011e600ef003a004ee33696235daa # rtsp stream | ||
126 | + rtmp://192.168.1.105/live/test # rtmp stream | ||
127 | + http://112.50.243.8/PLTV/88888888/224/3221225900/1.m3u8 # http stream | ||
128 | +``` | ||
129 | + | ||
130 | +To run inference on example images in `yolov5/data/images`: | ||
131 | + | ||
132 | +```bash | ||
133 | +$ yolo_detect --source yolov5/data/images --weights yolov5s.pt --conf 0.25 | ||
134 | +``` | ||
135 | + | ||
136 | +## Status | ||
137 | + | ||
138 | +Builds for the latest commit for `Windows/Linux/MacOS` with `Python3.6/3.7/3.8`: <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml"><img src="https://github.com/fcakyon/yolov5-python/workflows/CI%20CPU%20Testing/badge.svg" alt="CI CPU testing"></a> | ||
139 | + | ||
140 | +Status for the train/detect/test scripts: <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml"><img src="https://github.com/fcakyon/yolov5-python/workflows/Package%20CPU%20Testing/badge.svg" alt="Package CPU testing"></a> |
code/yolo-RTMP/yolo_module/setup.cfg
0 → 100644
code/yolo-RTMP/yolo_module/setup.py
0 → 100644
1 | +import io | ||
2 | +import os | ||
3 | +import re | ||
4 | + | ||
5 | +import setuptools | ||
6 | + | ||
7 | + | ||
8 | +def get_long_description(): | ||
9 | + base_dir = os.path.abspath(os.path.dirname(__file__)) | ||
10 | + with io.open(os.path.join(base_dir, "README.md"), encoding="utf-8") as f: | ||
11 | + return f.read() | ||
12 | + | ||
13 | + | ||
14 | +def get_requirements(): | ||
15 | + with open("requirements.txt") as f: | ||
16 | + return f.read().splitlines() | ||
17 | + | ||
18 | + | ||
19 | +def get_version(): | ||
20 | + current_dir = os.path.abspath(os.path.dirname(__file__)) | ||
21 | + version_file = os.path.join(current_dir, "yolov5", "__init__.py") | ||
22 | + with io.open(version_file, encoding="utf-8") as f: | ||
23 | + return re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', f.read(), re.M).group(1) | ||
24 | + | ||
25 | + | ||
26 | +setuptools.setup( | ||
27 | + name="yolov5", | ||
28 | + version=get_version(), | ||
29 | + author="", | ||
30 | + license="GPL", | ||
31 | + description="Packaged version of the Yolov5 object detector", | ||
32 | + long_description=get_long_description(), | ||
33 | + long_description_content_type="text/markdown", | ||
34 | + url="https://github.com/fcakyon/yolov5-pip", | ||
35 | + packages=setuptools.find_packages(exclude=["tests"]), | ||
36 | + python_requires=">=3.6", | ||
37 | + install_requires=get_requirements(), | ||
38 | + extras_require={"tests": ["pytest"]}, | ||
39 | + include_package_data=True, | ||
40 | + options={'bdist_wheel':{'python_tag':'py36.py37.py38'}}, | ||
41 | + classifiers=[ | ||
42 | + "Development Status :: 5 - Production/Stable", | ||
43 | + "License :: OSI Approved :: GNU General Public License (GPL)", | ||
44 | + "Operating System :: OS Independent", | ||
45 | + "Intended Audience :: Developers", | ||
46 | + "Intended Audience :: Science/Research", | ||
47 | + "Programming Language :: Python :: 3", | ||
48 | + "Programming Language :: Python :: 3.6", | ||
49 | + "Programming Language :: Python :: 3.7", | ||
50 | + "Programming Language :: Python :: 3.8", | ||
51 | + "Topic :: Software Development :: Libraries", | ||
52 | + "Topic :: Software Development :: Libraries :: Python Modules", | ||
53 | + "Topic :: Education", | ||
54 | + "Topic :: Scientific/Engineering", | ||
55 | + "Topic :: Scientific/Engineering :: Artificial Intelligence", | ||
56 | + "Topic :: Scientific/Engineering :: Image Recognition", | ||
57 | + ], | ||
58 | + keywords="machine-learning, deep-learning, ml, pytorch, YOLO, object-detection, vision, YOLOv3, YOLOv4, YOLOv5", | ||
59 | + entry_points={'console_scripts': [ | ||
60 | + 'yolo_train=yolov5.train:main', | ||
61 | + 'yolo_test=yolov5.test:main', | ||
62 | + 'yolo_detect=yolov5.detect:main', | ||
63 | + 'yolo_export=yolov5.models.export:main' | ||
64 | + ], | ||
65 | + } | ||
66 | +) |
1 | +Metadata-Version: 2.1 | ||
2 | +Name: yolov5 | ||
3 | +Version: 5.0.5 | ||
4 | +Summary: Packaged version of the Yolov5 object detector | ||
5 | +Home-page: https://github.com/fcakyon/yolov5-pip | ||
6 | +Author: | ||
7 | +License: GPL | ||
8 | +Description: <h1 align="center"> | ||
9 | + packaged ultralytics/yolov5 | ||
10 | + </h1> | ||
11 | + | ||
12 | + <h4 align="center"> | ||
13 | + pip install yolov5 | ||
14 | + </h4> | ||
15 | + | ||
16 | + <div align="center"> | ||
17 | + <a href="https://badge.fury.io/py/yolov5"><img src="https://badge.fury.io/py/yolov5.svg" alt="pypi version"></a> | ||
18 | + <a href="https://pepy.tech/project/yolov5"><img src="https://pepy.tech/badge/yolov5/month" alt="downloads"></a> | ||
19 | + <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml"><img src="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml/badge.svg" alt="ci testing"></a> | ||
20 | + <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml"><img src="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml/badge.svg" alt="package testing"></a> | ||
21 | + </div> | ||
22 | + | ||
23 | + ## Overview | ||
24 | + | ||
25 | + You can finally install [YOLOv5 object detector](https://github.com/ultralytics/yolov5) using [pip](https://pypi.org/project/yolov5/) and integrate into your project easily. | ||
26 | + | ||
27 | + <img src="https://user-images.githubusercontent.com/26833433/114313216-f0a5e100-9af5-11eb-8445-c682b60da2e3.png" width="1000"> | ||
28 | + | ||
29 | + ## Installation | ||
30 | + | ||
31 | + - Install yolov5 using pip `(for Python >=3.7)`: | ||
32 | + | ||
33 | + ```console | ||
34 | + pip install yolov5 | ||
35 | + ``` | ||
36 | + | ||
37 | + - Install yolov5 using pip `(for Python 3.6)`: | ||
38 | + | ||
39 | + ```console | ||
40 | + pip install "numpy>=1.18.5,<1.20" "matplotlib>=3.2.2,<4" | ||
41 | + pip install yolov5 | ||
42 | + ``` | ||
43 | + | ||
44 | + ## Basic Usage | ||
45 | + | ||
46 | + ```python | ||
47 | + import yolov5 | ||
48 | + | ||
49 | + # model | ||
50 | + model = yolov5.load('yolov5s') | ||
51 | + | ||
52 | + # image | ||
53 | + img = 'https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg' | ||
54 | + | ||
55 | + # inference | ||
56 | + results = model(img) | ||
57 | + | ||
58 | + # inference with larger input size | ||
59 | + results = model(img, size=1280) | ||
60 | + | ||
61 | + # inference with test time augmentation | ||
62 | + results = model(img, augment=True) | ||
63 | + | ||
64 | + # show results | ||
65 | + results.show() | ||
66 | + | ||
67 | + # save results | ||
68 | + results.save(save_dir='results/') | ||
69 | + | ||
70 | + ``` | ||
71 | + | ||
72 | + ## Alternative Usage | ||
73 | + | ||
74 | + ```python | ||
75 | + from yolo_module.yolov5 import YOLOv5 | ||
76 | + | ||
77 | + # set model params | ||
78 | + model_path = "yolov5/weights/yolov5s.pt" # it automatically downloads yolov5s model to given path | ||
79 | + device = "cuda" # or "cpu" | ||
80 | + | ||
81 | + # init yolov5 model | ||
82 | + yolov5 = YOLOv5(model_path, device) | ||
83 | + | ||
84 | + # load images | ||
85 | + image1 = 'https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg' | ||
86 | + image2 = 'https://github.com/ultralytics/yolov5/blob/master/data/images/bus.jpg' | ||
87 | + | ||
88 | + # perform inference | ||
89 | + results = yolov5.predict(image1) | ||
90 | + | ||
91 | + # perform inference with larger input size | ||
92 | + results = yolov5.predict(image1, size=1280) | ||
93 | + | ||
94 | + # perform inference with test time augmentation | ||
95 | + results = yolov5.predict(image1, augment=True) | ||
96 | + | ||
97 | + # perform inference on multiple images | ||
98 | + results = yolov5.predict([image1, image2], size=1280, augment=True) | ||
99 | + | ||
100 | + # show detection bounding boxes on image | ||
101 | + results.show() | ||
102 | + | ||
103 | + # save results into "results/" folder | ||
104 | + results.save(save_dir='results/') | ||
105 | + ``` | ||
106 | + | ||
107 | + ## Scripts | ||
108 | + | ||
109 | + You can call yolo_train, yolo_detect and yolo_test commands after installing the package via `pip`: | ||
110 | + | ||
111 | + ### Training | ||
112 | + | ||
113 | + Run commands below to reproduce results on [COCO](https://github.com/ultralytics/yolov5/blob/master/data/scripts/get_coco.sh) dataset (dataset auto-downloads on first use). Training times for YOLOv5s/m/l/x are 2/4/6/8 days on a single V100 (multi-GPU times faster). Use the largest `--batch-size` your GPU allows (batch sizes shown for 16 GB devices). | ||
114 | + | ||
115 | + ```bash | ||
116 | + $ yolo_train --data coco.yaml --cfg yolov5s.yaml --weights '' --batch-size 64 | ||
117 | + yolov5m 40 | ||
118 | + yolov5l 24 | ||
119 | + yolov5x 16 | ||
120 | + ``` | ||
121 | + | ||
122 | + ### Inference | ||
123 | + | ||
124 | + yolo_detect command runs inference on a variety of sources, downloading models automatically from the [latest YOLOv5 release](https://github.com/ultralytics/yolov5/releases) and saving results to `runs/detect`. | ||
125 | + | ||
126 | + ```bash | ||
127 | + $ yolo_detect --source 0 # webcam | ||
128 | + file.jpg # image | ||
129 | + file.mp4 # video | ||
130 | + path/ # directory | ||
131 | + path/*.jpg # glob | ||
132 | + rtsp://170.93.143.139/rtplive/470011e600ef003a004ee33696235daa # rtsp stream | ||
133 | + rtmp://192.168.1.105/live/test # rtmp stream | ||
134 | + http://112.50.243.8/PLTV/88888888/224/3221225900/1.m3u8 # http stream | ||
135 | + ``` | ||
136 | + | ||
137 | + To run inference on example images in `yolov5/data/images`: | ||
138 | + | ||
139 | + ```bash | ||
140 | + $ yolo_detect --source yolov5/data/images --weights yolov5s.pt --conf 0.25 | ||
141 | + ``` | ||
142 | + | ||
143 | + ## Status | ||
144 | + | ||
145 | + Builds for the latest commit for `Windows/Linux/MacOS` with `Python3.6/3.7/3.8`: <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/ci.yml"><img src="https://github.com/fcakyon/yolov5-python/workflows/CI%20CPU%20Testing/badge.svg" alt="CI CPU testing"></a> | ||
146 | + | ||
147 | + Status for the train/detect/test scripts: <a href="https://github.com/fcakyon/yolov5-pip/actions/workflows/package_testing.yml"><img src="https://github.com/fcakyon/yolov5-python/workflows/Package%20CPU%20Testing/badge.svg" alt="Package CPU testing"></a> | ||
148 | + | ||
149 | +Keywords: machine-learning,deep-learning,ml,pytorch,YOLO,object-detection,vision,YOLOv3,YOLOv4,YOLOv5 | ||
150 | +Platform: UNKNOWN | ||
151 | +Classifier: Development Status :: 5 - Production/Stable | ||
152 | +Classifier: License :: OSI Approved :: GNU General Public License (GPL) | ||
153 | +Classifier: Operating System :: OS Independent | ||
154 | +Classifier: Intended Audience :: Developers | ||
155 | +Classifier: Intended Audience :: Science/Research | ||
156 | +Classifier: Programming Language :: Python :: 3 | ||
157 | +Classifier: Programming Language :: Python :: 3.6 | ||
158 | +Classifier: Programming Language :: Python :: 3.7 | ||
159 | +Classifier: Programming Language :: Python :: 3.8 | ||
160 | +Classifier: Topic :: Software Development :: Libraries | ||
161 | +Classifier: Topic :: Software Development :: Libraries :: Python Modules | ||
162 | +Classifier: Topic :: Education | ||
163 | +Classifier: Topic :: Scientific/Engineering | ||
164 | +Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence | ||
165 | +Classifier: Topic :: Scientific/Engineering :: Image Recognition | ||
166 | +Requires-Python: >=3.6 | ||
167 | +Description-Content-Type: text/markdown | ||
168 | +Provides-Extra: tests |
1 | +LICENSE | ||
2 | +MANIFEST.in | ||
3 | +README.md | ||
4 | +setup.py | ||
5 | +yolov5/__init__.py | ||
6 | +yolov5/detect.py | ||
7 | +yolov5/helpers.py | ||
8 | +yolov5/hubconf.py | ||
9 | +yolov5/test.py | ||
10 | +yolov5/train.py | ||
11 | +yolov5.egg-info/PKG-INFO | ||
12 | +yolov5.egg-info/SOURCES.txt | ||
13 | +yolov5.egg-info/dependency_links.txt | ||
14 | +yolov5.egg-info/entry_points.txt | ||
15 | +yolov5.egg-info/requires.txt | ||
16 | +yolov5.egg-info/top_level.txt | ||
17 | +yolov5/data/GlobalWheat2020.yaml | ||
18 | +yolov5/data/VisDrone.yaml | ||
19 | +yolov5/data/argoverse_hd.yaml | ||
20 | +yolov5/data/coco.yaml | ||
21 | +yolov5/data/coco128.yaml | ||
22 | +yolov5/data/hyp.finetune.yaml | ||
23 | +yolov5/data/hyp.finetune_objects365.yaml | ||
24 | +yolov5/data/hyp.scratch.yaml | ||
25 | +yolov5/data/objects365.yaml | ||
26 | +yolov5/data/visdrone.yaml | ||
27 | +yolov5/data/voc.yaml | ||
28 | +yolov5/data/images/bus.jpg | ||
29 | +yolov5/data/images/zidane.jpg | ||
30 | +yolov5/data/scripts/get_argoverse_hd.sh | ||
31 | +yolov5/data/scripts/get_coco.sh | ||
32 | +yolov5/data/scripts/get_coco128.sh | ||
33 | +yolov5/data/scripts/get_voc.sh | ||
34 | +yolov5/models/__init__.py | ||
35 | +yolov5/models/common.py | ||
36 | +yolov5/models/experimental.py | ||
37 | +yolov5/models/export.py | ||
38 | +yolov5/models/yolo.py | ||
39 | +yolov5/models/yolov5l.yaml | ||
40 | +yolov5/models/yolov5m.yaml | ||
41 | +yolov5/models/yolov5s.yaml | ||
42 | +yolov5/models/yolov5x.yaml | ||
43 | +yolov5/models/hub/anchors.yaml | ||
44 | +yolov5/models/hub/yolov3-spp.yaml | ||
45 | +yolov5/models/hub/yolov3-tiny.yaml | ||
46 | +yolov5/models/hub/yolov3.yaml | ||
47 | +yolov5/models/hub/yolov5-fpn.yaml | ||
48 | +yolov5/models/hub/yolov5-p2.yaml | ||
49 | +yolov5/models/hub/yolov5-p6.yaml | ||
50 | +yolov5/models/hub/yolov5-p7.yaml | ||
51 | +yolov5/models/hub/yolov5-panet.yaml | ||
52 | +yolov5/models/hub/yolov5l6.yaml | ||
53 | +yolov5/models/hub/yolov5m6.yaml | ||
54 | +yolov5/models/hub/yolov5s-transformer.yaml | ||
55 | +yolov5/models/hub/yolov5s6.yaml | ||
56 | +yolov5/models/hub/yolov5x6.yaml | ||
57 | +yolov5/utils/__init__.py | ||
58 | +yolov5/utils/activations.py | ||
59 | +yolov5/utils/autoanchor.py | ||
60 | +yolov5/utils/datasets.py | ||
61 | +yolov5/utils/general.py | ||
62 | +yolov5/utils/google_utils.py | ||
63 | +yolov5/utils/loss.py | ||
64 | +yolov5/utils/metrics.py | ||
65 | +yolov5/utils/plots.py | ||
66 | +yolov5/utils/torch_utils.py | ||
67 | +yolov5/utils/aws/__init__.py | ||
68 | +yolov5/utils/aws/resume.py | ||
69 | +yolov5/utils/neptuneai_logging/__init__.py | ||
70 | +yolov5/utils/neptuneai_logging/neptuneai_utils.py | ||
71 | +yolov5/utils/wandb_logging/__init__.py | ||
72 | +yolov5/utils/wandb_logging/log_dataset.py | ||
73 | +yolov5/utils/wandb_logging/wandb_utils.py | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +yolov5 |
No preview for this file type
No preview for this file type
No preview for this file type
1 | +# Global Wheat 2020 dataset http://www.global-wheat.com/ | ||
2 | +# Train command: python train.py --data GlobalWheat2020.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /datasets/GlobalWheat2020 | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | + | ||
9 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
10 | +train: # 3422 images | ||
11 | + - ../datasets/GlobalWheat2020/images/arvalis_1 | ||
12 | + - ../datasets/GlobalWheat2020/images/arvalis_2 | ||
13 | + - ../datasets/GlobalWheat2020/images/arvalis_3 | ||
14 | + - ../datasets/GlobalWheat2020/images/ethz_1 | ||
15 | + - ../datasets/GlobalWheat2020/images/rres_1 | ||
16 | + - ../datasets/GlobalWheat2020/images/inrae_1 | ||
17 | + - ../datasets/GlobalWheat2020/images/usask_1 | ||
18 | + | ||
19 | +val: # 748 images (WARNING: train set contains ethz_1) | ||
20 | + - ../datasets/GlobalWheat2020/images/ethz_1 | ||
21 | + | ||
22 | +test: # 1276 images | ||
23 | + - ../datasets/GlobalWheat2020/images/utokyo_1 | ||
24 | + - ../datasets/GlobalWheat2020/images/utokyo_2 | ||
25 | + - ../datasets/GlobalWheat2020/images/nau_1 | ||
26 | + - ../datasets/GlobalWheat2020/images/uq_1 | ||
27 | + | ||
28 | +# number of classes | ||
29 | +nc: 1 | ||
30 | + | ||
31 | +# class names | ||
32 | +names: [ 'wheat_head' ] | ||
33 | + | ||
34 | + | ||
35 | +# download command/URL (optional) -------------------------------------------------------------------------------------- | ||
36 | +download: | | ||
37 | + from utils.general import download, Path | ||
38 | + | ||
39 | + # Download | ||
40 | + dir = Path('../datasets/GlobalWheat2020') # dataset directory | ||
41 | + urls = ['https://zenodo.org/record/4298502/files/global-wheat-codalab-official.zip', | ||
42 | + 'https://github.com/ultralytics/yolov5/releases/download/v1.0/GlobalWheat2020_labels.zip'] | ||
43 | + download(urls, dir=dir) | ||
44 | + | ||
45 | + # Make Directories | ||
46 | + for p in 'annotations', 'images', 'labels': | ||
47 | + (dir / p).mkdir(parents=True, exist_ok=True) | ||
48 | + | ||
49 | + # Move | ||
50 | + for p in 'arvalis_1', 'arvalis_2', 'arvalis_3', 'ethz_1', 'rres_1', 'inrae_1', 'usask_1', \ | ||
51 | + 'utokyo_1', 'utokyo_2', 'nau_1', 'uq_1': | ||
52 | + (dir / p).rename(dir / 'images' / p) # move to /images | ||
53 | + f = (dir / p).with_suffix('.json') # json file | ||
54 | + if f.exists(): | ||
55 | + f.rename((dir / 'annotations' / p).with_suffix('.json')) # move to /annotations |
1 | +# Argoverse-HD dataset (ring-front-center camera) http://www.cs.cmu.edu/~mengtial/proj/streaming/ | ||
2 | +# Train command: python train.py --data argoverse_hd.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /argoverse | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | + | ||
9 | +# download command/URL (optional) | ||
10 | +download: bash data/scripts/get_argoverse_hd.sh | ||
11 | + | ||
12 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
13 | +train: ../argoverse/Argoverse-1.1/images/train/ # 39384 images | ||
14 | +val: ../argoverse/Argoverse-1.1/images/val/ # 15062 iamges | ||
15 | +test: ../argoverse/Argoverse-1.1/images/test/ # Submit to: https://eval.ai/web/challenges/challenge-page/800/overview | ||
16 | + | ||
17 | +# number of classes | ||
18 | +nc: 8 | ||
19 | + | ||
20 | +# class names | ||
21 | +names: [ 'person', 'bicycle', 'car', 'motorcycle', 'bus', 'truck', 'traffic_light', 'stop_sign' ] |
1 | +# COCO 2017 dataset http://cocodataset.org | ||
2 | +# Train command: python train.py --data coco.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /coco | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | + | ||
9 | +# download command/URL (optional) | ||
10 | +download: bash data/scripts/get_coco.sh | ||
11 | + | ||
12 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
13 | +train: ../coco/train2017.txt # 118287 images | ||
14 | +val: ../coco/val2017.txt # 5000 images | ||
15 | +test: ../coco/test-dev2017.txt # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794 | ||
16 | + | ||
17 | +# number of classes | ||
18 | +nc: 80 | ||
19 | + | ||
20 | +# class names | ||
21 | +names: [ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', | ||
22 | + 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', | ||
23 | + 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', | ||
24 | + 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', | ||
25 | + 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', | ||
26 | + 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', | ||
27 | + 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', | ||
28 | + 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', | ||
29 | + 'hair drier', 'toothbrush' ] | ||
30 | + | ||
31 | +# Print classes | ||
32 | +# with open('data/coco.yaml') as f: | ||
33 | +# d = yaml.safe_load(f) # dict | ||
34 | +# for i, x in enumerate(d['names']): | ||
35 | +# print(i, x) |
1 | +# COCO 2017 dataset http://cocodataset.org - first 128 training images | ||
2 | +# Train command: python train.py --data coco128.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /coco128 | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | + | ||
9 | +# download command/URL (optional) | ||
10 | +download: https://github.com/ultralytics/yolov5/releases/download/v1.0/coco128.zip | ||
11 | + | ||
12 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
13 | +train: ../coco128/images/train2017/ # 128 images | ||
14 | +val: ../coco128/images/train2017/ # 128 images | ||
15 | + | ||
16 | +# number of classes | ||
17 | +nc: 80 | ||
18 | + | ||
19 | +# class names | ||
20 | +names: [ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', | ||
21 | + 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', | ||
22 | + 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', | ||
23 | + 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', | ||
24 | + 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', | ||
25 | + 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', | ||
26 | + 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', | ||
27 | + 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', | ||
28 | + 'hair drier', 'toothbrush' ] |
1 | +# Hyperparameters for VOC finetuning | ||
2 | +# python train.py --batch 64 --weights yolov5m.pt --data voc.yaml --img 512 --epochs 50 | ||
3 | +# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials | ||
4 | + | ||
5 | + | ||
6 | +# Hyperparameter Evolution Results | ||
7 | +# Generations: 306 | ||
8 | +# P R mAP.5 mAP.5:.95 box obj cls | ||
9 | +# Metrics: 0.6 0.936 0.896 0.684 0.0115 0.00805 0.00146 | ||
10 | + | ||
11 | +lr0: 0.0032 | ||
12 | +lrf: 0.12 | ||
13 | +momentum: 0.843 | ||
14 | +weight_decay: 0.00036 | ||
15 | +warmup_epochs: 2.0 | ||
16 | +warmup_momentum: 0.5 | ||
17 | +warmup_bias_lr: 0.05 | ||
18 | +box: 0.0296 | ||
19 | +cls: 0.243 | ||
20 | +cls_pw: 0.631 | ||
21 | +obj: 0.301 | ||
22 | +obj_pw: 0.911 | ||
23 | +iou_t: 0.2 | ||
24 | +anchor_t: 2.91 | ||
25 | +# anchors: 3.63 | ||
26 | +fl_gamma: 0.0 | ||
27 | +hsv_h: 0.0138 | ||
28 | +hsv_s: 0.664 | ||
29 | +hsv_v: 0.464 | ||
30 | +degrees: 0.373 | ||
31 | +translate: 0.245 | ||
32 | +scale: 0.898 | ||
33 | +shear: 0.602 | ||
34 | +perspective: 0.0 | ||
35 | +flipud: 0.00856 | ||
36 | +fliplr: 0.5 | ||
37 | +mosaic: 1.0 | ||
38 | +mixup: 0.243 |
1 | +lr0: 0.00258 | ||
2 | +lrf: 0.17 | ||
3 | +momentum: 0.779 | ||
4 | +weight_decay: 0.00058 | ||
5 | +warmup_epochs: 1.33 | ||
6 | +warmup_momentum: 0.86 | ||
7 | +warmup_bias_lr: 0.0711 | ||
8 | +box: 0.0539 | ||
9 | +cls: 0.299 | ||
10 | +cls_pw: 0.825 | ||
11 | +obj: 0.632 | ||
12 | +obj_pw: 1.0 | ||
13 | +iou_t: 0.2 | ||
14 | +anchor_t: 3.44 | ||
15 | +anchors: 3.2 | ||
16 | +fl_gamma: 0.0 | ||
17 | +hsv_h: 0.0188 | ||
18 | +hsv_s: 0.704 | ||
19 | +hsv_v: 0.36 | ||
20 | +degrees: 0.0 | ||
21 | +translate: 0.0902 | ||
22 | +scale: 0.491 | ||
23 | +shear: 0.0 | ||
24 | +perspective: 0.0 | ||
25 | +flipud: 0.0 | ||
26 | +fliplr: 0.5 | ||
27 | +mosaic: 1.0 | ||
28 | +mixup: 0.0 |
1 | +# Hyperparameters for COCO training from scratch | ||
2 | +# python train.py --batch 40 --cfg yolov5m.yaml --weights '' --data coco.yaml --img 640 --epochs 300 | ||
3 | +# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials | ||
4 | + | ||
5 | + | ||
6 | +lr0: 0.01 # initial learning rate (SGD=1E-2, Adam=1E-3) | ||
7 | +lrf: 0.2 # final OneCycleLR learning rate (lr0 * lrf) | ||
8 | +momentum: 0.937 # SGD momentum/Adam beta1 | ||
9 | +weight_decay: 0.0005 # optimizer weight decay 5e-4 | ||
10 | +warmup_epochs: 3.0 # warmup epochs (fractions ok) | ||
11 | +warmup_momentum: 0.8 # warmup initial momentum | ||
12 | +warmup_bias_lr: 0.1 # warmup initial bias lr | ||
13 | +box: 0.05 # box loss gain | ||
14 | +cls: 0.5 # cls loss gain | ||
15 | +cls_pw: 1.0 # cls BCELoss positive_weight | ||
16 | +obj: 1.0 # obj loss gain (scale with pixels) | ||
17 | +obj_pw: 1.0 # obj BCELoss positive_weight | ||
18 | +iou_t: 0.20 # IoU training threshold | ||
19 | +anchor_t: 4.0 # anchor-multiple threshold | ||
20 | +# anchors: 3 # anchors per output layer (0 to ignore) | ||
21 | +fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5) | ||
22 | +hsv_h: 0.015 # image HSV-Hue augmentation (fraction) | ||
23 | +hsv_s: 0.7 # image HSV-Saturation augmentation (fraction) | ||
24 | +hsv_v: 0.4 # image HSV-Value augmentation (fraction) | ||
25 | +degrees: 0.0 # image rotation (+/- deg) | ||
26 | +translate: 0.1 # image translation (+/- fraction) | ||
27 | +scale: 0.5 # image scale (+/- gain) | ||
28 | +shear: 0.0 # image shear (+/- deg) | ||
29 | +perspective: 0.0 # image perspective (+/- fraction), range 0-0.001 | ||
30 | +flipud: 0.0 # image flip up-down (probability) | ||
31 | +fliplr: 0.5 # image flip left-right (probability) | ||
32 | +mosaic: 1.0 # image mosaic (probability) | ||
33 | +mixup: 0.0 # image mixup (probability) |
476 KB
165 KB
1 | +# Objects365 dataset https://www.objects365.org/ | ||
2 | +# Train command: python train.py --data objects365.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /datasets/objects365 | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
9 | +train: ../datasets/objects365/images/train # 1742289 images | ||
10 | +val: ../datasets/objects365/images/val # 5570 images | ||
11 | + | ||
12 | +# number of classes | ||
13 | +nc: 365 | ||
14 | + | ||
15 | +# class names | ||
16 | +names: [ 'Person', 'Sneakers', 'Chair', 'Other Shoes', 'Hat', 'Car', 'Lamp', 'Glasses', 'Bottle', 'Desk', 'Cup', | ||
17 | + 'Street Lights', 'Cabinet/shelf', 'Handbag/Satchel', 'Bracelet', 'Plate', 'Picture/Frame', 'Helmet', 'Book', | ||
18 | + 'Gloves', 'Storage box', 'Boat', 'Leather Shoes', 'Flower', 'Bench', 'Potted Plant', 'Bowl/Basin', 'Flag', | ||
19 | + 'Pillow', 'Boots', 'Vase', 'Microphone', 'Necklace', 'Ring', 'SUV', 'Wine Glass', 'Belt', 'Monitor/TV', | ||
20 | + 'Backpack', 'Umbrella', 'Traffic Light', 'Speaker', 'Watch', 'Tie', 'Trash bin Can', 'Slippers', 'Bicycle', | ||
21 | + 'Stool', 'Barrel/bucket', 'Van', 'Couch', 'Sandals', 'Basket', 'Drum', 'Pen/Pencil', 'Bus', 'Wild Bird', | ||
22 | + 'High Heels', 'Motorcycle', 'Guitar', 'Carpet', 'Cell Phone', 'Bread', 'Camera', 'Canned', 'Truck', | ||
23 | + 'Traffic cone', 'Cymbal', 'Lifesaver', 'Towel', 'Stuffed Toy', 'Candle', 'Sailboat', 'Laptop', 'Awning', | ||
24 | + 'Bed', 'Faucet', 'Tent', 'Horse', 'Mirror', 'Power outlet', 'Sink', 'Apple', 'Air Conditioner', 'Knife', | ||
25 | + 'Hockey Stick', 'Paddle', 'Pickup Truck', 'Fork', 'Traffic Sign', 'Balloon', 'Tripod', 'Dog', 'Spoon', 'Clock', | ||
26 | + 'Pot', 'Cow', 'Cake', 'Dinning Table', 'Sheep', 'Hanger', 'Blackboard/Whiteboard', 'Napkin', 'Other Fish', | ||
27 | + 'Orange/Tangerine', 'Toiletry', 'Keyboard', 'Tomato', 'Lantern', 'Machinery Vehicle', 'Fan', | ||
28 | + 'Green Vegetables', 'Banana', 'Baseball Glove', 'Airplane', 'Mouse', 'Train', 'Pumpkin', 'Soccer', 'Skiboard', | ||
29 | + 'Luggage', 'Nightstand', 'Tea pot', 'Telephone', 'Trolley', 'Head Phone', 'Sports Car', 'Stop Sign', | ||
30 | + 'Dessert', 'Scooter', 'Stroller', 'Crane', 'Remote', 'Refrigerator', 'Oven', 'Lemon', 'Duck', 'Baseball Bat', | ||
31 | + 'Surveillance Camera', 'Cat', 'Jug', 'Broccoli', 'Piano', 'Pizza', 'Elephant', 'Skateboard', 'Surfboard', | ||
32 | + 'Gun', 'Skating and Skiing shoes', 'Gas stove', 'Donut', 'Bow Tie', 'Carrot', 'Toilet', 'Kite', 'Strawberry', | ||
33 | + 'Other Balls', 'Shovel', 'Pepper', 'Computer Box', 'Toilet Paper', 'Cleaning Products', 'Chopsticks', | ||
34 | + 'Microwave', 'Pigeon', 'Baseball', 'Cutting/chopping Board', 'Coffee Table', 'Side Table', 'Scissors', | ||
35 | + 'Marker', 'Pie', 'Ladder', 'Snowboard', 'Cookies', 'Radiator', 'Fire Hydrant', 'Basketball', 'Zebra', 'Grape', | ||
36 | + 'Giraffe', 'Potato', 'Sausage', 'Tricycle', 'Violin', 'Egg', 'Fire Extinguisher', 'Candy', 'Fire Truck', | ||
37 | + 'Billiards', 'Converter', 'Bathtub', 'Wheelchair', 'Golf Club', 'Briefcase', 'Cucumber', 'Cigar/Cigarette', | ||
38 | + 'Paint Brush', 'Pear', 'Heavy Truck', 'Hamburger', 'Extractor', 'Extension Cord', 'Tong', 'Tennis Racket', | ||
39 | + 'Folder', 'American Football', 'earphone', 'Mask', 'Kettle', 'Tennis', 'Ship', 'Swing', 'Coffee Machine', | ||
40 | + 'Slide', 'Carriage', 'Onion', 'Green beans', 'Projector', 'Frisbee', 'Washing Machine/Drying Machine', | ||
41 | + 'Chicken', 'Printer', 'Watermelon', 'Saxophone', 'Tissue', 'Toothbrush', 'Ice cream', 'Hot-air balloon', | ||
42 | + 'Cello', 'French Fries', 'Scale', 'Trophy', 'Cabbage', 'Hot dog', 'Blender', 'Peach', 'Rice', 'Wallet/Purse', | ||
43 | + 'Volleyball', 'Deer', 'Goose', 'Tape', 'Tablet', 'Cosmetics', 'Trumpet', 'Pineapple', 'Golf Ball', | ||
44 | + 'Ambulance', 'Parking meter', 'Mango', 'Key', 'Hurdle', 'Fishing Rod', 'Medal', 'Flute', 'Brush', 'Penguin', | ||
45 | + 'Megaphone', 'Corn', 'Lettuce', 'Garlic', 'Swan', 'Helicopter', 'Green Onion', 'Sandwich', 'Nuts', | ||
46 | + 'Speed Limit Sign', 'Induction Cooker', 'Broom', 'Trombone', 'Plum', 'Rickshaw', 'Goldfish', 'Kiwi fruit', | ||
47 | + 'Router/modem', 'Poker Card', 'Toaster', 'Shrimp', 'Sushi', 'Cheese', 'Notepaper', 'Cherry', 'Pliers', 'CD', | ||
48 | + 'Pasta', 'Hammer', 'Cue', 'Avocado', 'Hamimelon', 'Flask', 'Mushroom', 'Screwdriver', 'Soap', 'Recorder', | ||
49 | + 'Bear', 'Eggplant', 'Board Eraser', 'Coconut', 'Tape Measure/Ruler', 'Pig', 'Showerhead', 'Globe', 'Chips', | ||
50 | + 'Steak', 'Crosswalk Sign', 'Stapler', 'Camel', 'Formula 1', 'Pomegranate', 'Dishwasher', 'Crab', | ||
51 | + 'Hoverboard', 'Meat ball', 'Rice Cooker', 'Tuba', 'Calculator', 'Papaya', 'Antelope', 'Parrot', 'Seal', | ||
52 | + 'Butterfly', 'Dumbbell', 'Donkey', 'Lion', 'Urinal', 'Dolphin', 'Electric Drill', 'Hair Dryer', 'Egg tart', | ||
53 | + 'Jellyfish', 'Treadmill', 'Lighter', 'Grapefruit', 'Game board', 'Mop', 'Radish', 'Baozi', 'Target', 'French', | ||
54 | + 'Spring Rolls', 'Monkey', 'Rabbit', 'Pencil Case', 'Yak', 'Red Cabbage', 'Binoculars', 'Asparagus', 'Barbell', | ||
55 | + 'Scallop', 'Noddles', 'Comb', 'Dumpling', 'Oyster', 'Table Tennis paddle', 'Cosmetics Brush/Eyeliner Pencil', | ||
56 | + 'Chainsaw', 'Eraser', 'Lobster', 'Durian', 'Okra', 'Lipstick', 'Cosmetics Mirror', 'Curling', 'Table Tennis' ] | ||
57 | + | ||
58 | + | ||
59 | +# download command/URL (optional) -------------------------------------------------------------------------------------- | ||
60 | +download: | | ||
61 | + from pycocotools.coco import COCO | ||
62 | + from tqdm import tqdm | ||
63 | + | ||
64 | + from utils.general import download, Path | ||
65 | + | ||
66 | + # Make Directories | ||
67 | + dir = Path('../datasets/objects365') # dataset directory | ||
68 | + for p in 'images', 'labels': | ||
69 | + (dir / p).mkdir(parents=True, exist_ok=True) | ||
70 | + for q in 'train', 'val': | ||
71 | + (dir / p / q).mkdir(parents=True, exist_ok=True) | ||
72 | + | ||
73 | + # Download | ||
74 | + url = "https://dorc.ks3-cn-beijing.ksyun.com/data-set/2020Objects365%E6%95%B0%E6%8D%AE%E9%9B%86/train/" | ||
75 | + download([url + 'zhiyuan_objv2_train.tar.gz'], dir=dir, delete=False) # annotations json | ||
76 | + download([url + f for f in [f'patch{i}.tar.gz' for i in range(51)]], dir=dir / 'images' / 'train', | ||
77 | + curl=True, delete=False, threads=8) | ||
78 | + | ||
79 | + # Move | ||
80 | + train = dir / 'images' / 'train' | ||
81 | + for f in tqdm(train.rglob('*.jpg'), desc=f'Moving images'): | ||
82 | + f.rename(train / f.name) # move to /images/train | ||
83 | + | ||
84 | + # Labels | ||
85 | + coco = COCO(dir / 'zhiyuan_objv2_train.json') | ||
86 | + names = [x["name"] for x in coco.loadCats(coco.getCatIds())] | ||
87 | + for cid, cat in enumerate(names): | ||
88 | + catIds = coco.getCatIds(catNms=[cat]) | ||
89 | + imgIds = coco.getImgIds(catIds=catIds) | ||
90 | + for im in tqdm(coco.loadImgs(imgIds), desc=f'Class {cid + 1}/{len(names)} {cat}'): | ||
91 | + width, height = im["width"], im["height"] | ||
92 | + path = Path(im["file_name"]) # image filename | ||
93 | + try: | ||
94 | + with open(dir / 'labels' / 'train' / path.with_suffix('.txt').name, 'a') as file: | ||
95 | + annIds = coco.getAnnIds(imgIds=im["id"], catIds=catIds, iscrowd=None) | ||
96 | + for a in coco.loadAnns(annIds): | ||
97 | + x, y, w, h = a['bbox'] # bounding box in xywh (xy top-left corner) | ||
98 | + x, y = x + w / 2, y + h / 2 # xy to center | ||
99 | + file.write(f"{cid} {x / width:.5f} {y / height:.5f} {w / width:.5f} {h / height:.5f}\n") | ||
100 | + | ||
101 | + except Exception as e: | ||
102 | + print(e) |
1 | +#!/bin/bash | ||
2 | +# Argoverse-HD dataset (ring-front-center camera) http://www.cs.cmu.edu/~mengtial/proj/streaming/ | ||
3 | +# Download command: bash data/scripts/get_argoverse_hd.sh | ||
4 | +# Train command: python train.py --data argoverse_hd.yaml | ||
5 | +# Default dataset location is next to YOLOv5: | ||
6 | +# /parent_folder | ||
7 | +# /argoverse | ||
8 | +# /yolov5 | ||
9 | + | ||
10 | +# Download/unzip images | ||
11 | +d='../argoverse/' # unzip directory | ||
12 | +mkdir $d | ||
13 | +url=https://argoverse-hd.s3.us-east-2.amazonaws.com/ | ||
14 | +f=Argoverse-HD-Full.zip | ||
15 | +curl -L $url$f -o $f && unzip -q $f -d $d && rm $f &# download, unzip, remove in background | ||
16 | +wait # finish background tasks | ||
17 | + | ||
18 | +cd ../argoverse/Argoverse-1.1/ | ||
19 | +ln -s tracking images | ||
20 | + | ||
21 | +cd ../Argoverse-HD/annotations/ | ||
22 | + | ||
23 | +python3 - "$@" <<END | ||
24 | +import json | ||
25 | +from pathlib import Path | ||
26 | + | ||
27 | +annotation_files = ["train.json", "val.json"] | ||
28 | +print("Converting annotations to YOLOv5 format...") | ||
29 | + | ||
30 | +for val in annotation_files: | ||
31 | + a = json.load(open(val, "rb")) | ||
32 | + | ||
33 | + label_dict = {} | ||
34 | + for annot in a['annotations']: | ||
35 | + img_id = annot['image_id'] | ||
36 | + img_name = a['images'][img_id]['name'] | ||
37 | + img_label_name = img_name[:-3] + "txt" | ||
38 | + | ||
39 | + cls = annot['category_id'] # instance class id | ||
40 | + x_center, y_center, width, height = annot['bbox'] | ||
41 | + x_center = (x_center + width / 2) / 1920. # offset and scale | ||
42 | + y_center = (y_center + height / 2) / 1200. # offset and scale | ||
43 | + width /= 1920. # scale | ||
44 | + height /= 1200. # scale | ||
45 | + | ||
46 | + img_dir = "./labels/" + a['seq_dirs'][a['images'][annot['image_id']]['sid']] | ||
47 | + | ||
48 | + Path(img_dir).mkdir(parents=True, exist_ok=True) | ||
49 | + if img_dir + "/" + img_label_name not in label_dict: | ||
50 | + label_dict[img_dir + "/" + img_label_name] = [] | ||
51 | + | ||
52 | + label_dict[img_dir + "/" + img_label_name].append(f"{cls} {x_center} {y_center} {width} {height}\n") | ||
53 | + | ||
54 | + for filename in label_dict: | ||
55 | + with open(filename, "w") as file: | ||
56 | + for string in label_dict[filename]: | ||
57 | + file.write(string) | ||
58 | + | ||
59 | +END | ||
60 | + | ||
61 | +mv ./labels ../../Argoverse-1.1/ |
1 | +#!/bin/bash | ||
2 | +# COCO 2017 dataset http://cocodataset.org | ||
3 | +# Download command: bash data/scripts/get_coco.sh | ||
4 | +# Train command: python train.py --data coco.yaml | ||
5 | +# Default dataset location is next to YOLOv5: | ||
6 | +# /parent_folder | ||
7 | +# /coco | ||
8 | +# /yolov5 | ||
9 | + | ||
10 | +# Download/unzip labels | ||
11 | +d='../' # unzip directory | ||
12 | +url=https://github.com/ultralytics/yolov5/releases/download/v1.0/ | ||
13 | +f='coco2017labels.zip' # or 'coco2017labels-segments.zip', 68 MB | ||
14 | +echo 'Downloading' $url$f ' ...' | ||
15 | +curl -L $url$f -o $f && unzip -q $f -d $d && rm $f & # download, unzip, remove in background | ||
16 | + | ||
17 | +# Download/unzip images | ||
18 | +d='../coco/images' # unzip directory | ||
19 | +url=http://images.cocodataset.org/zips/ | ||
20 | +f1='train2017.zip' # 19G, 118k images | ||
21 | +f2='val2017.zip' # 1G, 5k images | ||
22 | +f3='test2017.zip' # 7G, 41k images (optional) | ||
23 | +for f in $f1 $f2; do | ||
24 | + echo 'Downloading' $url$f '...' | ||
25 | + curl -L $url$f -o $f && unzip -q $f -d $d && rm $f & # download, unzip, remove in background | ||
26 | +done | ||
27 | +wait # finish background tasks |
1 | +#!/bin/bash | ||
2 | +# COCO128 dataset https://www.kaggle.com/ultralytics/coco128 | ||
3 | +# Download command: bash data/scripts/get_coco128.sh | ||
4 | +# Train command: python train.py --data coco128.yaml | ||
5 | +# Default dataset location is next to /yolov5: | ||
6 | +# /parent_folder | ||
7 | +# /coco128 | ||
8 | +# /yolov5 | ||
9 | + | ||
10 | +# Download/unzip images and labels | ||
11 | +d='../' # unzip directory | ||
12 | +url=https://github.com/ultralytics/yolov5/releases/download/v1.0/ | ||
13 | +f='coco128.zip' # or 'coco2017labels-segments.zip', 68 MB | ||
14 | +echo 'Downloading' $url$f ' ...' | ||
15 | +curl -L $url$f -o $f && unzip -q $f -d $d && rm $f & # download, unzip, remove in background | ||
16 | + | ||
17 | +wait # finish background tasks |
1 | +#!/bin/bash | ||
2 | +# PASCAL VOC dataset http://host.robots.ox.ac.uk/pascal/VOC/ | ||
3 | +# Download command: bash data/scripts/get_voc.sh | ||
4 | +# Train command: python train.py --data voc.yaml | ||
5 | +# Default dataset location is next to YOLOv5: | ||
6 | +# /parent_folder | ||
7 | +# /VOC | ||
8 | +# /yolov5 | ||
9 | + | ||
10 | +start=$(date +%s) | ||
11 | +mkdir -p ../tmp | ||
12 | +cd ../tmp/ | ||
13 | + | ||
14 | +# Download/unzip images and labels | ||
15 | +d='.' # unzip directory | ||
16 | +url=https://github.com/ultralytics/yolov5/releases/download/v1.0/ | ||
17 | +f1=VOCtrainval_06-Nov-2007.zip # 446MB, 5012 images | ||
18 | +f2=VOCtest_06-Nov-2007.zip # 438MB, 4953 images | ||
19 | +f3=VOCtrainval_11-May-2012.zip # 1.95GB, 17126 images | ||
20 | +for f in $f3 $f2 $f1; do | ||
21 | + echo 'Downloading' $url$f '...' | ||
22 | + curl -L $url$f -o $f && unzip -q $f -d $d && rm $f & # download, unzip, remove in background | ||
23 | +done | ||
24 | +wait # finish background tasks | ||
25 | + | ||
26 | +end=$(date +%s) | ||
27 | +runtime=$((end - start)) | ||
28 | +echo "Completed in" $runtime "seconds" | ||
29 | + | ||
30 | +echo "Splitting dataset..." | ||
31 | +python3 - "$@" <<END | ||
32 | +import os | ||
33 | +import xml.etree.ElementTree as ET | ||
34 | +from os import getcwd | ||
35 | + | ||
36 | +sets = [('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')] | ||
37 | + | ||
38 | +classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", | ||
39 | + "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] | ||
40 | + | ||
41 | + | ||
42 | +def convert_box(size, box): | ||
43 | + dw = 1. / (size[0]) | ||
44 | + dh = 1. / (size[1]) | ||
45 | + x, y, w, h = (box[0] + box[1]) / 2.0 - 1, (box[2] + box[3]) / 2.0 - 1, box[1] - box[0], box[3] - box[2] | ||
46 | + return x * dw, y * dh, w * dw, h * dh | ||
47 | + | ||
48 | + | ||
49 | +def convert_annotation(year, image_id): | ||
50 | + in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml' % (year, image_id)) | ||
51 | + out_file = open('VOCdevkit/VOC%s/labels/%s.txt' % (year, image_id), 'w') | ||
52 | + tree = ET.parse(in_file) | ||
53 | + root = tree.getroot() | ||
54 | + size = root.find('size') | ||
55 | + w = int(size.find('width').text) | ||
56 | + h = int(size.find('height').text) | ||
57 | + | ||
58 | + for obj in root.iter('object'): | ||
59 | + difficult = obj.find('difficult').text | ||
60 | + cls = obj.find('name').text | ||
61 | + if cls not in classes or int(difficult) == 1: | ||
62 | + continue | ||
63 | + cls_id = classes.index(cls) | ||
64 | + xmlbox = obj.find('bndbox') | ||
65 | + b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), | ||
66 | + float(xmlbox.find('ymax').text)) | ||
67 | + bb = convert_box((w, h), b) | ||
68 | + out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') | ||
69 | + | ||
70 | + | ||
71 | +cwd = getcwd() | ||
72 | +for year, image_set in sets: | ||
73 | + if not os.path.exists('VOCdevkit/VOC%s/labels/' % year): | ||
74 | + os.makedirs('VOCdevkit/VOC%s/labels/' % year) | ||
75 | + image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt' % (year, image_set)).read().strip().split() | ||
76 | + list_file = open('%s_%s.txt' % (year, image_set), 'w') | ||
77 | + for image_id in image_ids: | ||
78 | + list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n' % (cwd, year, image_id)) | ||
79 | + convert_annotation(year, image_id) | ||
80 | + list_file.close() | ||
81 | +END | ||
82 | + | ||
83 | +cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt >train.txt | ||
84 | +cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt >train.all.txt | ||
85 | + | ||
86 | +mkdir ../VOC ../VOC/images ../VOC/images/train ../VOC/images/val | ||
87 | +mkdir ../VOC/labels ../VOC/labels/train ../VOC/labels/val | ||
88 | + | ||
89 | +python3 - "$@" <<END | ||
90 | +import os | ||
91 | + | ||
92 | +print(os.path.exists('../tmp/train.txt')) | ||
93 | +with open('../tmp/train.txt', 'r') as f: | ||
94 | + for line in f.readlines(): | ||
95 | + line = "/".join(line.split('/')[-5:]).strip() | ||
96 | + if os.path.exists("../" + line): | ||
97 | + os.system("cp ../" + line + " ../VOC/images/train") | ||
98 | + | ||
99 | + line = line.replace('JPEGImages', 'labels').replace('jpg', 'txt') | ||
100 | + if os.path.exists("../" + line): | ||
101 | + os.system("cp ../" + line + " ../VOC/labels/train") | ||
102 | + | ||
103 | +print(os.path.exists('../tmp/2007_test.txt')) | ||
104 | +with open('../tmp/2007_test.txt', 'r') as f: | ||
105 | + for line in f.readlines(): | ||
106 | + line = "/".join(line.split('/')[-5:]).strip() | ||
107 | + if os.path.exists("../" + line): | ||
108 | + os.system("cp ../" + line + " ../VOC/images/val") | ||
109 | + | ||
110 | + line = line.replace('JPEGImages', 'labels').replace('jpg', 'txt') | ||
111 | + if os.path.exists("../" + line): | ||
112 | + os.system("cp ../" + line + " ../VOC/labels/val") | ||
113 | +END | ||
114 | + | ||
115 | +rm -rf ../tmp # remove temporary directory | ||
116 | +echo "VOC download done." |
1 | +# VisDrone2019-DET dataset https://github.com/VisDrone/VisDrone-Dataset | ||
2 | +# Train command: python train.py --data visdrone.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /VisDrone | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | + | ||
9 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
10 | +train: ../VisDrone/VisDrone2019-DET-train/images # 6471 images | ||
11 | +val: ../VisDrone/VisDrone2019-DET-val/images # 548 images | ||
12 | +test: ../VisDrone/VisDrone2019-DET-test-dev/images # 1610 images | ||
13 | + | ||
14 | +# number of classes | ||
15 | +nc: 10 | ||
16 | + | ||
17 | +# class names | ||
18 | +names: [ 'pedestrian', 'people', 'bicycle', 'car', 'van', 'truck', 'tricycle', 'awning-tricycle', 'bus', 'motor' ] | ||
19 | + | ||
20 | + | ||
21 | +# download command/URL (optional) -------------------------------------------------------------------------------------- | ||
22 | +download: | | ||
23 | + import os | ||
24 | + from pathlib import Path | ||
25 | + | ||
26 | + from utils.general import download | ||
27 | + | ||
28 | + | ||
29 | + def visdrone2yolo(dir): | ||
30 | + from PIL import Image | ||
31 | + from tqdm import tqdm | ||
32 | + | ||
33 | + def convert_box(size, box): | ||
34 | + # Convert VisDrone box to YOLO xywh box | ||
35 | + dw = 1. / size[0] | ||
36 | + dh = 1. / size[1] | ||
37 | + return (box[0] + box[2] / 2) * dw, (box[1] + box[3] / 2) * dh, box[2] * dw, box[3] * dh | ||
38 | + | ||
39 | + (dir / 'labels').mkdir(parents=True, exist_ok=True) # make labels directory | ||
40 | + pbar = tqdm((dir / 'annotations').glob('*.txt'), desc=f'Converting {dir}') | ||
41 | + for f in pbar: | ||
42 | + img_size = Image.open((dir / 'images' / f.name).with_suffix('.jpg')).size | ||
43 | + lines = [] | ||
44 | + with open(f, 'r') as file: # read annotation.txt | ||
45 | + for row in [x.split(',') for x in file.read().strip().splitlines()]: | ||
46 | + if row[4] == '0': # VisDrone 'ignored regions' class 0 | ||
47 | + continue | ||
48 | + cls = int(row[5]) - 1 | ||
49 | + box = convert_box(img_size, tuple(map(int, row[:4]))) | ||
50 | + lines.append(f"{cls} {' '.join(f'{x:.6f}' for x in box)}\n") | ||
51 | + with open(str(f).replace(os.sep + 'annotations' + os.sep, os.sep + 'labels' + os.sep), 'w') as fl: | ||
52 | + fl.writelines(lines) # write label.txt | ||
53 | + | ||
54 | + | ||
55 | + # Download | ||
56 | + dir = Path('../VisDrone') # dataset directory | ||
57 | + urls = ['https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-train.zip', | ||
58 | + 'https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-val.zip', | ||
59 | + 'https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-test-dev.zip', | ||
60 | + 'https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-test-challenge.zip'] | ||
61 | + download(urls, dir=dir) | ||
62 | + | ||
63 | + # Convert | ||
64 | + for d in 'VisDrone2019-DET-train', 'VisDrone2019-DET-val', 'VisDrone2019-DET-test-dev': | ||
65 | + visdrone2yolo(dir / d) # convert VisDrone annotations to YOLO labels |
1 | +# PASCAL VOC dataset http://host.robots.ox.ac.uk/pascal/VOC/ | ||
2 | +# Train command: python train.py --data voc.yaml | ||
3 | +# Default dataset location is next to YOLOv5: | ||
4 | +# /parent_folder | ||
5 | +# /VOC | ||
6 | +# /yolov5 | ||
7 | + | ||
8 | + | ||
9 | +# download command/URL (optional) | ||
10 | +download: bash data/scripts/get_voc.sh | ||
11 | + | ||
12 | +# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/] | ||
13 | +train: ../VOC/images/train/ # 16551 images | ||
14 | +val: ../VOC/images/val/ # 4952 images | ||
15 | + | ||
16 | +# number of classes | ||
17 | +nc: 20 | ||
18 | + | ||
19 | +# class names | ||
20 | +names: [ 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', | ||
21 | + 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor' ] |
code/yolo-RTMP/yolo_module/yolov5/detect.py
0 → 100644
This diff is collapsed. Click to expand it.
code/yolo-RTMP/yolo_module/yolov5/helpers.py
0 → 100644
1 | +from pathlib import Path | ||
2 | + | ||
3 | +from yolo_module.yolov5.models.yolo import Model | ||
4 | +from yolo_module.yolov5.utils.general import set_logging, yolov5_in_syspath | ||
5 | +from yolo_module.yolov5.utils.google_utils import attempt_download | ||
6 | +from yolo_module.yolov5.utils.torch_utils import torch | ||
7 | + | ||
8 | + | ||
9 | +def load_model(model_path, device=None, autoshape=True, verbose=False): | ||
10 | + """ | ||
11 | + Creates a specified YOLOv5 model | ||
12 | + | ||
13 | + Arguments: | ||
14 | + model_path (str): path of the model | ||
15 | + config_path (str): path of the config file | ||
16 | + device (str): select device that model will be loaded (cpu, cuda) | ||
17 | + pretrained (bool): load pretrained weights into the model | ||
18 | + autoshape (bool): make model ready for inference | ||
19 | + verbose (bool): if False, yolov5 logs will be silent | ||
20 | + | ||
21 | + Returns: | ||
22 | + pytorch model | ||
23 | + | ||
24 | + (Adapted from yolo_module.yolov5.hubconf.create) | ||
25 | + """ | ||
26 | + # set logging | ||
27 | + set_logging(verbose=verbose) | ||
28 | + | ||
29 | + # set device if not given | ||
30 | + if not device: | ||
31 | + device = "cuda:0" if torch.cuda.is_available() else "cpu" | ||
32 | + | ||
33 | + attempt_download(model_path) # download if not found locally | ||
34 | + with yolov5_in_syspath(): | ||
35 | + model = torch.load(model_path, map_location=torch.device(device)) | ||
36 | + if isinstance(model, dict): | ||
37 | + model = model["model"] # load model | ||
38 | + hub_model = Model(model.yaml).to(next(model.parameters()).device) # create | ||
39 | + hub_model.load_state_dict(model.float().state_dict()) # load state_dict | ||
40 | + hub_model.names = model.names # class names | ||
41 | + model = hub_model | ||
42 | + | ||
43 | + if autoshape: | ||
44 | + model = model.autoshape() | ||
45 | + | ||
46 | + return model | ||
47 | + | ||
48 | + | ||
49 | +class YOLOv5: | ||
50 | + def __init__(self, model_path, device=None, load_on_init=True): | ||
51 | + self.model_path = model_path | ||
52 | + self.device = device | ||
53 | + if load_on_init: | ||
54 | + Path(model_path).parents[0].mkdir(parents=True, exist_ok=True) | ||
55 | + self.model = load_model(model_path=model_path, device=device, autoshape=True) | ||
56 | + else: | ||
57 | + self.model = None | ||
58 | + | ||
59 | + def load_model(self): | ||
60 | + """ | ||
61 | + Load yolov5 weight. | ||
62 | + """ | ||
63 | + Path(self.model_path).parents[0].mkdir(parents=True, exist_ok=True) | ||
64 | + self.model = load_model(model_path=self.model_path, device=self.device, autoshape=True) | ||
65 | + | ||
66 | + def predict(self, image_list, size=640, augment=False): | ||
67 | + """ | ||
68 | + Perform yolov5 prediction using loaded model weights. | ||
69 | + | ||
70 | + Returns results as a yolov5.models.common.Detections object. | ||
71 | + """ | ||
72 | + assert self.model is not None, "before predict, you need to call .load_model()" | ||
73 | + results = self.model(imgs=image_list, size=size, augment=augment) | ||
74 | + return results | ||
75 | + | ||
76 | +if __name__ == "__main__": | ||
77 | + model_path = "yolov5/weights/yolov5s.pt" | ||
78 | + device = "cuda" | ||
79 | + model = load_model(model_path=model_path, config_path=None, device=device) | ||
80 | + | ||
81 | + from PIL import Image | ||
82 | + imgs = [Image.open(x) for x in Path("yolov5/data/images").glob("*.jpg")] | ||
83 | + results = model(imgs) |
code/yolo-RTMP/yolo_module/yolov5/hubconf.py
0 → 100644
1 | +"""YOLOv5 PyTorch Hub models https://pytorch.org/hub/ultralytics_yolov5/ | ||
2 | + | ||
3 | +Usage: | ||
4 | + import torch | ||
5 | + model = torch.hub.load('ultralytics/yolov5', 'yolov5s') | ||
6 | +""" | ||
7 | + | ||
8 | +from pathlib import Path | ||
9 | + | ||
10 | +import torch | ||
11 | + | ||
12 | +from yolo_module.yolov5.models.yolo import Model, attempt_load | ||
13 | +from yolo_module.yolov5.utils.general import (check_requirements, set_logging, | ||
14 | + yolov5_in_syspath) | ||
15 | +from yolo_module.yolov5.utils.google_utils import attempt_download | ||
16 | +from yolo_module.yolov5.utils.torch_utils import select_device | ||
17 | + | ||
18 | +dependencies = ['torch', 'yaml'] | ||
19 | +#check_requirements(Path(__file__).parent / 'requirements.txt', exclude=('tensorboard', 'pycocotools', 'thop')) | ||
20 | + | ||
21 | + | ||
22 | +def create(name, pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
23 | + """Creates a specified YOLOv5 model | ||
24 | + | ||
25 | + Arguments: | ||
26 | + name (str): name of model, i.e. 'yolov5s' | ||
27 | + pretrained (bool): load pretrained weights into the model | ||
28 | + channels (int): number of input channels | ||
29 | + classes (int): number of model classes | ||
30 | + autoshape (bool): apply YOLOv5 .autoshape() wrapper to model | ||
31 | + verbose (bool): print all information to screen | ||
32 | + | ||
33 | + Returns: | ||
34 | + YOLOv5 pytorch model | ||
35 | + """ | ||
36 | + set_logging(verbose=verbose) | ||
37 | + fname = Path(name).with_suffix('.pt') # checkpoint filename | ||
38 | + try: | ||
39 | + if pretrained and channels == 3 and classes == 80: | ||
40 | + model = attempt_load(fname, map_location=torch.device('cpu')) # download/load FP32 model | ||
41 | + else: | ||
42 | + cfg = list((Path(__file__).parent / 'models').rglob(f'{name}.yaml'))[0] # model.yaml path | ||
43 | + model = Model(cfg, channels, classes) # create model | ||
44 | + if pretrained: | ||
45 | + attempt_download(fname) # download if not found locally | ||
46 | + with yolov5_in_syspath(): | ||
47 | + ckpt = torch.load(fname, map_location=torch.device('cpu')) # load | ||
48 | + msd = model.state_dict() # model state_dict | ||
49 | + csd = ckpt['model'].float().state_dict() # checkpoint state_dict as FP32 | ||
50 | + csd = {k: v for k, v in csd.items() if msd[k].shape == v.shape} # filter | ||
51 | + model.load_state_dict(csd, strict=False) # load | ||
52 | + if len(ckpt['model'].names) == classes: | ||
53 | + model.names = ckpt['model'].names # set class names attribute | ||
54 | + if autoshape: | ||
55 | + model = model.autoshape() # for file/URI/PIL/cv2/np inputs and NMS | ||
56 | + device = select_device('0' if torch.cuda.is_available() else 'cpu') # default to GPU if available | ||
57 | + return model.to(device) | ||
58 | + | ||
59 | + except Exception as e: | ||
60 | + help_url = 'https://github.com/ultralytics/yolov5/issues/36' | ||
61 | + s = 'Cache may be out of date, try `force_reload=True`. See %s for help.' % help_url | ||
62 | + raise Exception(s) from e | ||
63 | + | ||
64 | + | ||
65 | +def custom(path='path/to/model.pt', autoshape=True, verbose=True): | ||
66 | + # YOLOv5 custom or local model | ||
67 | + return create(path, autoshape=autoshape, verbose=verbose) | ||
68 | + | ||
69 | + | ||
70 | +def yolov5s(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
71 | + # YOLOv5-small model https://github.com/ultralytics/yolov5 | ||
72 | + return create('yolov5s', pretrained, channels, classes, autoshape, verbose) | ||
73 | + | ||
74 | + | ||
75 | +def yolov5m(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
76 | + # YOLOv5-medium model https://github.com/ultralytics/yolov5 | ||
77 | + return create('yolov5m', pretrained, channels, classes, autoshape, verbose) | ||
78 | + | ||
79 | + | ||
80 | +def yolov5l(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
81 | + # YOLOv5-large model https://github.com/ultralytics/yolov5 | ||
82 | + return create('yolov5l', pretrained, channels, classes, autoshape, verbose) | ||
83 | + | ||
84 | + | ||
85 | +def yolov5x(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
86 | + # YOLOv5-xlarge model https://github.com/ultralytics/yolov5 | ||
87 | + return create('yolov5x', pretrained, channels, classes, autoshape, verbose) | ||
88 | + | ||
89 | + | ||
90 | +def yolov5s6(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
91 | + # YOLOv5-small-P6 model https://github.com/ultralytics/yolov5 | ||
92 | + return create('yolov5s6', pretrained, channels, classes, autoshape, verbose) | ||
93 | + | ||
94 | + | ||
95 | +def yolov5m6(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
96 | + # YOLOv5-medium-P6 model https://github.com/ultralytics/yolov5 | ||
97 | + return create('yolov5m6', pretrained, channels, classes, autoshape, verbose) | ||
98 | + | ||
99 | + | ||
100 | +def yolov5l6(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
101 | + # YOLOv5-large-P6 model https://github.com/ultralytics/yolov5 | ||
102 | + return create('yolov5l6', pretrained, channels, classes, autoshape, verbose) | ||
103 | + | ||
104 | + | ||
105 | +def yolov5x6(pretrained=True, channels=3, classes=80, autoshape=True, verbose=True): | ||
106 | + # YOLOv5-xlarge-P6 model https://github.com/ultralytics/yolov5 | ||
107 | + return create('yolov5x6', pretrained, channels, classes, autoshape, verbose) | ||
108 | + | ||
109 | + | ||
110 | +if __name__ == '__main__': | ||
111 | + model = create(name='yolov5s', pretrained=True, channels=3, classes=80, autoshape=True, verbose=True) # pretrained | ||
112 | + # model = custom(path='path/to/model.pt') # custom | ||
113 | + | ||
114 | + # Verify inference | ||
115 | + import cv2 | ||
116 | + import numpy as np | ||
117 | + from PIL import Image | ||
118 | + | ||
119 | + imgs = ['data/images/zidane.jpg', # filename | ||
120 | + 'https://github.com/ultralytics/yolov5/releases/download/v1.0/zidane.jpg', # URI | ||
121 | + cv2.imread('data/images/bus.jpg')[:, :, ::-1], # OpenCV | ||
122 | + Image.open('data/images/bus.jpg'), # PIL | ||
123 | + np.zeros((320, 640, 3))] # numpy | ||
124 | + | ||
125 | + results = model(imgs) # batched inference | ||
126 | + results.print() | ||
127 | + results.save() |
File mode changed
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
This diff is collapsed. Click to expand it.
1 | +# YOLOv5 experimental modules | ||
2 | + | ||
3 | +import sys | ||
4 | +from pathlib import Path | ||
5 | + | ||
6 | +import numpy as np | ||
7 | +import torch | ||
8 | +import torch.nn as nn | ||
9 | +from yolo_module.yolov5.models.common import Conv, DWConv | ||
10 | +from yolo_module.yolov5.utils.general import yolov5_in_syspath | ||
11 | +from yolo_module.yolov5.utils.google_utils import attempt_download | ||
12 | + | ||
13 | + | ||
14 | +class CrossConv(nn.Module): | ||
15 | + # Cross Convolution Downsample | ||
16 | + def __init__(self, c1, c2, k=3, s=1, g=1, e=1.0, shortcut=False): | ||
17 | + # ch_in, ch_out, kernel, stride, groups, expansion, shortcut | ||
18 | + super(CrossConv, self).__init__() | ||
19 | + c_ = int(c2 * e) # hidden channels | ||
20 | + self.cv1 = Conv(c1, c_, (1, k), (1, s)) | ||
21 | + self.cv2 = Conv(c_, c2, (k, 1), (s, 1), g=g) | ||
22 | + self.add = shortcut and c1 == c2 | ||
23 | + | ||
24 | + def forward(self, x): | ||
25 | + return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x)) | ||
26 | + | ||
27 | + | ||
28 | +class Sum(nn.Module): | ||
29 | + # Weighted sum of 2 or more layers https://arxiv.org/abs/1911.09070 | ||
30 | + def __init__(self, n, weight=False): # n: number of inputs | ||
31 | + super(Sum, self).__init__() | ||
32 | + self.weight = weight # apply weights boolean | ||
33 | + self.iter = range(n - 1) # iter object | ||
34 | + if weight: | ||
35 | + self.w = nn.Parameter(-torch.arange(1., n) / 2, requires_grad=True) # layer weights | ||
36 | + | ||
37 | + def forward(self, x): | ||
38 | + y = x[0] # no weight | ||
39 | + if self.weight: | ||
40 | + w = torch.sigmoid(self.w) * 2 | ||
41 | + for i in self.iter: | ||
42 | + y = y + x[i + 1] * w[i] | ||
43 | + else: | ||
44 | + for i in self.iter: | ||
45 | + y = y + x[i + 1] | ||
46 | + return y | ||
47 | + | ||
48 | + | ||
49 | +class GhostConv(nn.Module): | ||
50 | + # Ghost Convolution https://github.com/huawei-noah/ghostnet | ||
51 | + def __init__(self, c1, c2, k=1, s=1, g=1, act=True): # ch_in, ch_out, kernel, stride, groups | ||
52 | + super(GhostConv, self).__init__() | ||
53 | + c_ = c2 // 2 # hidden channels | ||
54 | + self.cv1 = Conv(c1, c_, k, s, None, g, act) | ||
55 | + self.cv2 = Conv(c_, c_, 5, 1, None, c_, act) | ||
56 | + | ||
57 | + def forward(self, x): | ||
58 | + y = self.cv1(x) | ||
59 | + return torch.cat([y, self.cv2(y)], 1) | ||
60 | + | ||
61 | + | ||
62 | +class GhostBottleneck(nn.Module): | ||
63 | + # Ghost Bottleneck https://github.com/huawei-noah/ghostnet | ||
64 | + def __init__(self, c1, c2, k=3, s=1): # ch_in, ch_out, kernel, stride | ||
65 | + super(GhostBottleneck, self).__init__() | ||
66 | + c_ = c2 // 2 | ||
67 | + self.conv = nn.Sequential(GhostConv(c1, c_, 1, 1), # pw | ||
68 | + DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(), # dw | ||
69 | + GhostConv(c_, c2, 1, 1, act=False)) # pw-linear | ||
70 | + self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False), | ||
71 | + Conv(c1, c2, 1, 1, act=False)) if s == 2 else nn.Identity() | ||
72 | + | ||
73 | + def forward(self, x): | ||
74 | + return self.conv(x) + self.shortcut(x) | ||
75 | + | ||
76 | + | ||
77 | +class MixConv2d(nn.Module): | ||
78 | + # Mixed Depthwise Conv https://arxiv.org/abs/1907.09595 | ||
79 | + def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True): | ||
80 | + super(MixConv2d, self).__init__() | ||
81 | + groups = len(k) | ||
82 | + if equal_ch: # equal c_ per group | ||
83 | + i = torch.linspace(0, groups - 1E-6, c2).floor() # c2 indices | ||
84 | + c_ = [(i == g).sum() for g in range(groups)] # intermediate channels | ||
85 | + else: # equal weight.numel() per group | ||
86 | + b = [c2] + [0] * groups | ||
87 | + a = np.eye(groups + 1, groups, k=-1) | ||
88 | + a -= np.roll(a, 1, axis=1) | ||
89 | + a *= np.array(k) ** 2 | ||
90 | + a[0] = 1 | ||
91 | + c_ = np.linalg.lstsq(a, b, rcond=None)[0].round() # solve for equal weight indices, ax = b | ||
92 | + | ||
93 | + self.m = nn.ModuleList([nn.Conv2d(c1, int(c_[g]), k[g], s, k[g] // 2, bias=False) for g in range(groups)]) | ||
94 | + self.bn = nn.BatchNorm2d(c2) | ||
95 | + self.act = nn.LeakyReLU(0.1, inplace=True) | ||
96 | + | ||
97 | + def forward(self, x): | ||
98 | + return x + self.act(self.bn(torch.cat([m(x) for m in self.m], 1))) | ||
99 | + | ||
100 | + | ||
101 | +class Ensemble(nn.ModuleList): | ||
102 | + # Ensemble of models | ||
103 | + def __init__(self): | ||
104 | + super(Ensemble, self).__init__() | ||
105 | + | ||
106 | + def forward(self, x, augment=False): | ||
107 | + y = [] | ||
108 | + for module in self: | ||
109 | + y.append(module(x, augment)[0]) | ||
110 | + # y = torch.stack(y).max(0)[0] # max ensemble | ||
111 | + # y = torch.stack(y).mean(0) # mean ensemble | ||
112 | + y = torch.cat(y, 1) # nms ensemble | ||
113 | + return y, None # inference, train output | ||
114 | + | ||
115 | + | ||
116 | +def attempt_load(weights, map_location=None, inplace=True): | ||
117 | + with yolov5_in_syspath(): | ||
118 | + from models.yolo import Detect, Model | ||
119 | + | ||
120 | + # Loads an ensemble of models weights=[a,b,c] or a single model weights=[a] or weights=a | ||
121 | + model = Ensemble() | ||
122 | + | ||
123 | + for w in weights if isinstance(weights, list) else [weights]: | ||
124 | + attempt_download(w) | ||
125 | + with yolov5_in_syspath(): | ||
126 | + ckpt = torch.load(w, map_location=map_location) # load | ||
127 | + model.append(ckpt['ema' if ckpt.get('ema') else 'model'].float().fuse().eval()) # FP32 model | ||
128 | + | ||
129 | + # Compatibility updates | ||
130 | + target_class_name_list = [class_.__name__ for class_ in [nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, Detect, Model]] # yolov5 5.0.3 compatibility | ||
131 | + for m in model.modules(): | ||
132 | + if type(m).__name__ in target_class_name_list: | ||
133 | + m.inplace = inplace # pytorch 1.7.0 compatibility | ||
134 | + elif type(m) is Conv: | ||
135 | + m._non_persistent_buffers_set = set() # pytorch 1.6.0 compatibility | ||
136 | + | ||
137 | + if len(model) == 1: | ||
138 | + return model[-1] # return model | ||
139 | + else: | ||
140 | + print(f'Ensemble created with {weights}\n') | ||
141 | + for k in ['names']: | ||
142 | + setattr(model, k, getattr(model[-1], k)) | ||
143 | + model.stride = model[torch.argmax(torch.tensor([m.stride.max() for m in model])).int()].stride # max stride | ||
144 | + return model # return ensemble |
1 | +"""Exports a YOLOv5 *.pt model to ONNX and TorchScript formats | ||
2 | + | ||
3 | +Usage: | ||
4 | + $ export PYTHONPATH="$PWD" && python models/export.py --weights yolov5s.pt --img 640 --batch 1 | ||
5 | +""" | ||
6 | + | ||
7 | +import argparse | ||
8 | +import sys | ||
9 | +import time | ||
10 | +from pathlib import Path | ||
11 | + | ||
12 | +import torch | ||
13 | +import torch.nn as nn | ||
14 | +import yolov5.models as models | ||
15 | +from torch.utils.mobile_optimizer import optimize_for_mobile | ||
16 | +from yolo_module.yolov5.models.experimental import attempt_load | ||
17 | +from yolo_module.yolov5.utils.activations import Hardswish, SiLU | ||
18 | +from yolo_module.yolov5.utils.general import (check_img_size, check_requirements, colorstr, | ||
19 | + file_size, set_logging) | ||
20 | +from yolo_module.yolov5.utils.torch_utils import select_device | ||
21 | + | ||
22 | +#sys.path.append(Path(__file__).parent.parent.absolute().__str__()) # to run '$ python *.py' files in subdirectories | ||
23 | + | ||
24 | + | ||
25 | + | ||
26 | +def main(): | ||
27 | + parser = argparse.ArgumentParser() | ||
28 | + parser.add_argument('--weights', type=str, default='./yolov5s.pt', help='weights path') | ||
29 | + parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='image size') # height, width | ||
30 | + parser.add_argument('--batch-size', type=int, default=1, help='batch size') | ||
31 | + parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu') | ||
32 | + parser.add_argument('--half', action='store_true', help='FP16 half-precision export') | ||
33 | + parser.add_argument('--inplace', action='store_true', help='set YOLOv5 Detect() inplace=True') | ||
34 | + parser.add_argument('--train', action='store_true', help='model.train() mode') | ||
35 | + parser.add_argument('--optimize', action='store_true', help='optimize TorchScript for mobile') # TorchScript-only | ||
36 | + parser.add_argument('--dynamic', action='store_true', help='dynamic ONNX axes') # ONNX-only | ||
37 | + parser.add_argument('--simplify', action='store_true', help='simplify ONNX model') # ONNX-only | ||
38 | + opt = parser.parse_args() | ||
39 | + opt.img_size *= 2 if len(opt.img_size) == 1 else 1 # expand | ||
40 | + print(opt) | ||
41 | + set_logging() | ||
42 | + t = time.time() | ||
43 | + | ||
44 | + # Load PyTorch model | ||
45 | + device = select_device(opt.device) | ||
46 | + | ||
47 | + model = attempt_load(opt.weights, map_location=device) # load FP32 model | ||
48 | + labels = model.names | ||
49 | + | ||
50 | + # Checks | ||
51 | + gs = int(max(model.stride)) # grid size (max stride) | ||
52 | + opt.img_size = [check_img_size(x, gs) for x in opt.img_size] # verify img_size are gs-multiples | ||
53 | + assert not (opt.device.lower() == "cpu" and opt.half), '--half only compatible with GPU export, i.e. use --device 0' | ||
54 | + | ||
55 | + # Input | ||
56 | + img = torch.zeros(opt.batch_size, 3, *opt.img_size).to(device) # image size(1,3,320,192) iDetection | ||
57 | + | ||
58 | + # Update model | ||
59 | + if opt.half: | ||
60 | + img, model = img.half(), model.half() # to FP16 | ||
61 | + if opt.train: | ||
62 | + model.train() # training mode (no grid construction in Detect layer) | ||
63 | + for k, m in model.named_modules(): | ||
64 | + m._non_persistent_buffers_set = set() # pytorch 1.6.0 compatibility | ||
65 | + if isinstance(m, models.common.Conv): # assign export-friendly activations | ||
66 | + if isinstance(m.act, nn.Hardswish): | ||
67 | + m.act = Hardswish() | ||
68 | + elif isinstance(m.act, nn.SiLU): | ||
69 | + m.act = SiLU() | ||
70 | + elif isinstance(m, models.yolo.Detect): | ||
71 | + m.inplace = opt.inplace | ||
72 | + m.onnx_dynamic = opt.dynamic | ||
73 | + # m.forward = m.forward_export # assign forward (optional) | ||
74 | + | ||
75 | + for _ in range(2): | ||
76 | + y = model(img) # dry runs | ||
77 | + print(f"\n{colorstr('PyTorch:')} starting from {opt.weights} ({file_size(opt.weights):.1f} MB)") | ||
78 | + | ||
79 | + # TorchScript export ----------------------------------------------------------------------------------------------- | ||
80 | + prefix = colorstr('TorchScript:') | ||
81 | + try: | ||
82 | + print(f'\n{prefix} starting export with torch {torch.__version__}...') | ||
83 | + f = opt.weights.replace('.pt', '.torchscript.pt') # filename | ||
84 | + ts = torch.jit.trace(model, img, strict=False) | ||
85 | + (optimize_for_mobile(ts) if opt.optimize else ts).save(f) | ||
86 | + print(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)') | ||
87 | + except Exception as e: | ||
88 | + print(f'{prefix} export failure: {e}') | ||
89 | + | ||
90 | + # ONNX export ------------------------------------------------------------------------------------------------------ | ||
91 | + prefix = colorstr('ONNX:') | ||
92 | + try: | ||
93 | + import onnx | ||
94 | + | ||
95 | + print(f'{prefix} starting export with onnx {onnx.__version__}...') | ||
96 | + f = opt.weights.replace('.pt', '.onnx') # filename | ||
97 | + torch.onnx.export(model, img, f, verbose=False, opset_version=12, input_names=['images'], | ||
98 | + dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'}, # size(1,3,640,640) | ||
99 | + 'output': {0: 'batch', 2: 'y', 3: 'x'}} if opt.dynamic else None) | ||
100 | + | ||
101 | + # Checks | ||
102 | + model_onnx = onnx.load(f) # load onnx model | ||
103 | + onnx.checker.check_model(model_onnx) # check onnx model | ||
104 | + # print(onnx.helper.printable_graph(model_onnx.graph)) # print | ||
105 | + | ||
106 | + # Simplify | ||
107 | + if opt.simplify: | ||
108 | + try: | ||
109 | + check_requirements(['onnx-simplifier']) | ||
110 | + import onnxsim | ||
111 | + | ||
112 | + print(f'{prefix} simplifying with onnx-simplifier {onnxsim.__version__}...') | ||
113 | + model_onnx, check = onnxsim.simplify(model_onnx, | ||
114 | + dynamic_input_shape=opt.dynamic, | ||
115 | + input_shapes={'images': list(img.shape)} if opt.dynamic else None) | ||
116 | + assert check, 'assert check failed' | ||
117 | + onnx.save(model_onnx, f) | ||
118 | + except Exception as e: | ||
119 | + print(f'{prefix} simplifier failure: {e}') | ||
120 | + print(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)') | ||
121 | + except Exception as e: | ||
122 | + print(f'{prefix} export failure: {e}') | ||
123 | + | ||
124 | + # CoreML export ---------------------------------------------------------------------------------------------------- | ||
125 | + prefix = colorstr('CoreML:') | ||
126 | + try: | ||
127 | + import coremltools as ct | ||
128 | + | ||
129 | + print(f'{prefix} starting export with coremltools {ct.__version__}...') | ||
130 | + model = ct.convert(ts, inputs=[ct.ImageType(name='image', shape=img.shape, scale=1 / 255.0, bias=[0, 0, 0])]) | ||
131 | + f = opt.weights.replace('.pt', '.mlmodel') # filename | ||
132 | + model.save(f) | ||
133 | + print(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)') | ||
134 | + except Exception as e: | ||
135 | + print(f'{prefix} export failure: {e}') | ||
136 | + | ||
137 | + # Finish | ||
138 | + print(f'\nExport complete ({time.time() - t:.2f}s). Visualize with https://github.com/lutzroeder/netron.') | ||
139 | + | ||
140 | +if __name__ == '__main__': | ||
141 | + main() |
1 | +# Default YOLOv5 anchors for COCO data | ||
2 | + | ||
3 | + | ||
4 | +# P5 ------------------------------------------------------------------------------------------------------------------- | ||
5 | +# P5-640: | ||
6 | +anchors_p5_640: | ||
7 | + - [ 10,13, 16,30, 33,23 ] # P3/8 | ||
8 | + - [ 30,61, 62,45, 59,119 ] # P4/16 | ||
9 | + - [ 116,90, 156,198, 373,326 ] # P5/32 | ||
10 | + | ||
11 | + | ||
12 | +# P6 ------------------------------------------------------------------------------------------------------------------- | ||
13 | +# P6-640: thr=0.25: 0.9964 BPR, 5.54 anchors past thr, n=12, img_size=640, metric_all=0.281/0.716-mean/best, past_thr=0.469-mean: 9,11, 21,19, 17,41, 43,32, 39,70, 86,64, 65,131, 134,130, 120,265, 282,180, 247,354, 512,387 | ||
14 | +anchors_p6_640: | ||
15 | + - [ 9,11, 21,19, 17,41 ] # P3/8 | ||
16 | + - [ 43,32, 39,70, 86,64 ] # P4/16 | ||
17 | + - [ 65,131, 134,130, 120,265 ] # P5/32 | ||
18 | + - [ 282,180, 247,354, 512,387 ] # P6/64 | ||
19 | + | ||
20 | +# P6-1280: thr=0.25: 0.9950 BPR, 5.55 anchors past thr, n=12, img_size=1280, metric_all=0.281/0.714-mean/best, past_thr=0.468-mean: 19,27, 44,40, 38,94, 96,68, 86,152, 180,137, 140,301, 303,264, 238,542, 436,615, 739,380, 925,792 | ||
21 | +anchors_p6_1280: | ||
22 | + - [ 19,27, 44,40, 38,94 ] # P3/8 | ||
23 | + - [ 96,68, 86,152, 180,137 ] # P4/16 | ||
24 | + - [ 140,301, 303,264, 238,542 ] # P5/32 | ||
25 | + - [ 436,615, 739,380, 925,792 ] # P6/64 | ||
26 | + | ||
27 | +# P6-1920: thr=0.25: 0.9950 BPR, 5.55 anchors past thr, n=12, img_size=1920, metric_all=0.281/0.714-mean/best, past_thr=0.468-mean: 28,41, 67,59, 57,141, 144,103, 129,227, 270,205, 209,452, 455,396, 358,812, 653,922, 1109,570, 1387,1187 | ||
28 | +anchors_p6_1920: | ||
29 | + - [ 28,41, 67,59, 57,141 ] # P3/8 | ||
30 | + - [ 144,103, 129,227, 270,205 ] # P4/16 | ||
31 | + - [ 209,452, 455,396, 358,812 ] # P5/32 | ||
32 | + - [ 653,922, 1109,570, 1387,1187 ] # P6/64 | ||
33 | + | ||
34 | + | ||
35 | +# P7 ------------------------------------------------------------------------------------------------------------------- | ||
36 | +# P7-640: thr=0.25: 0.9962 BPR, 6.76 anchors past thr, n=15, img_size=640, metric_all=0.275/0.733-mean/best, past_thr=0.466-mean: 11,11, 13,30, 29,20, 30,46, 61,38, 39,92, 78,80, 146,66, 79,163, 149,150, 321,143, 157,303, 257,402, 359,290, 524,372 | ||
37 | +anchors_p7_640: | ||
38 | + - [ 11,11, 13,30, 29,20 ] # P3/8 | ||
39 | + - [ 30,46, 61,38, 39,92 ] # P4/16 | ||
40 | + - [ 78,80, 146,66, 79,163 ] # P5/32 | ||
41 | + - [ 149,150, 321,143, 157,303 ] # P6/64 | ||
42 | + - [ 257,402, 359,290, 524,372 ] # P7/128 | ||
43 | + | ||
44 | +# P7-1280: thr=0.25: 0.9968 BPR, 6.71 anchors past thr, n=15, img_size=1280, metric_all=0.273/0.732-mean/best, past_thr=0.463-mean: 19,22, 54,36, 32,77, 70,83, 138,71, 75,173, 165,159, 148,334, 375,151, 334,317, 251,626, 499,474, 750,326, 534,814, 1079,818 | ||
45 | +anchors_p7_1280: | ||
46 | + - [ 19,22, 54,36, 32,77 ] # P3/8 | ||
47 | + - [ 70,83, 138,71, 75,173 ] # P4/16 | ||
48 | + - [ 165,159, 148,334, 375,151 ] # P5/32 | ||
49 | + - [ 334,317, 251,626, 499,474 ] # P6/64 | ||
50 | + - [ 750,326, 534,814, 1079,818 ] # P7/128 | ||
51 | + | ||
52 | +# P7-1920: thr=0.25: 0.9968 BPR, 6.71 anchors past thr, n=15, img_size=1920, metric_all=0.273/0.732-mean/best, past_thr=0.463-mean: 29,34, 81,55, 47,115, 105,124, 207,107, 113,259, 247,238, 222,500, 563,227, 501,476, 376,939, 749,711, 1126,489, 801,1222, 1618,1227 | ||
53 | +anchors_p7_1920: | ||
54 | + - [ 29,34, 81,55, 47,115 ] # P3/8 | ||
55 | + - [ 105,124, 207,107, 113,259 ] # P4/16 | ||
56 | + - [ 247,238, 222,500, 563,227 ] # P5/32 | ||
57 | + - [ 501,476, 376,939, 749,711 ] # P6/64 | ||
58 | + - [ 1126,489, 801,1222, 1618,1227 ] # P7/128 |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# darknet53 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Conv, [32, 3, 1]], # 0 | ||
16 | + [-1, 1, Conv, [64, 3, 2]], # 1-P1/2 | ||
17 | + [-1, 1, Bottleneck, [64]], | ||
18 | + [-1, 1, Conv, [128, 3, 2]], # 3-P2/4 | ||
19 | + [-1, 2, Bottleneck, [128]], | ||
20 | + [-1, 1, Conv, [256, 3, 2]], # 5-P3/8 | ||
21 | + [-1, 8, Bottleneck, [256]], | ||
22 | + [-1, 1, Conv, [512, 3, 2]], # 7-P4/16 | ||
23 | + [-1, 8, Bottleneck, [512]], | ||
24 | + [-1, 1, Conv, [1024, 3, 2]], # 9-P5/32 | ||
25 | + [-1, 4, Bottleneck, [1024]], # 10 | ||
26 | + ] | ||
27 | + | ||
28 | +# YOLOv3-SPP head | ||
29 | +head: | ||
30 | + [[-1, 1, Bottleneck, [1024, False]], | ||
31 | + [-1, 1, SPP, [512, [5, 9, 13]]], | ||
32 | + [-1, 1, Conv, [1024, 3, 1]], | ||
33 | + [-1, 1, Conv, [512, 1, 1]], | ||
34 | + [-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large) | ||
35 | + | ||
36 | + [-2, 1, Conv, [256, 1, 1]], | ||
37 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
38 | + [[-1, 8], 1, Concat, [1]], # cat backbone P4 | ||
39 | + [-1, 1, Bottleneck, [512, False]], | ||
40 | + [-1, 1, Bottleneck, [512, False]], | ||
41 | + [-1, 1, Conv, [256, 1, 1]], | ||
42 | + [-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium) | ||
43 | + | ||
44 | + [-2, 1, Conv, [128, 1, 1]], | ||
45 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
46 | + [[-1, 6], 1, Concat, [1]], # cat backbone P3 | ||
47 | + [-1, 1, Bottleneck, [256, False]], | ||
48 | + [-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small) | ||
49 | + | ||
50 | + [[27, 22, 15], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
51 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,14, 23,27, 37,58] # P4/16 | ||
9 | + - [81,82, 135,169, 344,319] # P5/32 | ||
10 | + | ||
11 | +# YOLOv3-tiny backbone | ||
12 | +backbone: | ||
13 | + # [from, number, module, args] | ||
14 | + [[-1, 1, Conv, [16, 3, 1]], # 0 | ||
15 | + [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 1-P1/2 | ||
16 | + [-1, 1, Conv, [32, 3, 1]], | ||
17 | + [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 3-P2/4 | ||
18 | + [-1, 1, Conv, [64, 3, 1]], | ||
19 | + [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 5-P3/8 | ||
20 | + [-1, 1, Conv, [128, 3, 1]], | ||
21 | + [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 7-P4/16 | ||
22 | + [-1, 1, Conv, [256, 3, 1]], | ||
23 | + [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 9-P5/32 | ||
24 | + [-1, 1, Conv, [512, 3, 1]], | ||
25 | + [-1, 1, nn.ZeroPad2d, [[0, 1, 0, 1]]], # 11 | ||
26 | + [-1, 1, nn.MaxPool2d, [2, 1, 0]], # 12 | ||
27 | + ] | ||
28 | + | ||
29 | +# YOLOv3-tiny head | ||
30 | +head: | ||
31 | + [[-1, 1, Conv, [1024, 3, 1]], | ||
32 | + [-1, 1, Conv, [256, 1, 1]], | ||
33 | + [-1, 1, Conv, [512, 3, 1]], # 15 (P5/32-large) | ||
34 | + | ||
35 | + [-2, 1, Conv, [128, 1, 1]], | ||
36 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
37 | + [[-1, 8], 1, Concat, [1]], # cat backbone P4 | ||
38 | + [-1, 1, Conv, [256, 3, 1]], # 19 (P4/16-medium) | ||
39 | + | ||
40 | + [[19, 15], 1, Detect, [nc, anchors]], # Detect(P4, P5) | ||
41 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# darknet53 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Conv, [32, 3, 1]], # 0 | ||
16 | + [-1, 1, Conv, [64, 3, 2]], # 1-P1/2 | ||
17 | + [-1, 1, Bottleneck, [64]], | ||
18 | + [-1, 1, Conv, [128, 3, 2]], # 3-P2/4 | ||
19 | + [-1, 2, Bottleneck, [128]], | ||
20 | + [-1, 1, Conv, [256, 3, 2]], # 5-P3/8 | ||
21 | + [-1, 8, Bottleneck, [256]], | ||
22 | + [-1, 1, Conv, [512, 3, 2]], # 7-P4/16 | ||
23 | + [-1, 8, Bottleneck, [512]], | ||
24 | + [-1, 1, Conv, [1024, 3, 2]], # 9-P5/32 | ||
25 | + [-1, 4, Bottleneck, [1024]], # 10 | ||
26 | + ] | ||
27 | + | ||
28 | +# YOLOv3 head | ||
29 | +head: | ||
30 | + [[-1, 1, Bottleneck, [1024, False]], | ||
31 | + [-1, 1, Conv, [512, [1, 1]]], | ||
32 | + [-1, 1, Conv, [1024, 3, 1]], | ||
33 | + [-1, 1, Conv, [512, 1, 1]], | ||
34 | + [-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large) | ||
35 | + | ||
36 | + [-2, 1, Conv, [256, 1, 1]], | ||
37 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
38 | + [[-1, 8], 1, Concat, [1]], # cat backbone P4 | ||
39 | + [-1, 1, Bottleneck, [512, False]], | ||
40 | + [-1, 1, Bottleneck, [512, False]], | ||
41 | + [-1, 1, Conv, [256, 1, 1]], | ||
42 | + [-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium) | ||
43 | + | ||
44 | + [-2, 1, Conv, [128, 1, 1]], | ||
45 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
46 | + [[-1, 6], 1, Concat, [1]], # cat backbone P3 | ||
47 | + [-1, 1, Bottleneck, [256, False]], | ||
48 | + [-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small) | ||
49 | + | ||
50 | + [[27, 22, 15], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
51 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, Bottleneck, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, BottleneckCSP, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, BottleneckCSP, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 6, BottleneckCSP, [1024]], # 9 | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 FPN head | ||
28 | +head: | ||
29 | + [[-1, 3, BottleneckCSP, [1024, False]], # 10 (P5/32-large) | ||
30 | + | ||
31 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
32 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
33 | + [-1, 1, Conv, [512, 1, 1]], | ||
34 | + [-1, 3, BottleneckCSP, [512, False]], # 14 (P4/16-medium) | ||
35 | + | ||
36 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
37 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
38 | + [-1, 1, Conv, [256, 1, 1]], | ||
39 | + [-1, 3, BottleneckCSP, [256, False]], # 18 (P3/8-small) | ||
40 | + | ||
41 | + [[18, 14, 10], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
42 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: 3 | ||
8 | + | ||
9 | +# YOLOv5 backbone | ||
10 | +backbone: | ||
11 | + # [from, number, module, args] | ||
12 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
13 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
14 | + [ -1, 3, C3, [ 128 ] ], | ||
15 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
16 | + [ -1, 9, C3, [ 256 ] ], | ||
17 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
18 | + [ -1, 9, C3, [ 512 ] ], | ||
19 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 7-P5/32 | ||
20 | + [ -1, 1, SPP, [ 1024, [ 5, 9, 13 ] ] ], | ||
21 | + [ -1, 3, C3, [ 1024, False ] ], # 9 | ||
22 | + ] | ||
23 | + | ||
24 | +# YOLOv5 head | ||
25 | +head: | ||
26 | + [ [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
27 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
28 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
29 | + [ -1, 3, C3, [ 512, False ] ], # 13 | ||
30 | + | ||
31 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
32 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
33 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
34 | + [ -1, 3, C3, [ 256, False ] ], # 17 (P3/8-small) | ||
35 | + | ||
36 | + [ -1, 1, Conv, [ 128, 1, 1 ] ], | ||
37 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
38 | + [ [ -1, 2 ], 1, Concat, [ 1 ] ], # cat backbone P2 | ||
39 | + [ -1, 1, C3, [ 128, False ] ], # 21 (P2/4-xsmall) | ||
40 | + | ||
41 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], | ||
42 | + [ [ -1, 18 ], 1, Concat, [ 1 ] ], # cat head P3 | ||
43 | + [ -1, 3, C3, [ 256, False ] ], # 24 (P3/8-small) | ||
44 | + | ||
45 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
46 | + [ [ -1, 14 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
47 | + [ -1, 3, C3, [ 512, False ] ], # 27 (P4/16-medium) | ||
48 | + | ||
49 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
50 | + [ [ -1, 10 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
51 | + [ -1, 3, C3, [ 1024, False ] ], # 30 (P5/32-large) | ||
52 | + | ||
53 | + [ [ 24, 27, 30 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5) | ||
54 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: 3 | ||
8 | + | ||
9 | +# YOLOv5 backbone | ||
10 | +backbone: | ||
11 | + # [from, number, module, args] | ||
12 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
13 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
14 | + [ -1, 3, C3, [ 128 ] ], | ||
15 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
16 | + [ -1, 9, C3, [ 256 ] ], | ||
17 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
18 | + [ -1, 9, C3, [ 512 ] ], | ||
19 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32 | ||
20 | + [ -1, 3, C3, [ 768 ] ], | ||
21 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64 | ||
22 | + [ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ], | ||
23 | + [ -1, 3, C3, [ 1024, False ] ], # 11 | ||
24 | + ] | ||
25 | + | ||
26 | +# YOLOv5 head | ||
27 | +head: | ||
28 | + [ [ -1, 1, Conv, [ 768, 1, 1 ] ], | ||
29 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
30 | + [ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5 | ||
31 | + [ -1, 3, C3, [ 768, False ] ], # 15 | ||
32 | + | ||
33 | + [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
34 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
35 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
36 | + [ -1, 3, C3, [ 512, False ] ], # 19 | ||
37 | + | ||
38 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
39 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
40 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
41 | + [ -1, 3, C3, [ 256, False ] ], # 23 (P3/8-small) | ||
42 | + | ||
43 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
44 | + [ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
45 | + [ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium) | ||
46 | + | ||
47 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
48 | + [ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
49 | + [ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large) | ||
50 | + | ||
51 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], | ||
52 | + [ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6 | ||
53 | + [ -1, 3, C3, [ 1024, False ] ], # 32 (P5/64-xlarge) | ||
54 | + | ||
55 | + [ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6) | ||
56 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: 3 | ||
8 | + | ||
9 | +# YOLOv5 backbone | ||
10 | +backbone: | ||
11 | + # [from, number, module, args] | ||
12 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
13 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
14 | + [ -1, 3, C3, [ 128 ] ], | ||
15 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
16 | + [ -1, 9, C3, [ 256 ] ], | ||
17 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
18 | + [ -1, 9, C3, [ 512 ] ], | ||
19 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32 | ||
20 | + [ -1, 3, C3, [ 768 ] ], | ||
21 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64 | ||
22 | + [ -1, 3, C3, [ 1024 ] ], | ||
23 | + [ -1, 1, Conv, [ 1280, 3, 2 ] ], # 11-P7/128 | ||
24 | + [ -1, 1, SPP, [ 1280, [ 3, 5 ] ] ], | ||
25 | + [ -1, 3, C3, [ 1280, False ] ], # 13 | ||
26 | + ] | ||
27 | + | ||
28 | +# YOLOv5 head | ||
29 | +head: | ||
30 | + [ [ -1, 1, Conv, [ 1024, 1, 1 ] ], | ||
31 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
32 | + [ [ -1, 10 ], 1, Concat, [ 1 ] ], # cat backbone P6 | ||
33 | + [ -1, 3, C3, [ 1024, False ] ], # 17 | ||
34 | + | ||
35 | + [ -1, 1, Conv, [ 768, 1, 1 ] ], | ||
36 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
37 | + [ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5 | ||
38 | + [ -1, 3, C3, [ 768, False ] ], # 21 | ||
39 | + | ||
40 | + [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
41 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
42 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
43 | + [ -1, 3, C3, [ 512, False ] ], # 25 | ||
44 | + | ||
45 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
46 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
47 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
48 | + [ -1, 3, C3, [ 256, False ] ], # 29 (P3/8-small) | ||
49 | + | ||
50 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
51 | + [ [ -1, 26 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
52 | + [ -1, 3, C3, [ 512, False ] ], # 32 (P4/16-medium) | ||
53 | + | ||
54 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
55 | + [ [ -1, 22 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
56 | + [ -1, 3, C3, [ 768, False ] ], # 35 (P5/32-large) | ||
57 | + | ||
58 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], | ||
59 | + [ [ -1, 18 ], 1, Concat, [ 1 ] ], # cat head P6 | ||
60 | + [ -1, 3, C3, [ 1024, False ] ], # 38 (P6/64-xlarge) | ||
61 | + | ||
62 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], | ||
63 | + [ [ -1, 14 ], 1, Concat, [ 1 ] ], # cat head P7 | ||
64 | + [ -1, 3, C3, [ 1280, False ] ], # 41 (P7/128-xxlarge) | ||
65 | + | ||
66 | + [ [ 29, 32, 35, 38, 41 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6, P7) | ||
67 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, BottleneckCSP, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, BottleneckCSP, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, BottleneckCSP, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 3, BottleneckCSP, [1024, False]], # 9 | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 PANet head | ||
28 | +head: | ||
29 | + [[-1, 1, Conv, [512, 1, 1]], | ||
30 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
31 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
32 | + [-1, 3, BottleneckCSP, [512, False]], # 13 | ||
33 | + | ||
34 | + [-1, 1, Conv, [256, 1, 1]], | ||
35 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
36 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
37 | + [-1, 3, BottleneckCSP, [256, False]], # 17 (P3/8-small) | ||
38 | + | ||
39 | + [-1, 1, Conv, [256, 3, 2]], | ||
40 | + [[-1, 14], 1, Concat, [1]], # cat head P4 | ||
41 | + [-1, 3, BottleneckCSP, [512, False]], # 20 (P4/16-medium) | ||
42 | + | ||
43 | + [-1, 1, Conv, [512, 3, 2]], | ||
44 | + [[-1, 10], 1, Concat, [1]], # cat head P5 | ||
45 | + [-1, 3, BottleneckCSP, [1024, False]], # 23 (P5/32-large) | ||
46 | + | ||
47 | + [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
48 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [ 19,27, 44,40, 38,94 ] # P3/8 | ||
9 | + - [ 96,68, 86,152, 180,137 ] # P4/16 | ||
10 | + - [ 140,301, 303,264, 238,542 ] # P5/32 | ||
11 | + - [ 436,615, 739,380, 925,792 ] # P6/64 | ||
12 | + | ||
13 | +# YOLOv5 backbone | ||
14 | +backbone: | ||
15 | + # [from, number, module, args] | ||
16 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
17 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
18 | + [ -1, 3, C3, [ 128 ] ], | ||
19 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
20 | + [ -1, 9, C3, [ 256 ] ], | ||
21 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
22 | + [ -1, 9, C3, [ 512 ] ], | ||
23 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32 | ||
24 | + [ -1, 3, C3, [ 768 ] ], | ||
25 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64 | ||
26 | + [ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ], | ||
27 | + [ -1, 3, C3, [ 1024, False ] ], # 11 | ||
28 | + ] | ||
29 | + | ||
30 | +# YOLOv5 head | ||
31 | +head: | ||
32 | + [ [ -1, 1, Conv, [ 768, 1, 1 ] ], | ||
33 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
34 | + [ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5 | ||
35 | + [ -1, 3, C3, [ 768, False ] ], # 15 | ||
36 | + | ||
37 | + [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
38 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
39 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
40 | + [ -1, 3, C3, [ 512, False ] ], # 19 | ||
41 | + | ||
42 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
43 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
44 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
45 | + [ -1, 3, C3, [ 256, False ] ], # 23 (P3/8-small) | ||
46 | + | ||
47 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
48 | + [ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
49 | + [ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium) | ||
50 | + | ||
51 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
52 | + [ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
53 | + [ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large) | ||
54 | + | ||
55 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], | ||
56 | + [ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6 | ||
57 | + [ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge) | ||
58 | + | ||
59 | + [ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6) | ||
60 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 0.67 # model depth multiple | ||
4 | +width_multiple: 0.75 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [ 19,27, 44,40, 38,94 ] # P3/8 | ||
9 | + - [ 96,68, 86,152, 180,137 ] # P4/16 | ||
10 | + - [ 140,301, 303,264, 238,542 ] # P5/32 | ||
11 | + - [ 436,615, 739,380, 925,792 ] # P6/64 | ||
12 | + | ||
13 | +# YOLOv5 backbone | ||
14 | +backbone: | ||
15 | + # [from, number, module, args] | ||
16 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
17 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
18 | + [ -1, 3, C3, [ 128 ] ], | ||
19 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
20 | + [ -1, 9, C3, [ 256 ] ], | ||
21 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
22 | + [ -1, 9, C3, [ 512 ] ], | ||
23 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32 | ||
24 | + [ -1, 3, C3, [ 768 ] ], | ||
25 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64 | ||
26 | + [ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ], | ||
27 | + [ -1, 3, C3, [ 1024, False ] ], # 11 | ||
28 | + ] | ||
29 | + | ||
30 | +# YOLOv5 head | ||
31 | +head: | ||
32 | + [ [ -1, 1, Conv, [ 768, 1, 1 ] ], | ||
33 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
34 | + [ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5 | ||
35 | + [ -1, 3, C3, [ 768, False ] ], # 15 | ||
36 | + | ||
37 | + [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
38 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
39 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
40 | + [ -1, 3, C3, [ 512, False ] ], # 19 | ||
41 | + | ||
42 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
43 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
44 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
45 | + [ -1, 3, C3, [ 256, False ] ], # 23 (P3/8-small) | ||
46 | + | ||
47 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
48 | + [ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
49 | + [ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium) | ||
50 | + | ||
51 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
52 | + [ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
53 | + [ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large) | ||
54 | + | ||
55 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], | ||
56 | + [ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6 | ||
57 | + [ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge) | ||
58 | + | ||
59 | + [ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6) | ||
60 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 0.33 # model depth multiple | ||
4 | +width_multiple: 0.50 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, C3, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, C3, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, C3, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 3, C3TR, [1024, False]], # 9 <-------- C3TR() Transformer module | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 head | ||
28 | +head: | ||
29 | + [[-1, 1, Conv, [512, 1, 1]], | ||
30 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
31 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
32 | + [-1, 3, C3, [512, False]], # 13 | ||
33 | + | ||
34 | + [-1, 1, Conv, [256, 1, 1]], | ||
35 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
36 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
37 | + [-1, 3, C3, [256, False]], # 17 (P3/8-small) | ||
38 | + | ||
39 | + [-1, 1, Conv, [256, 3, 2]], | ||
40 | + [[-1, 14], 1, Concat, [1]], # cat head P4 | ||
41 | + [-1, 3, C3, [512, False]], # 20 (P4/16-medium) | ||
42 | + | ||
43 | + [-1, 1, Conv, [512, 3, 2]], | ||
44 | + [[-1, 10], 1, Concat, [1]], # cat head P5 | ||
45 | + [-1, 3, C3, [1024, False]], # 23 (P5/32-large) | ||
46 | + | ||
47 | + [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
48 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 0.33 # model depth multiple | ||
4 | +width_multiple: 0.50 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [ 19,27, 44,40, 38,94 ] # P3/8 | ||
9 | + - [ 96,68, 86,152, 180,137 ] # P4/16 | ||
10 | + - [ 140,301, 303,264, 238,542 ] # P5/32 | ||
11 | + - [ 436,615, 739,380, 925,792 ] # P6/64 | ||
12 | + | ||
13 | +# YOLOv5 backbone | ||
14 | +backbone: | ||
15 | + # [from, number, module, args] | ||
16 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
17 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
18 | + [ -1, 3, C3, [ 128 ] ], | ||
19 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
20 | + [ -1, 9, C3, [ 256 ] ], | ||
21 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
22 | + [ -1, 9, C3, [ 512 ] ], | ||
23 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32 | ||
24 | + [ -1, 3, C3, [ 768 ] ], | ||
25 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64 | ||
26 | + [ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ], | ||
27 | + [ -1, 3, C3, [ 1024, False ] ], # 11 | ||
28 | + ] | ||
29 | + | ||
30 | +# YOLOv5 head | ||
31 | +head: | ||
32 | + [ [ -1, 1, Conv, [ 768, 1, 1 ] ], | ||
33 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
34 | + [ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5 | ||
35 | + [ -1, 3, C3, [ 768, False ] ], # 15 | ||
36 | + | ||
37 | + [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
38 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
39 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
40 | + [ -1, 3, C3, [ 512, False ] ], # 19 | ||
41 | + | ||
42 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
43 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
44 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
45 | + [ -1, 3, C3, [ 256, False ] ], # 23 (P3/8-small) | ||
46 | + | ||
47 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
48 | + [ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
49 | + [ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium) | ||
50 | + | ||
51 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
52 | + [ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
53 | + [ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large) | ||
54 | + | ||
55 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], | ||
56 | + [ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6 | ||
57 | + [ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge) | ||
58 | + | ||
59 | + [ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6) | ||
60 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.33 # model depth multiple | ||
4 | +width_multiple: 1.25 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [ 19,27, 44,40, 38,94 ] # P3/8 | ||
9 | + - [ 96,68, 86,152, 180,137 ] # P4/16 | ||
10 | + - [ 140,301, 303,264, 238,542 ] # P5/32 | ||
11 | + - [ 436,615, 739,380, 925,792 ] # P6/64 | ||
12 | + | ||
13 | +# YOLOv5 backbone | ||
14 | +backbone: | ||
15 | + # [from, number, module, args] | ||
16 | + [ [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2 | ||
17 | + [ -1, 1, Conv, [ 128, 3, 2 ] ], # 1-P2/4 | ||
18 | + [ -1, 3, C3, [ 128 ] ], | ||
19 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8 | ||
20 | + [ -1, 9, C3, [ 256 ] ], | ||
21 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16 | ||
22 | + [ -1, 9, C3, [ 512 ] ], | ||
23 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32 | ||
24 | + [ -1, 3, C3, [ 768 ] ], | ||
25 | + [ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64 | ||
26 | + [ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ], | ||
27 | + [ -1, 3, C3, [ 1024, False ] ], # 11 | ||
28 | + ] | ||
29 | + | ||
30 | +# YOLOv5 head | ||
31 | +head: | ||
32 | + [ [ -1, 1, Conv, [ 768, 1, 1 ] ], | ||
33 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
34 | + [ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5 | ||
35 | + [ -1, 3, C3, [ 768, False ] ], # 15 | ||
36 | + | ||
37 | + [ -1, 1, Conv, [ 512, 1, 1 ] ], | ||
38 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
39 | + [ [ -1, 6 ], 1, Concat, [ 1 ] ], # cat backbone P4 | ||
40 | + [ -1, 3, C3, [ 512, False ] ], # 19 | ||
41 | + | ||
42 | + [ -1, 1, Conv, [ 256, 1, 1 ] ], | ||
43 | + [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ], | ||
44 | + [ [ -1, 4 ], 1, Concat, [ 1 ] ], # cat backbone P3 | ||
45 | + [ -1, 3, C3, [ 256, False ] ], # 23 (P3/8-small) | ||
46 | + | ||
47 | + [ -1, 1, Conv, [ 256, 3, 2 ] ], | ||
48 | + [ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4 | ||
49 | + [ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium) | ||
50 | + | ||
51 | + [ -1, 1, Conv, [ 512, 3, 2 ] ], | ||
52 | + [ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5 | ||
53 | + [ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large) | ||
54 | + | ||
55 | + [ -1, 1, Conv, [ 768, 3, 2 ] ], | ||
56 | + [ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6 | ||
57 | + [ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge) | ||
58 | + | ||
59 | + [ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6) | ||
60 | + ] |
This diff is collapsed. Click to expand it.
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.0 # model depth multiple | ||
4 | +width_multiple: 1.0 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, C3, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, C3, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, C3, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 3, C3, [1024, False]], # 9 | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 head | ||
28 | +head: | ||
29 | + [[-1, 1, Conv, [512, 1, 1]], | ||
30 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
31 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
32 | + [-1, 3, C3, [512, False]], # 13 | ||
33 | + | ||
34 | + [-1, 1, Conv, [256, 1, 1]], | ||
35 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
36 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
37 | + [-1, 3, C3, [256, False]], # 17 (P3/8-small) | ||
38 | + | ||
39 | + [-1, 1, Conv, [256, 3, 2]], | ||
40 | + [[-1, 14], 1, Concat, [1]], # cat head P4 | ||
41 | + [-1, 3, C3, [512, False]], # 20 (P4/16-medium) | ||
42 | + | ||
43 | + [-1, 1, Conv, [512, 3, 2]], | ||
44 | + [[-1, 10], 1, Concat, [1]], # cat head P5 | ||
45 | + [-1, 3, C3, [1024, False]], # 23 (P5/32-large) | ||
46 | + | ||
47 | + [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
48 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 0.67 # model depth multiple | ||
4 | +width_multiple: 0.75 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, C3, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, C3, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, C3, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 3, C3, [1024, False]], # 9 | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 head | ||
28 | +head: | ||
29 | + [[-1, 1, Conv, [512, 1, 1]], | ||
30 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
31 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
32 | + [-1, 3, C3, [512, False]], # 13 | ||
33 | + | ||
34 | + [-1, 1, Conv, [256, 1, 1]], | ||
35 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
36 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
37 | + [-1, 3, C3, [256, False]], # 17 (P3/8-small) | ||
38 | + | ||
39 | + [-1, 1, Conv, [256, 3, 2]], | ||
40 | + [[-1, 14], 1, Concat, [1]], # cat head P4 | ||
41 | + [-1, 3, C3, [512, False]], # 20 (P4/16-medium) | ||
42 | + | ||
43 | + [-1, 1, Conv, [512, 3, 2]], | ||
44 | + [[-1, 10], 1, Concat, [1]], # cat head P5 | ||
45 | + [-1, 3, C3, [1024, False]], # 23 (P5/32-large) | ||
46 | + | ||
47 | + [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
48 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 0.33 # model depth multiple | ||
4 | +width_multiple: 0.50 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, C3, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, C3, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, C3, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 3, C3, [1024, False]], # 9 | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 head | ||
28 | +head: | ||
29 | + [[-1, 1, Conv, [512, 1, 1]], | ||
30 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
31 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
32 | + [-1, 3, C3, [512, False]], # 13 | ||
33 | + | ||
34 | + [-1, 1, Conv, [256, 1, 1]], | ||
35 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
36 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
37 | + [-1, 3, C3, [256, False]], # 17 (P3/8-small) | ||
38 | + | ||
39 | + [-1, 1, Conv, [256, 3, 2]], | ||
40 | + [[-1, 14], 1, Concat, [1]], # cat head P4 | ||
41 | + [-1, 3, C3, [512, False]], # 20 (P4/16-medium) | ||
42 | + | ||
43 | + [-1, 1, Conv, [512, 3, 2]], | ||
44 | + [[-1, 10], 1, Concat, [1]], # cat head P5 | ||
45 | + [-1, 3, C3, [1024, False]], # 23 (P5/32-large) | ||
46 | + | ||
47 | + [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
48 | + ] |
1 | +# parameters | ||
2 | +nc: 80 # number of classes | ||
3 | +depth_multiple: 1.33 # model depth multiple | ||
4 | +width_multiple: 1.25 # layer channel multiple | ||
5 | + | ||
6 | +# anchors | ||
7 | +anchors: | ||
8 | + - [10,13, 16,30, 33,23] # P3/8 | ||
9 | + - [30,61, 62,45, 59,119] # P4/16 | ||
10 | + - [116,90, 156,198, 373,326] # P5/32 | ||
11 | + | ||
12 | +# YOLOv5 backbone | ||
13 | +backbone: | ||
14 | + # [from, number, module, args] | ||
15 | + [[-1, 1, Focus, [64, 3]], # 0-P1/2 | ||
16 | + [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 | ||
17 | + [-1, 3, C3, [128]], | ||
18 | + [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 | ||
19 | + [-1, 9, C3, [256]], | ||
20 | + [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 | ||
21 | + [-1, 9, C3, [512]], | ||
22 | + [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 | ||
23 | + [-1, 1, SPP, [1024, [5, 9, 13]]], | ||
24 | + [-1, 3, C3, [1024, False]], # 9 | ||
25 | + ] | ||
26 | + | ||
27 | +# YOLOv5 head | ||
28 | +head: | ||
29 | + [[-1, 1, Conv, [512, 1, 1]], | ||
30 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
31 | + [[-1, 6], 1, Concat, [1]], # cat backbone P4 | ||
32 | + [-1, 3, C3, [512, False]], # 13 | ||
33 | + | ||
34 | + [-1, 1, Conv, [256, 1, 1]], | ||
35 | + [-1, 1, nn.Upsample, [None, 2, 'nearest']], | ||
36 | + [[-1, 4], 1, Concat, [1]], # cat backbone P3 | ||
37 | + [-1, 3, C3, [256, False]], # 17 (P3/8-small) | ||
38 | + | ||
39 | + [-1, 1, Conv, [256, 3, 2]], | ||
40 | + [[-1, 14], 1, Concat, [1]], # cat head P4 | ||
41 | + [-1, 3, C3, [512, False]], # 20 (P4/16-medium) | ||
42 | + | ||
43 | + [-1, 1, Conv, [512, 3, 2]], | ||
44 | + [[-1, 10], 1, Concat, [1]], # cat head P5 | ||
45 | + [-1, 3, C3, [1024, False]], # 23 (P5/32-large) | ||
46 | + | ||
47 | + [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) | ||
48 | + ] |
code/yolo-RTMP/yolo_module/yolov5/test.py
0 → 100644
This diff is collapsed. Click to expand it.
code/yolo-RTMP/yolo_module/yolov5/train.py
0 → 100644
This diff is collapsed. Click to expand it.
File mode changed
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
1 | +# Activation functions | ||
2 | + | ||
3 | +import torch | ||
4 | +import torch.nn as nn | ||
5 | +import torch.nn.functional as F | ||
6 | + | ||
7 | + | ||
8 | +# SiLU https://arxiv.org/pdf/1606.08415.pdf ---------------------------------------------------------------------------- | ||
9 | +class SiLU(nn.Module): # export-friendly version of nn.SiLU() | ||
10 | + @staticmethod | ||
11 | + def forward(x): | ||
12 | + return x * torch.sigmoid(x) | ||
13 | + | ||
14 | + | ||
15 | +class Hardswish(nn.Module): # export-friendly version of nn.Hardswish() | ||
16 | + @staticmethod | ||
17 | + def forward(x): | ||
18 | + # return x * F.hardsigmoid(x) # for torchscript and CoreML | ||
19 | + return x * F.hardtanh(x + 3, 0., 6.) / 6. # for torchscript, CoreML and ONNX | ||
20 | + | ||
21 | + | ||
22 | +# Mish https://github.com/digantamisra98/Mish -------------------------------------------------------------------------- | ||
23 | +class Mish(nn.Module): | ||
24 | + @staticmethod | ||
25 | + def forward(x): | ||
26 | + return x * F.softplus(x).tanh() | ||
27 | + | ||
28 | + | ||
29 | +class MemoryEfficientMish(nn.Module): | ||
30 | + class F(torch.autograd.Function): | ||
31 | + @staticmethod | ||
32 | + def forward(ctx, x): | ||
33 | + ctx.save_for_backward(x) | ||
34 | + return x.mul(torch.tanh(F.softplus(x))) # x * tanh(ln(1 + exp(x))) | ||
35 | + | ||
36 | + @staticmethod | ||
37 | + def backward(ctx, grad_output): | ||
38 | + x = ctx.saved_tensors[0] | ||
39 | + sx = torch.sigmoid(x) | ||
40 | + fx = F.softplus(x).tanh() | ||
41 | + return grad_output * (fx + x * sx * (1 - fx * fx)) | ||
42 | + | ||
43 | + def forward(self, x): | ||
44 | + return self.F.apply(x) | ||
45 | + | ||
46 | + | ||
47 | +# FReLU https://arxiv.org/abs/2007.11824 ------------------------------------------------------------------------------- | ||
48 | +class FReLU(nn.Module): | ||
49 | + def __init__(self, c1, k=3): # ch_in, kernel | ||
50 | + super().__init__() | ||
51 | + self.conv = nn.Conv2d(c1, c1, k, 1, 1, groups=c1, bias=False) | ||
52 | + self.bn = nn.BatchNorm2d(c1) | ||
53 | + | ||
54 | + def forward(self, x): | ||
55 | + return torch.max(x, self.bn(self.conv(x))) | ||
56 | + | ||
57 | + | ||
58 | +# ACON https://arxiv.org/pdf/2009.04759.pdf ---------------------------------------------------------------------------- | ||
59 | +class AconC(nn.Module): | ||
60 | + r""" ACON activation (activate or not). | ||
61 | + AconC: (p1*x-p2*x) * sigmoid(beta*(p1*x-p2*x)) + p2*x, beta is a learnable parameter | ||
62 | + according to "Activate or Not: Learning Customized Activation" <https://arxiv.org/pdf/2009.04759.pdf>. | ||
63 | + """ | ||
64 | + | ||
65 | + def __init__(self, c1): | ||
66 | + super().__init__() | ||
67 | + self.p1 = nn.Parameter(torch.randn(1, c1, 1, 1)) | ||
68 | + self.p2 = nn.Parameter(torch.randn(1, c1, 1, 1)) | ||
69 | + self.beta = nn.Parameter(torch.ones(1, c1, 1, 1)) | ||
70 | + | ||
71 | + def forward(self, x): | ||
72 | + dpx = (self.p1 - self.p2) * x | ||
73 | + return dpx * torch.sigmoid(self.beta * dpx) + self.p2 * x | ||
74 | + | ||
75 | + | ||
76 | +class MetaAconC(nn.Module): | ||
77 | + r""" ACON activation (activate or not). | ||
78 | + MetaAconC: (p1*x-p2*x) * sigmoid(beta*(p1*x-p2*x)) + p2*x, beta is generated by a small network | ||
79 | + according to "Activate or Not: Learning Customized Activation" <https://arxiv.org/pdf/2009.04759.pdf>. | ||
80 | + """ | ||
81 | + | ||
82 | + def __init__(self, c1, k=1, s=1, r=16): # ch_in, kernel, stride, r | ||
83 | + super().__init__() | ||
84 | + c2 = max(r, c1 // r) | ||
85 | + self.p1 = nn.Parameter(torch.randn(1, c1, 1, 1)) | ||
86 | + self.p2 = nn.Parameter(torch.randn(1, c1, 1, 1)) | ||
87 | + self.fc1 = nn.Conv2d(c1, c2, k, s, bias=True) | ||
88 | + self.fc2 = nn.Conv2d(c2, c1, k, s, bias=True) | ||
89 | + # self.bn1 = nn.BatchNorm2d(c2) | ||
90 | + # self.bn2 = nn.BatchNorm2d(c1) | ||
91 | + | ||
92 | + def forward(self, x): | ||
93 | + y = x.mean(dim=2, keepdims=True).mean(dim=3, keepdims=True) | ||
94 | + # batch-size 1 bug/instabilities https://github.com/ultralytics/yolov5/issues/2891 | ||
95 | + # beta = torch.sigmoid(self.bn2(self.fc2(self.bn1(self.fc1(y))))) # bug/unstable | ||
96 | + beta = torch.sigmoid(self.fc2(self.fc1(y))) # bug patch BN layers removed | ||
97 | + dpx = (self.p1 - self.p2) * x | ||
98 | + return dpx * torch.sigmoid(beta * dpx) + self.p2 * x |
1 | +# Auto-anchor utils | ||
2 | + | ||
3 | +import numpy as np | ||
4 | +import torch | ||
5 | +import yaml | ||
6 | +from tqdm import tqdm | ||
7 | +from yolo_module.yolov5.utils.general import colorstr | ||
8 | + | ||
9 | + | ||
10 | +def check_anchor_order(m): | ||
11 | + # Check anchor order against stride order for YOLOv5 Detect() module m, and correct if necessary | ||
12 | + a = m.anchor_grid.prod(-1).view(-1) # anchor area | ||
13 | + da = a[-1] - a[0] # delta a | ||
14 | + ds = m.stride[-1] - m.stride[0] # delta s | ||
15 | + if da.sign() != ds.sign(): # same order | ||
16 | + print('Reversing anchor order') | ||
17 | + m.anchors[:] = m.anchors.flip(0) | ||
18 | + m.anchor_grid[:] = m.anchor_grid.flip(0) | ||
19 | + | ||
20 | + | ||
21 | +def check_anchors(dataset, model, thr=4.0, imgsz=640): | ||
22 | + # Check anchor fit to data, recompute if necessary | ||
23 | + prefix = colorstr('autoanchor: ') | ||
24 | + print(f'\n{prefix}Analyzing anchors... ', end='') | ||
25 | + m = model.module.model[-1] if hasattr(model, 'module') else model.model[-1] # Detect() | ||
26 | + shapes = imgsz * dataset.shapes / dataset.shapes.max(1, keepdims=True) | ||
27 | + scale = np.random.uniform(0.9, 1.1, size=(shapes.shape[0], 1)) # augment scale | ||
28 | + wh = torch.tensor(np.concatenate([l[:, 3:5] * s for s, l in zip(shapes * scale, dataset.labels)])).float() # wh | ||
29 | + | ||
30 | + def metric(k): # compute metric | ||
31 | + r = wh[:, None] / k[None] | ||
32 | + x = torch.min(r, 1. / r).min(2)[0] # ratio metric | ||
33 | + best = x.max(1)[0] # best_x | ||
34 | + aat = (x > 1. / thr).float().sum(1).mean() # anchors above threshold | ||
35 | + bpr = (best > 1. / thr).float().mean() # best possible recall | ||
36 | + return bpr, aat | ||
37 | + | ||
38 | + anchors = m.anchor_grid.clone().cpu().view(-1, 2) # current anchors | ||
39 | + bpr, aat = metric(anchors) | ||
40 | + print(f'anchors/target = {aat:.2f}, Best Possible Recall (BPR) = {bpr:.4f}', end='') | ||
41 | + if bpr < 0.98: # threshold to recompute | ||
42 | + print('. Attempting to improve anchors, please wait...') | ||
43 | + na = m.anchor_grid.numel() // 2 # number of anchors | ||
44 | + try: | ||
45 | + anchors = kmean_anchors(dataset, n=na, img_size=imgsz, thr=thr, gen=1000, verbose=False) | ||
46 | + except Exception as e: | ||
47 | + print(f'{prefix}ERROR: {e}') | ||
48 | + new_bpr = metric(anchors)[0] | ||
49 | + if new_bpr > bpr: # replace anchors | ||
50 | + anchors = torch.tensor(anchors, device=m.anchors.device).type_as(m.anchors) | ||
51 | + m.anchor_grid[:] = anchors.clone().view_as(m.anchor_grid) # for inference | ||
52 | + m.anchors[:] = anchors.clone().view_as(m.anchors) / m.stride.to(m.anchors.device).view(-1, 1, 1) # loss | ||
53 | + check_anchor_order(m) | ||
54 | + print(f'{prefix}New anchors saved to model. Update model *.yaml to use these anchors in the future.') | ||
55 | + else: | ||
56 | + print(f'{prefix}Original anchors better than new anchors. Proceeding with original anchors.') | ||
57 | + print('') # newline | ||
58 | + | ||
59 | + | ||
60 | +def kmean_anchors(path='./data/coco128.yaml', n=9, img_size=640, thr=4.0, gen=1000, verbose=True): | ||
61 | + """ Creates kmeans-evolved anchors from training dataset | ||
62 | + | ||
63 | + Arguments: | ||
64 | + path: path to dataset *.yaml, or a loaded dataset | ||
65 | + n: number of anchors | ||
66 | + img_size: image size used for training | ||
67 | + thr: anchor-label wh ratio threshold hyperparameter hyp['anchor_t'] used for training, default=4.0 | ||
68 | + gen: generations to evolve anchors using genetic algorithm | ||
69 | + verbose: print all results | ||
70 | + | ||
71 | + Return: | ||
72 | + k: kmeans evolved anchors | ||
73 | + | ||
74 | + Usage: | ||
75 | + from utils.autoanchor import *; _ = kmean_anchors() | ||
76 | + """ | ||
77 | + from scipy.cluster.vq import kmeans | ||
78 | + | ||
79 | + thr = 1. / thr | ||
80 | + prefix = colorstr('autoanchor: ') | ||
81 | + | ||
82 | + def metric(k, wh): # compute metrics | ||
83 | + r = wh[:, None] / k[None] | ||
84 | + x = torch.min(r, 1. / r).min(2)[0] # ratio metric | ||
85 | + # x = wh_iou(wh, torch.tensor(k)) # iou metric | ||
86 | + return x, x.max(1)[0] # x, best_x | ||
87 | + | ||
88 | + def anchor_fitness(k): # mutation fitness | ||
89 | + _, best = metric(torch.tensor(k, dtype=torch.float32), wh) | ||
90 | + return (best * (best > thr).float()).mean() # fitness | ||
91 | + | ||
92 | + def print_results(k): | ||
93 | + k = k[np.argsort(k.prod(1))] # sort small to large | ||
94 | + x, best = metric(k, wh0) | ||
95 | + bpr, aat = (best > thr).float().mean(), (x > thr).float().mean() * n # best possible recall, anch > thr | ||
96 | + print(f'{prefix}thr={thr:.2f}: {bpr:.4f} best possible recall, {aat:.2f} anchors past thr') | ||
97 | + print(f'{prefix}n={n}, img_size={img_size}, metric_all={x.mean():.3f}/{best.mean():.3f}-mean/best, ' | ||
98 | + f'past_thr={x[x > thr].mean():.3f}-mean: ', end='') | ||
99 | + for i, x in enumerate(k): | ||
100 | + print('%i,%i' % (round(x[0]), round(x[1])), end=', ' if i < len(k) - 1 else '\n') # use in *.cfg | ||
101 | + return k | ||
102 | + | ||
103 | + if isinstance(path, str): # *.yaml file | ||
104 | + with open(path) as f: | ||
105 | + data_dict = yaml.safe_load(f) # model dict | ||
106 | + from yolo_module.yolov5.utils.datasets import LoadImagesAndLabels | ||
107 | + dataset = LoadImagesAndLabels(data_dict['train'], augment=True, rect=True) | ||
108 | + else: | ||
109 | + dataset = path # dataset | ||
110 | + | ||
111 | + # Get label wh | ||
112 | + shapes = img_size * dataset.shapes / dataset.shapes.max(1, keepdims=True) | ||
113 | + wh0 = np.concatenate([l[:, 3:5] * s for s, l in zip(shapes, dataset.labels)]) # wh | ||
114 | + | ||
115 | + # Filter | ||
116 | + i = (wh0 < 3.0).any(1).sum() | ||
117 | + if i: | ||
118 | + print(f'{prefix}WARNING: Extremely small objects found. {i} of {len(wh0)} labels are < 3 pixels in size.') | ||
119 | + wh = wh0[(wh0 >= 2.0).any(1)] # filter > 2 pixels | ||
120 | + # wh = wh * (np.random.rand(wh.shape[0], 1) * 0.9 + 0.1) # multiply by random scale 0-1 | ||
121 | + | ||
122 | + # Kmeans calculation | ||
123 | + print(f'{prefix}Running kmeans for {n} anchors on {len(wh)} points...') | ||
124 | + s = wh.std(0) # sigmas for whitening | ||
125 | + k, dist = kmeans(wh / s, n, iter=30) # points, mean distance | ||
126 | + assert len(k) == n, print(f'{prefix}ERROR: scipy.cluster.vq.kmeans requested {n} points but returned only {len(k)}') | ||
127 | + k *= s | ||
128 | + wh = torch.tensor(wh, dtype=torch.float32) # filtered | ||
129 | + wh0 = torch.tensor(wh0, dtype=torch.float32) # unfiltered | ||
130 | + k = print_results(k) | ||
131 | + | ||
132 | + # Plot | ||
133 | + # k, d = [None] * 20, [None] * 20 | ||
134 | + # for i in tqdm(range(1, 21)): | ||
135 | + # k[i-1], d[i-1] = kmeans(wh / s, i) # points, mean distance | ||
136 | + # fig, ax = plt.subplots(1, 2, figsize=(14, 7), tight_layout=True) | ||
137 | + # ax = ax.ravel() | ||
138 | + # ax[0].plot(np.arange(1, 21), np.array(d) ** 2, marker='.') | ||
139 | + # fig, ax = plt.subplots(1, 2, figsize=(14, 7)) # plot wh | ||
140 | + # ax[0].hist(wh[wh[:, 0]<100, 0],400) | ||
141 | + # ax[1].hist(wh[wh[:, 1]<100, 1],400) | ||
142 | + # fig.savefig('wh.png', dpi=200) | ||
143 | + | ||
144 | + # Evolve | ||
145 | + npr = np.random | ||
146 | + f, sh, mp, s = anchor_fitness(k), k.shape, 0.9, 0.1 # fitness, generations, mutation prob, sigma | ||
147 | + pbar = tqdm(range(gen), desc=f'{prefix}Evolving anchors with Genetic Algorithm:') # progress bar | ||
148 | + for _ in pbar: | ||
149 | + v = np.ones(sh) | ||
150 | + while (v == 1).all(): # mutate until a change occurs (prevent duplicates) | ||
151 | + v = ((npr.random(sh) < mp) * npr.random() * npr.randn(*sh) * s + 1).clip(0.3, 3.0) | ||
152 | + kg = (k.copy() * v).clip(min=2.0) | ||
153 | + fg = anchor_fitness(kg) | ||
154 | + if fg > f: | ||
155 | + f, k = fg, kg.copy() | ||
156 | + pbar.desc = f'{prefix}Evolving anchors with Genetic Algorithm: fitness = {f:.4f}' | ||
157 | + if verbose: | ||
158 | + print_results(k) | ||
159 | + | ||
160 | + return print_results(k) |
File mode changed
1 | +# Resume all interrupted trainings in yolov5/ dir including DDP trainings | ||
2 | +# Usage: $ python utils/aws/resume.py | ||
3 | + | ||
4 | +import os | ||
5 | +import sys | ||
6 | +from pathlib import Path | ||
7 | + | ||
8 | +import torch | ||
9 | +import yaml | ||
10 | +from yolo_module.yolov5.utils.general import yolov5_in_syspath | ||
11 | + | ||
12 | +sys.path.append('./') # to run '$ python *.py' files in subdirectories | ||
13 | + | ||
14 | +port = 0 # --master_port | ||
15 | +path = Path('').resolve() | ||
16 | + | ||
17 | +for last in path.rglob('*/**/last.pt'): | ||
18 | + with yolov5_in_syspath(): | ||
19 | + ckpt = torch.load(last) | ||
20 | + if ckpt['optimizer'] is None: | ||
21 | + continue | ||
22 | + | ||
23 | + # Load opt.yaml | ||
24 | + with open(last.parent.parent / 'opt.yaml') as f: | ||
25 | + opt = yaml.safe_load(f) | ||
26 | + | ||
27 | + # Get device count | ||
28 | + d = opt['device'].split(',') # devices | ||
29 | + nd = len(d) # number of devices | ||
30 | + ddp = nd > 1 or (nd == 0 and torch.cuda.device_count() > 1) # distributed data parallel | ||
31 | + | ||
32 | + if ddp: # multi-GPU | ||
33 | + port += 1 | ||
34 | + cmd = f'python -m torch.distributed.launch --nproc_per_node {nd} --master_port {port} train.py --resume {last}' | ||
35 | + else: # single-GPU | ||
36 | + cmd = f'python train.py --resume {last}' | ||
37 | + | ||
38 | + cmd += ' > /dev/null 2>&1 &' # redirect output to dev/null and run in daemon thread | ||
39 | + print(cmd) | ||
40 | + os.system(cmd) |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 | +# Google utils: https://cloud.google.com/storage/docs/reference/libraries | ||
2 | + | ||
3 | +import os | ||
4 | +import platform | ||
5 | +import subprocess | ||
6 | +import time | ||
7 | +from pathlib import Path | ||
8 | + | ||
9 | +import requests | ||
10 | +import torch | ||
11 | + | ||
12 | + | ||
13 | +def gsutil_getsize(url=''): | ||
14 | + # gs://bucket/file size https://cloud.google.com/storage/docs/gsutil/commands/du | ||
15 | + s = subprocess.check_output(f'gsutil du {url}', shell=True).decode('utf-8') | ||
16 | + return eval(s.split(' ')[0]) if len(s) else 0 # bytes | ||
17 | + | ||
18 | + | ||
19 | +def attempt_download(file, repo='ultralytics/yolov5'): | ||
20 | + # Attempt file download if does not exist | ||
21 | + file = Path(str(file).strip().replace("'", '')) | ||
22 | + | ||
23 | + if not file.exists(): | ||
24 | + file.parent.mkdir(parents=True, exist_ok=True) # make parent dir (if required) | ||
25 | + try: | ||
26 | + response = requests.get(f'https://api.github.com/repos/{repo}/releases/latest').json() # github api | ||
27 | + assets = [x['name'] for x in response['assets']] # release assets, i.e. ['yolov5s.pt', 'yolov5m.pt', ...] | ||
28 | + tag = response['tag_name'] # i.e. 'v1.0' | ||
29 | + except: # fallback plan | ||
30 | + assets = ['yolov5s.pt', 'yolov5m.pt', 'yolov5l.pt', 'yolov5x.pt', | ||
31 | + 'yolov5s6.pt', 'yolov5m6.pt', 'yolov5l6.pt', 'yolov5x6.pt'] | ||
32 | + try: | ||
33 | + tag = subprocess.check_output('git tag', shell=True, stderr=subprocess.STDOUT).decode().split()[-1] | ||
34 | + except: | ||
35 | + tag = 'v5.0' # current release | ||
36 | + | ||
37 | + name = file.name | ||
38 | + if name in assets: | ||
39 | + msg = f'{file} missing, try downloading from https://github.com/{repo}/releases/' | ||
40 | + redundant = False # second download option | ||
41 | + try: # GitHub | ||
42 | + url = f'https://github.com/{repo}/releases/download/{tag}/{name}' | ||
43 | + print(f'Downloading {url} to {file}...') | ||
44 | + torch.hub.download_url_to_file(url, file) | ||
45 | + assert file.exists() and file.stat().st_size > 1E6 # check | ||
46 | + except Exception as e: # GCP | ||
47 | + print(f'Download error: {e}') | ||
48 | + assert redundant, 'No secondary mirror' | ||
49 | + url = f'https://storage.googleapis.com/{repo}/ckpt/{name}' | ||
50 | + print(f'Downloading {url} to {file}...') | ||
51 | + os.system(f"curl -L '{url}' -o '{file}' --retry 3 -C -") # curl download, retry and resume on fail | ||
52 | + finally: | ||
53 | + if not file.exists() or file.stat().st_size < 1E6: # check | ||
54 | + file.unlink(missing_ok=True) # remove partial downloads | ||
55 | + print(f'ERROR: Download failure: {msg}') | ||
56 | + print('') | ||
57 | + return | ||
58 | + | ||
59 | + | ||
60 | +def gdrive_download(id='16TiPfZj7htmTyhntwcZyEEAejOUxuT6m', file='tmp.zip'): | ||
61 | + # Downloads a file from Google Drive. from yolo_module.yolov5.utils.google_utils import *; gdrive_download() | ||
62 | + t = time.time() | ||
63 | + file = Path(file) | ||
64 | + cookie = Path('cookie') # gdrive cookie | ||
65 | + print(f'Downloading https://drive.google.com/uc?export=download&id={id} as {file}... ', end='') | ||
66 | + file.unlink(missing_ok=True) # remove existing file | ||
67 | + cookie.unlink(missing_ok=True) # remove existing cookie | ||
68 | + | ||
69 | + # Attempt file download | ||
70 | + out = "NUL" if platform.system() == "Windows" else "/dev/null" | ||
71 | + os.system(f'curl -c ./cookie -s -L "drive.google.com/uc?export=download&id={id}" > {out}') | ||
72 | + if os.path.exists('cookie'): # large file | ||
73 | + s = f'curl -Lb ./cookie "drive.google.com/uc?export=download&confirm={get_token()}&id={id}" -o {file}' | ||
74 | + else: # small file | ||
75 | + s = f'curl -s -L -o {file} "drive.google.com/uc?export=download&id={id}"' | ||
76 | + r = os.system(s) # execute, capture return | ||
77 | + cookie.unlink(missing_ok=True) # remove existing cookie | ||
78 | + | ||
79 | + # Error check | ||
80 | + if r != 0: | ||
81 | + file.unlink(missing_ok=True) # remove partial | ||
82 | + print('Download error ') # raise Exception('Download error') | ||
83 | + return r | ||
84 | + | ||
85 | + # Unzip if archive | ||
86 | + if file.suffix == '.zip': | ||
87 | + print('unzipping... ', end='') | ||
88 | + os.system(f'unzip -q {file}') # unzip | ||
89 | + file.unlink() # remove zip to free space | ||
90 | + | ||
91 | + print(f'Done ({time.time() - t:.1f}s)') | ||
92 | + return r | ||
93 | + | ||
94 | + | ||
95 | +def get_token(cookie="./cookie"): | ||
96 | + with open(cookie) as f: | ||
97 | + for line in f: | ||
98 | + if "download" in line: | ||
99 | + return line.split()[-1] | ||
100 | + return "" | ||
101 | + | ||
102 | +# def upload_blob(bucket_name, source_file_name, destination_blob_name): | ||
103 | +# # Uploads a file to a bucket | ||
104 | +# # https://cloud.google.com/storage/docs/uploading-objects#storage-upload-object-python | ||
105 | +# | ||
106 | +# storage_client = storage.Client() | ||
107 | +# bucket = storage_client.get_bucket(bucket_name) | ||
108 | +# blob = bucket.blob(destination_blob_name) | ||
109 | +# | ||
110 | +# blob.upload_from_filename(source_file_name) | ||
111 | +# | ||
112 | +# print('File {} uploaded to {}.'.format( | ||
113 | +# source_file_name, | ||
114 | +# destination_blob_name)) | ||
115 | +# | ||
116 | +# | ||
117 | +# def download_blob(bucket_name, source_blob_name, destination_file_name): | ||
118 | +# # Uploads a blob from a bucket | ||
119 | +# storage_client = storage.Client() | ||
120 | +# bucket = storage_client.get_bucket(bucket_name) | ||
121 | +# blob = bucket.blob(source_blob_name) | ||
122 | +# | ||
123 | +# blob.download_to_filename(destination_file_name) | ||
124 | +# | ||
125 | +# print('Blob {} downloaded to {}.'.format( | ||
126 | +# source_blob_name, | ||
127 | +# destination_file_name)) |
1 | +# Loss functions | ||
2 | + | ||
3 | +import torch | ||
4 | +import torch.nn as nn | ||
5 | +from yolo_module.yolov5.utils.general import bbox_iou | ||
6 | +from yolo_module.yolov5.utils.torch_utils import is_parallel | ||
7 | + | ||
8 | + | ||
9 | +def smooth_BCE(eps=0.1): # https://github.com/ultralytics/yolov3/issues/238#issuecomment-598028441 | ||
10 | + # return positive, negative label smoothing BCE targets | ||
11 | + return 1.0 - 0.5 * eps, 0.5 * eps | ||
12 | + | ||
13 | + | ||
14 | +class BCEBlurWithLogitsLoss(nn.Module): | ||
15 | + # BCEwithLogitLoss() with reduced missing label effects. | ||
16 | + def __init__(self, alpha=0.05): | ||
17 | + super(BCEBlurWithLogitsLoss, self).__init__() | ||
18 | + self.loss_fcn = nn.BCEWithLogitsLoss(reduction='none') # must be nn.BCEWithLogitsLoss() | ||
19 | + self.alpha = alpha | ||
20 | + | ||
21 | + def forward(self, pred, true): | ||
22 | + loss = self.loss_fcn(pred, true) | ||
23 | + pred = torch.sigmoid(pred) # prob from logits | ||
24 | + dx = pred - true # reduce only missing label effects | ||
25 | + # dx = (pred - true).abs() # reduce missing label and false label effects | ||
26 | + alpha_factor = 1 - torch.exp((dx - 1) / (self.alpha + 1e-4)) | ||
27 | + loss *= alpha_factor | ||
28 | + return loss.mean() | ||
29 | + | ||
30 | + | ||
31 | +class FocalLoss(nn.Module): | ||
32 | + # Wraps focal loss around existing loss_fcn(), i.e. criteria = FocalLoss(nn.BCEWithLogitsLoss(), gamma=1.5) | ||
33 | + def __init__(self, loss_fcn, gamma=1.5, alpha=0.25): | ||
34 | + super(FocalLoss, self).__init__() | ||
35 | + self.loss_fcn = loss_fcn # must be nn.BCEWithLogitsLoss() | ||
36 | + self.gamma = gamma | ||
37 | + self.alpha = alpha | ||
38 | + self.reduction = loss_fcn.reduction | ||
39 | + self.loss_fcn.reduction = 'none' # required to apply FL to each element | ||
40 | + | ||
41 | + def forward(self, pred, true): | ||
42 | + loss = self.loss_fcn(pred, true) | ||
43 | + # p_t = torch.exp(-loss) | ||
44 | + # loss *= self.alpha * (1.000001 - p_t) ** self.gamma # non-zero power for gradient stability | ||
45 | + | ||
46 | + # TF implementation https://github.com/tensorflow/addons/blob/v0.7.1/tensorflow_addons/losses/focal_loss.py | ||
47 | + pred_prob = torch.sigmoid(pred) # prob from logits | ||
48 | + p_t = true * pred_prob + (1 - true) * (1 - pred_prob) | ||
49 | + alpha_factor = true * self.alpha + (1 - true) * (1 - self.alpha) | ||
50 | + modulating_factor = (1.0 - p_t) ** self.gamma | ||
51 | + loss *= alpha_factor * modulating_factor | ||
52 | + | ||
53 | + if self.reduction == 'mean': | ||
54 | + return loss.mean() | ||
55 | + elif self.reduction == 'sum': | ||
56 | + return loss.sum() | ||
57 | + else: # 'none' | ||
58 | + return loss | ||
59 | + | ||
60 | + | ||
61 | +class QFocalLoss(nn.Module): | ||
62 | + # Wraps Quality focal loss around existing loss_fcn(), i.e. criteria = FocalLoss(nn.BCEWithLogitsLoss(), gamma=1.5) | ||
63 | + def __init__(self, loss_fcn, gamma=1.5, alpha=0.25): | ||
64 | + super(QFocalLoss, self).__init__() | ||
65 | + self.loss_fcn = loss_fcn # must be nn.BCEWithLogitsLoss() | ||
66 | + self.gamma = gamma | ||
67 | + self.alpha = alpha | ||
68 | + self.reduction = loss_fcn.reduction | ||
69 | + self.loss_fcn.reduction = 'none' # required to apply FL to each element | ||
70 | + | ||
71 | + def forward(self, pred, true): | ||
72 | + loss = self.loss_fcn(pred, true) | ||
73 | + | ||
74 | + pred_prob = torch.sigmoid(pred) # prob from logits | ||
75 | + alpha_factor = true * self.alpha + (1 - true) * (1 - self.alpha) | ||
76 | + modulating_factor = torch.abs(true - pred_prob) ** self.gamma | ||
77 | + loss *= alpha_factor * modulating_factor | ||
78 | + | ||
79 | + if self.reduction == 'mean': | ||
80 | + return loss.mean() | ||
81 | + elif self.reduction == 'sum': | ||
82 | + return loss.sum() | ||
83 | + else: # 'none' | ||
84 | + return loss | ||
85 | + | ||
86 | + | ||
87 | +class ComputeLoss: | ||
88 | + # Compute losses | ||
89 | + def __init__(self, model, autobalance=False): | ||
90 | + super(ComputeLoss, self).__init__() | ||
91 | + device = next(model.parameters()).device # get model device | ||
92 | + h = model.hyp # hyperparameters | ||
93 | + | ||
94 | + # Define criteria | ||
95 | + BCEcls = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([h['cls_pw']], device=device)) | ||
96 | + BCEobj = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([h['obj_pw']], device=device)) | ||
97 | + | ||
98 | + # Class label smoothing https://arxiv.org/pdf/1902.04103.pdf eqn 3 | ||
99 | + self.cp, self.cn = smooth_BCE(eps=h.get('label_smoothing', 0.0)) # positive, negative BCE targets | ||
100 | + | ||
101 | + # Focal loss | ||
102 | + g = h['fl_gamma'] # focal loss gamma | ||
103 | + if g > 0: | ||
104 | + BCEcls, BCEobj = FocalLoss(BCEcls, g), FocalLoss(BCEobj, g) | ||
105 | + | ||
106 | + det = model.module.model[-1] if is_parallel(model) else model.model[-1] # Detect() module | ||
107 | + self.balance = {3: [4.0, 1.0, 0.4]}.get(det.nl, [4.0, 1.0, 0.25, 0.06, .02]) # P3-P7 | ||
108 | + self.ssi = list(det.stride).index(16) if autobalance else 0 # stride 16 index | ||
109 | + self.BCEcls, self.BCEobj, self.gr, self.hyp, self.autobalance = BCEcls, BCEobj, model.gr, h, autobalance | ||
110 | + for k in 'na', 'nc', 'nl', 'anchors': | ||
111 | + setattr(self, k, getattr(det, k)) | ||
112 | + | ||
113 | + def __call__(self, p, targets): # predictions, targets, model | ||
114 | + device = targets.device | ||
115 | + lcls, lbox, lobj = torch.zeros(1, device=device), torch.zeros(1, device=device), torch.zeros(1, device=device) | ||
116 | + tcls, tbox, indices, anchors = self.build_targets(p, targets) # targets | ||
117 | + | ||
118 | + # Losses | ||
119 | + for i, pi in enumerate(p): # layer index, layer predictions | ||
120 | + b, a, gj, gi = indices[i] # image, anchor, gridy, gridx | ||
121 | + tobj = torch.zeros_like(pi[..., 0], device=device) # target obj | ||
122 | + | ||
123 | + n = b.shape[0] # number of targets | ||
124 | + if n: | ||
125 | + ps = pi[b, a, gj, gi] # prediction subset corresponding to targets | ||
126 | + | ||
127 | + # Regression | ||
128 | + pxy = ps[:, :2].sigmoid() * 2. - 0.5 | ||
129 | + pwh = (ps[:, 2:4].sigmoid() * 2) ** 2 * anchors[i] | ||
130 | + pbox = torch.cat((pxy, pwh), 1) # predicted box | ||
131 | + iou = bbox_iou(pbox.T, tbox[i], x1y1x2y2=False, CIoU=True) # iou(prediction, target) | ||
132 | + lbox += (1.0 - iou).mean() # iou loss | ||
133 | + | ||
134 | + # Objectness | ||
135 | + tobj[b, a, gj, gi] = (1.0 - self.gr) + self.gr * iou.detach().clamp(0).type(tobj.dtype) # iou ratio | ||
136 | + | ||
137 | + # Classification | ||
138 | + if self.nc > 1: # cls loss (only if multiple classes) | ||
139 | + t = torch.full_like(ps[:, 5:], self.cn, device=device) # targets | ||
140 | + t[range(n), tcls[i]] = self.cp | ||
141 | + lcls += self.BCEcls(ps[:, 5:], t) # BCE | ||
142 | + | ||
143 | + # Append targets to text file | ||
144 | + # with open('targets.txt', 'a') as file: | ||
145 | + # [file.write('%11.5g ' * 4 % tuple(x) + '\n') for x in torch.cat((txy[i], twh[i]), 1)] | ||
146 | + | ||
147 | + obji = self.BCEobj(pi[..., 4], tobj) | ||
148 | + lobj += obji * self.balance[i] # obj loss | ||
149 | + if self.autobalance: | ||
150 | + self.balance[i] = self.balance[i] * 0.9999 + 0.0001 / obji.detach().item() | ||
151 | + | ||
152 | + if self.autobalance: | ||
153 | + self.balance = [x / self.balance[self.ssi] for x in self.balance] | ||
154 | + lbox *= self.hyp['box'] | ||
155 | + lobj *= self.hyp['obj'] | ||
156 | + lcls *= self.hyp['cls'] | ||
157 | + bs = tobj.shape[0] # batch size | ||
158 | + | ||
159 | + loss = lbox + lobj + lcls | ||
160 | + return loss * bs, torch.cat((lbox, lobj, lcls, loss)).detach() | ||
161 | + | ||
162 | + def build_targets(self, p, targets): | ||
163 | + # Build targets for compute_loss(), input targets(image,class,x,y,w,h) | ||
164 | + na, nt = self.na, targets.shape[0] # number of anchors, targets | ||
165 | + tcls, tbox, indices, anch = [], [], [], [] | ||
166 | + gain = torch.ones(7, device=targets.device) # normalized to gridspace gain | ||
167 | + ai = torch.arange(na, device=targets.device).float().view(na, 1).repeat(1, nt) # same as .repeat_interleave(nt) | ||
168 | + targets = torch.cat((targets.repeat(na, 1, 1), ai[:, :, None]), 2) # append anchor indices | ||
169 | + | ||
170 | + g = 0.5 # bias | ||
171 | + off = torch.tensor([[0, 0], | ||
172 | + [1, 0], [0, 1], [-1, 0], [0, -1], # j,k,l,m | ||
173 | + # [1, 1], [1, -1], [-1, 1], [-1, -1], # jk,jm,lk,lm | ||
174 | + ], device=targets.device).float() * g # offsets | ||
175 | + | ||
176 | + for i in range(self.nl): | ||
177 | + anchors = self.anchors[i] | ||
178 | + gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]] # xyxy gain | ||
179 | + | ||
180 | + # Match targets to anchors | ||
181 | + t = targets * gain | ||
182 | + if nt: | ||
183 | + # Matches | ||
184 | + r = t[:, :, 4:6] / anchors[:, None] # wh ratio | ||
185 | + j = torch.max(r, 1. / r).max(2)[0] < self.hyp['anchor_t'] # compare | ||
186 | + # j = wh_iou(anchors, t[:, 4:6]) > model.hyp['iou_t'] # iou(3,n)=wh_iou(anchors(3,2), gwh(n,2)) | ||
187 | + t = t[j] # filter | ||
188 | + | ||
189 | + # Offsets | ||
190 | + gxy = t[:, 2:4] # grid xy | ||
191 | + gxi = gain[[2, 3]] - gxy # inverse | ||
192 | + j, k = ((gxy % 1. < g) & (gxy > 1.)).T | ||
193 | + l, m = ((gxi % 1. < g) & (gxi > 1.)).T | ||
194 | + j = torch.stack((torch.ones_like(j), j, k, l, m)) | ||
195 | + t = t.repeat((5, 1, 1))[j] | ||
196 | + offsets = (torch.zeros_like(gxy)[None] + off[:, None])[j] | ||
197 | + else: | ||
198 | + t = targets[0] | ||
199 | + offsets = 0 | ||
200 | + | ||
201 | + # Define | ||
202 | + b, c = t[:, :2].long().T # image, class | ||
203 | + gxy = t[:, 2:4] # grid xy | ||
204 | + gwh = t[:, 4:6] # grid wh | ||
205 | + gij = (gxy - offsets).long() | ||
206 | + gi, gj = gij.T # grid xy indices | ||
207 | + | ||
208 | + # Append | ||
209 | + a = t[:, 6].long() # anchor indices | ||
210 | + indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1))) # image, anchor, grid indices | ||
211 | + tbox.append(torch.cat((gxy - gij, gwh), 1)) # box | ||
212 | + anch.append(anchors[a]) # anchors | ||
213 | + tcls.append(c) # class | ||
214 | + | ||
215 | + return tcls, tbox, indices, anch |
1 | +# Model validation metrics | ||
2 | + | ||
3 | +from pathlib import Path | ||
4 | + | ||
5 | +import matplotlib.pyplot as plt | ||
6 | +import numpy as np | ||
7 | +import torch | ||
8 | + | ||
9 | +from . import general | ||
10 | + | ||
11 | + | ||
12 | +def fitness(x): | ||
13 | + # Model fitness as a weighted combination of metrics | ||
14 | + w = [0.0, 0.0, 0.1, 0.9] # weights for [P, R, mAP@0.5, mAP@0.5:0.95] | ||
15 | + return (x[:, :4] * w).sum(1) | ||
16 | + | ||
17 | + | ||
18 | +def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, save_dir='.', names=()): | ||
19 | + """ Compute the average precision, given the recall and precision curves. | ||
20 | + Source: https://github.com/rafaelpadilla/Object-Detection-Metrics. | ||
21 | + # Arguments | ||
22 | + tp: True positives (nparray, nx1 or nx10). | ||
23 | + conf: Objectness value from 0-1 (nparray). | ||
24 | + pred_cls: Predicted object classes (nparray). | ||
25 | + target_cls: True object classes (nparray). | ||
26 | + plot: Plot precision-recall curve at mAP@0.5 | ||
27 | + save_dir: Plot save directory | ||
28 | + # Returns | ||
29 | + The average precision as computed in py-faster-rcnn. | ||
30 | + """ | ||
31 | + | ||
32 | + # Sort by objectness | ||
33 | + i = np.argsort(-conf) | ||
34 | + tp, conf, pred_cls = tp[i], conf[i], pred_cls[i] | ||
35 | + | ||
36 | + # Find unique classes | ||
37 | + unique_classes = np.unique(target_cls) | ||
38 | + nc = unique_classes.shape[0] # number of classes, number of detections | ||
39 | + | ||
40 | + # Create Precision-Recall curve and compute AP for each class | ||
41 | + px, py = np.linspace(0, 1, 1000), [] # for plotting | ||
42 | + ap, p, r = np.zeros((nc, tp.shape[1])), np.zeros((nc, 1000)), np.zeros((nc, 1000)) | ||
43 | + for ci, c in enumerate(unique_classes): | ||
44 | + i = pred_cls == c | ||
45 | + n_l = (target_cls == c).sum() # number of labels | ||
46 | + n_p = i.sum() # number of predictions | ||
47 | + | ||
48 | + if n_p == 0 or n_l == 0: | ||
49 | + continue | ||
50 | + else: | ||
51 | + # Accumulate FPs and TPs | ||
52 | + fpc = (1 - tp[i]).cumsum(0) | ||
53 | + tpc = tp[i].cumsum(0) | ||
54 | + | ||
55 | + # Recall | ||
56 | + recall = tpc / (n_l + 1e-16) # recall curve | ||
57 | + r[ci] = np.interp(-px, -conf[i], recall[:, 0], left=0) # negative x, xp because xp decreases | ||
58 | + | ||
59 | + # Precision | ||
60 | + precision = tpc / (tpc + fpc) # precision curve | ||
61 | + p[ci] = np.interp(-px, -conf[i], precision[:, 0], left=1) # p at pr_score | ||
62 | + | ||
63 | + # AP from recall-precision curve | ||
64 | + for j in range(tp.shape[1]): | ||
65 | + ap[ci, j], mpre, mrec = compute_ap(recall[:, j], precision[:, j]) | ||
66 | + if plot and j == 0: | ||
67 | + py.append(np.interp(px, mrec, mpre)) # precision at mAP@0.5 | ||
68 | + | ||
69 | + # Compute F1 (harmonic mean of precision and recall) | ||
70 | + f1 = 2 * p * r / (p + r + 1e-16) | ||
71 | + if plot: | ||
72 | + plot_pr_curve(px, py, ap, Path(save_dir) / 'PR_curve.png', names) | ||
73 | + plot_mc_curve(px, f1, Path(save_dir) / 'F1_curve.png', names, ylabel='F1') | ||
74 | + plot_mc_curve(px, p, Path(save_dir) / 'P_curve.png', names, ylabel='Precision') | ||
75 | + plot_mc_curve(px, r, Path(save_dir) / 'R_curve.png', names, ylabel='Recall') | ||
76 | + | ||
77 | + i = f1.mean(0).argmax() # max F1 index | ||
78 | + return p[:, i], r[:, i], ap, f1[:, i], unique_classes.astype('int32') | ||
79 | + | ||
80 | + | ||
81 | +def compute_ap(recall, precision): | ||
82 | + """ Compute the average precision, given the recall and precision curves | ||
83 | + # Arguments | ||
84 | + recall: The recall curve (list) | ||
85 | + precision: The precision curve (list) | ||
86 | + # Returns | ||
87 | + Average precision, precision curve, recall curve | ||
88 | + """ | ||
89 | + | ||
90 | + # Append sentinel values to beginning and end | ||
91 | + mrec = np.concatenate(([0.], recall, [recall[-1] + 0.01])) | ||
92 | + mpre = np.concatenate(([1.], precision, [0.])) | ||
93 | + | ||
94 | + # Compute the precision envelope | ||
95 | + mpre = np.flip(np.maximum.accumulate(np.flip(mpre))) | ||
96 | + | ||
97 | + # Integrate area under curve | ||
98 | + method = 'interp' # methods: 'continuous', 'interp' | ||
99 | + if method == 'interp': | ||
100 | + x = np.linspace(0, 1, 101) # 101-point interp (COCO) | ||
101 | + ap = np.trapz(np.interp(x, mrec, mpre), x) # integrate | ||
102 | + else: # 'continuous' | ||
103 | + i = np.where(mrec[1:] != mrec[:-1])[0] # points where x axis (recall) changes | ||
104 | + ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) # area under curve | ||
105 | + | ||
106 | + return ap, mpre, mrec | ||
107 | + | ||
108 | + | ||
109 | +class ConfusionMatrix: | ||
110 | + # Updated version of https://github.com/kaanakan/object_detection_confusion_matrix | ||
111 | + def __init__(self, nc, conf=0.25, iou_thres=0.45): | ||
112 | + self.matrix = np.zeros((nc + 1, nc + 1)) | ||
113 | + self.nc = nc # number of classes | ||
114 | + self.conf = conf | ||
115 | + self.iou_thres = iou_thres | ||
116 | + | ||
117 | + def process_batch(self, detections, labels): | ||
118 | + """ | ||
119 | + Return intersection-over-union (Jaccard index) of boxes. | ||
120 | + Both sets of boxes are expected to be in (x1, y1, x2, y2) format. | ||
121 | + Arguments: | ||
122 | + detections (Array[N, 6]), x1, y1, x2, y2, conf, class | ||
123 | + labels (Array[M, 5]), class, x1, y1, x2, y2 | ||
124 | + Returns: | ||
125 | + None, updates confusion matrix accordingly | ||
126 | + """ | ||
127 | + detections = detections[detections[:, 4] > self.conf] | ||
128 | + gt_classes = labels[:, 0].int() | ||
129 | + detection_classes = detections[:, 5].int() | ||
130 | + iou = general.box_iou(labels[:, 1:], detections[:, :4]) | ||
131 | + | ||
132 | + x = torch.where(iou > self.iou_thres) | ||
133 | + if x[0].shape[0]: | ||
134 | + matches = torch.cat((torch.stack(x, 1), iou[x[0], x[1]][:, None]), 1).cpu().numpy() | ||
135 | + if x[0].shape[0] > 1: | ||
136 | + matches = matches[matches[:, 2].argsort()[::-1]] | ||
137 | + matches = matches[np.unique(matches[:, 1], return_index=True)[1]] | ||
138 | + matches = matches[matches[:, 2].argsort()[::-1]] | ||
139 | + matches = matches[np.unique(matches[:, 0], return_index=True)[1]] | ||
140 | + else: | ||
141 | + matches = np.zeros((0, 3)) | ||
142 | + | ||
143 | + n = matches.shape[0] > 0 | ||
144 | + m0, m1, _ = matches.transpose().astype(np.int16) | ||
145 | + for i, gc in enumerate(gt_classes): | ||
146 | + j = m0 == i | ||
147 | + if n and sum(j) == 1: | ||
148 | + self.matrix[detection_classes[m1[j]], gc] += 1 # correct | ||
149 | + else: | ||
150 | + self.matrix[self.nc, gc] += 1 # background FP | ||
151 | + | ||
152 | + if n: | ||
153 | + for i, dc in enumerate(detection_classes): | ||
154 | + if not any(m1 == i): | ||
155 | + self.matrix[dc, self.nc] += 1 # background FN | ||
156 | + | ||
157 | + def matrix(self): | ||
158 | + return self.matrix | ||
159 | + | ||
160 | + def plot(self, save_dir='', names=()): | ||
161 | + try: | ||
162 | + import seaborn as sn | ||
163 | + | ||
164 | + array = self.matrix / (self.matrix.sum(0).reshape(1, self.nc + 1) + 1E-6) # normalize | ||
165 | + array[array < 0.005] = np.nan # don't annotate (would appear as 0.00) | ||
166 | + | ||
167 | + fig = plt.figure(figsize=(12, 9), tight_layout=True) | ||
168 | + sn.set(font_scale=1.0 if self.nc < 50 else 0.8) # for label size | ||
169 | + labels = (0 < len(names) < 99) and len(names) == self.nc # apply names to ticklabels | ||
170 | + sn.heatmap(array, annot=self.nc < 30, annot_kws={"size": 8}, cmap='Blues', fmt='.2f', square=True, | ||
171 | + xticklabels=names + ['background FP'] if labels else "auto", | ||
172 | + yticklabels=names + ['background FN'] if labels else "auto").set_facecolor((1, 1, 1)) | ||
173 | + fig.axes[0].set_xlabel('True') | ||
174 | + fig.axes[0].set_ylabel('Predicted') | ||
175 | + fig.savefig(Path(save_dir) / 'confusion_matrix.png', dpi=250) | ||
176 | + except Exception as e: | ||
177 | + pass | ||
178 | + | ||
179 | + def print(self): | ||
180 | + for i in range(self.nc + 1): | ||
181 | + print(' '.join(map(str, self.matrix[i]))) | ||
182 | + | ||
183 | + | ||
184 | +# Plots ---------------------------------------------------------------------------------------------------------------- | ||
185 | + | ||
186 | +def plot_pr_curve(px, py, ap, save_dir='pr_curve.png', names=()): | ||
187 | + # Precision-recall curve | ||
188 | + fig, ax = plt.subplots(1, 1, figsize=(9, 6), tight_layout=True) | ||
189 | + py = np.stack(py, axis=1) | ||
190 | + | ||
191 | + if 0 < len(names) < 21: # display per-class legend if < 21 classes | ||
192 | + for i, y in enumerate(py.T): | ||
193 | + ax.plot(px, y, linewidth=1, label=f'{names[i]} {ap[i, 0]:.3f}') # plot(recall, precision) | ||
194 | + else: | ||
195 | + ax.plot(px, py, linewidth=1, color='grey') # plot(recall, precision) | ||
196 | + | ||
197 | + ax.plot(px, py.mean(1), linewidth=3, color='blue', label='all classes %.3f mAP@0.5' % ap[:, 0].mean()) | ||
198 | + ax.set_xlabel('Recall') | ||
199 | + ax.set_ylabel('Precision') | ||
200 | + ax.set_xlim(0, 1) | ||
201 | + ax.set_ylim(0, 1) | ||
202 | + plt.legend(bbox_to_anchor=(1.04, 1), loc="upper left") | ||
203 | + fig.savefig(Path(save_dir), dpi=250) | ||
204 | + | ||
205 | + | ||
206 | +def plot_mc_curve(px, py, save_dir='mc_curve.png', names=(), xlabel='Confidence', ylabel='Metric'): | ||
207 | + # Metric-confidence curve | ||
208 | + fig, ax = plt.subplots(1, 1, figsize=(9, 6), tight_layout=True) | ||
209 | + | ||
210 | + if 0 < len(names) < 21: # display per-class legend if < 21 classes | ||
211 | + for i, y in enumerate(py): | ||
212 | + ax.plot(px, y, linewidth=1, label=f'{names[i]}') # plot(confidence, metric) | ||
213 | + else: | ||
214 | + ax.plot(px, py.T, linewidth=1, color='grey') # plot(confidence, metric) | ||
215 | + | ||
216 | + y = py.mean(0) | ||
217 | + ax.plot(px, y, linewidth=3, color='blue', label=f'all classes {y.max():.2f} at {px[y.argmax()]:.3f}') | ||
218 | + ax.set_xlabel(xlabel) | ||
219 | + ax.set_ylabel(ylabel) | ||
220 | + ax.set_xlim(0, 1) | ||
221 | + ax.set_ylim(0, 1) | ||
222 | + plt.legend(bbox_to_anchor=(1.04, 1), loc="upper left") | ||
223 | + fig.savefig(Path(save_dir), dpi=250) |
File mode changed
1 | +from pathlib import Path | ||
2 | + | ||
3 | +from yolo_module.yolov5.utils.general import colorstr | ||
4 | + | ||
5 | +try: | ||
6 | + import neptune.new as neptune | ||
7 | +except ImportError: | ||
8 | + neptune = None | ||
9 | + | ||
10 | + | ||
11 | +class NeptuneLogger: | ||
12 | + def __init__(self, opt, name, data_dict, job_type='Training'): | ||
13 | + # Pre-training routine -- | ||
14 | + self.job_type = job_type | ||
15 | + self.neptune, self.neptune_run, self.data_dict = neptune, None, data_dict | ||
16 | + | ||
17 | + if self.neptune and opt.neptune_token: | ||
18 | + self.neptune_run = neptune.init(api_token=opt.neptune_token, | ||
19 | + project=opt.neptune_project, | ||
20 | + name=name) | ||
21 | + if self.neptune_run: | ||
22 | + if self.job_type == 'Training': | ||
23 | + if not opt.resume: | ||
24 | + neptune_data_dict = data_dict | ||
25 | + self.neptune_run["opt"] = vars(opt) | ||
26 | + self.neptune_run["data_dict"] = neptune_data_dict | ||
27 | + self.data_dict = self.setup_training(data_dict) | ||
28 | + prefix = colorstr('neptune: ') | ||
29 | + print(f"{prefix}NeptuneAI logging initiated successfully.") | ||
30 | + else: | ||
31 | + #prefix = colorstr('neptune: ') | ||
32 | + #print( | ||
33 | + # f"{prefix}Install NeptuneAI for YOLOv5 logging with 'pip install neptune-client' (recommended)") | ||
34 | + pass | ||
35 | + | ||
36 | + def setup_training(self, data_dict): | ||
37 | + self.log_dict, self.current_epoch = {}, 0 # Logging Constants | ||
38 | + return data_dict | ||
39 | + | ||
40 | + def log(self, log_dict): | ||
41 | + if self.neptune_run: | ||
42 | + for key, value in log_dict.items(): | ||
43 | + self.log_dict[key] = value | ||
44 | + | ||
45 | + def end_epoch(self, best_result=False): | ||
46 | + if self.neptune_run: | ||
47 | + for key, value in self.log_dict.items(): | ||
48 | + self.neptune_run[key].log(value) | ||
49 | + self.log_dict = {} | ||
50 | + | ||
51 | + def finish_run(self): | ||
52 | + if self.neptune_run: | ||
53 | + if self.log_dict: | ||
54 | + for key, value in self.log_dict.items(): | ||
55 | + self.neptune_run[key].log(value) | ||
56 | + self.neptune_run.stop() |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
File mode changed
1 | +import argparse | ||
2 | + | ||
3 | +import yaml | ||
4 | + | ||
5 | +from wandb_utils import WandbLogger | ||
6 | + | ||
7 | +WANDB_ARTIFACT_PREFIX = 'wandb-artifact://' | ||
8 | + | ||
9 | + | ||
10 | +def create_dataset_artifact(opt): | ||
11 | + with open(opt.data) as f: | ||
12 | + data = yaml.safe_load(f) # data dict | ||
13 | + logger = WandbLogger(opt, '', None, data, job_type='Dataset Creation') | ||
14 | + | ||
15 | + | ||
16 | +if __name__ == '__main__': | ||
17 | + parser = argparse.ArgumentParser() | ||
18 | + parser.add_argument('--data', type=str, default='data/coco128.yaml', help='data.yaml path') | ||
19 | + parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset') | ||
20 | + parser.add_argument('--project', type=str, default='YOLOv5', help='name of W&B Project') | ||
21 | + opt = parser.parse_args() | ||
22 | + opt.resume = False # Explicitly disallow resume check for dataset upload job | ||
23 | + | ||
24 | + create_dataset_artifact(opt) |
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment