김우재

feat: add RTMP-based service code

Showing 91 changed files with 3722 additions and 1 deletions
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 ![Demo](./assets/demo.gif) 3 ![Demo](./assets/demo.gif)
4 4
5 -## Architecture 5 +## Architectures
6 6
7 ![Architecture 1](./assets/architecture1.png) 7 ![Architecture 1](./assets/architecture1.png)
8 8
......
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
This diff is collapsed. Click to expand it.
1 +# Include the README
2 +include *.md
3 +
4 +# Include the license file
5 +include LICENSE
6 +
7 +# Include setup.py
8 +include setup.py
9 +
10 +# Include the data files
11 +recursive-include yolov5/data *
12 +
13 +# Include the yml files in models folder
14 +recursive-include yolov5/models *
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 +<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>
1 +[egg_info]
2 +tag_build =
3 +tag_date = 0
4 +
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 +[console_scripts]
2 +yolo_detect = yolov5.detect:main
3 +yolo_export = yolov5.models.export:main
4 +yolo_test = yolov5.test:main
5 +yolo_train = yolov5.train:main
6 +
1 +matplotlib>=3.2.2
2 +numpy>=1.18.5
3 +opencv-python>=4.1.2
4 +Pillow
5 +PyYAML>=5.3.1
6 +scipy>=1.4.1
7 +torch>=1.7.0
8 +torchvision>=0.8.1
9 +tqdm>=4.41.0
10 +tensorboard>=2.4.1
11 +seaborn>=0.11.0
12 +pandas
13 +thop
14 +pycocotools>=2.0
15 +
16 +[tests]
17 +pytest
1 +from yolo_module.yolov5.helpers import YOLOv5
2 +from yolo_module.yolov5.helpers import load_model as load
3 +
4 +__version__ = "5.0.5"
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)
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' ]
This diff is collapsed. Click to expand it.
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)
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()
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 + ]
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
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)
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)
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.
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)