kisa-misa commited on
Commit
2283b14
1 Parent(s): 68148c4

Upload 213 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +7 -0
  2. .gitignore +150 -0
  3. .pre-commit-config.yaml +65 -0
  4. CONTRIBUTING.md +113 -0
  5. MANIFEST.in +5 -0
  6. README.md +82 -12
  7. YOLOv8_DeepSORT_TRACKING_SCRIPT.ipynb +3 -0
  8. YOLOv8_Detection_Tracking_CustomData_Complete.ipynb +3 -0
  9. figure/figure1.png +3 -0
  10. figure/figure2.png +3 -0
  11. figure/figure3.png +3 -0
  12. mkdocs.yml +95 -0
  13. requirements.txt +46 -0
  14. setup.cfg +54 -0
  15. setup.py +53 -0
  16. ultralytics/__init__.py +9 -0
  17. ultralytics/hub/__init__.py +133 -0
  18. ultralytics/hub/auth.py +70 -0
  19. ultralytics/hub/session.py +122 -0
  20. ultralytics/hub/utils.py +150 -0
  21. ultralytics/models/README.md +36 -0
  22. ultralytics/models/v3/yolov3-spp.yaml +47 -0
  23. ultralytics/models/v3/yolov3-tiny.yaml +38 -0
  24. ultralytics/models/v3/yolov3.yaml +47 -0
  25. ultralytics/models/v5/yolov5l.yaml +44 -0
  26. ultralytics/models/v5/yolov5m.yaml +44 -0
  27. ultralytics/models/v5/yolov5n.yaml +44 -0
  28. ultralytics/models/v5/yolov5s.yaml +45 -0
  29. ultralytics/models/v5/yolov5x.yaml +44 -0
  30. ultralytics/models/v8/cls/yolov8l-cls.yaml +23 -0
  31. ultralytics/models/v8/cls/yolov8m-cls.yaml +23 -0
  32. ultralytics/models/v8/cls/yolov8n-cls.yaml +23 -0
  33. ultralytics/models/v8/cls/yolov8s-cls.yaml +23 -0
  34. ultralytics/models/v8/cls/yolov8x-cls.yaml +23 -0
  35. ultralytics/models/v8/seg/yolov8l-seg.yaml +40 -0
  36. ultralytics/models/v8/seg/yolov8m-seg.yaml +40 -0
  37. ultralytics/models/v8/seg/yolov8n-seg.yaml +40 -0
  38. ultralytics/models/v8/seg/yolov8s-seg.yaml +40 -0
  39. ultralytics/models/v8/seg/yolov8x-seg.yaml +40 -0
  40. ultralytics/models/v8/yolov8l.yaml +40 -0
  41. ultralytics/models/v8/yolov8m.yaml +40 -0
  42. ultralytics/models/v8/yolov8n.yaml +40 -0
  43. ultralytics/models/v8/yolov8s.yaml +40 -0
  44. ultralytics/models/v8/yolov8x.yaml +40 -0
  45. ultralytics/models/v8/yolov8x6.yaml +50 -0
  46. ultralytics/nn/__init__.py +0 -0
  47. ultralytics/nn/autobackend.py +381 -0
  48. ultralytics/nn/modules.py +688 -0
  49. ultralytics/nn/tasks.py +416 -0
  50. ultralytics/yolo/cli.py +52 -0
.gitattributes CHANGED
@@ -32,3 +32,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ figure/figure1.png filter=lfs diff=lfs merge=lfs -text
36
+ figure/figure2.png filter=lfs diff=lfs merge=lfs -text
37
+ figure/figure3.png filter=lfs diff=lfs merge=lfs -text
38
+ ultralytics/yolo/v8/detect/deep_sort_pytorch/deep_sort/deep/checkpoint/ckpt.t7 filter=lfs diff=lfs merge=lfs -text
39
+ ultralytics/yolo/v8/detect/night_motorbikes.mp4 filter=lfs diff=lfs merge=lfs -text
40
+ YOLOv8_DeepSORT_TRACKING_SCRIPT.ipynb filter=lfs diff=lfs merge=lfs -text
41
+ YOLOv8_Detection_Tracking_CustomData_Complete.ipynb filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ .python-version
86
+
87
+ # pipenv
88
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
90
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
91
+ # install all needed dependencies.
92
+ #Pipfile.lock
93
+
94
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95
+ __pypackages__/
96
+
97
+ # Celery stuff
98
+ celerybeat-schedule
99
+ celerybeat.pid
100
+
101
+ # SageMath parsed files
102
+ *.sage.py
103
+
104
+ # Environments
105
+ .env
106
+ .venv
107
+ env/
108
+ venv/
109
+ ENV/
110
+ env.bak/
111
+ venv.bak/
112
+
113
+ # Spyder project settings
114
+ .spyderproject
115
+ .spyproject
116
+
117
+ # Rope project settings
118
+ .ropeproject
119
+
120
+ # mkdocs documentation
121
+ /site
122
+
123
+ # mypy
124
+ .mypy_cache/
125
+ .dmypy.json
126
+ dmypy.json
127
+
128
+ # Pyre type checker
129
+ .pyre/
130
+
131
+ # datasets and projects
132
+ datasets/
133
+ runs/
134
+ wandb/
135
+
136
+ .DS_Store
137
+
138
+ # Neural Network weights -----------------------------------------------------------------------------------------------
139
+ *.weights
140
+ *.pt
141
+ *.pb
142
+ *.onnx
143
+ *.engine
144
+ *.mlmodel
145
+ *.torchscript
146
+ *.tflite
147
+ *.h5
148
+ *_saved_model/
149
+ *_web_model/
150
+ *_openvino_model/
.pre-commit-config.yaml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Define hooks for code formations
2
+ # Will be applied on any updated commit files if a user has installed and linked commit hook
3
+
4
+ default_language_version:
5
+ python: python3.8
6
+
7
+ exclude: 'docs/'
8
+ # Define bot property if installed via https://github.com/marketplace/pre-commit-ci
9
+ ci:
10
+ autofix_prs: true
11
+ autoupdate_commit_msg: '[pre-commit.ci] pre-commit suggestions'
12
+ autoupdate_schedule: monthly
13
+ # submodules: true
14
+
15
+ repos:
16
+ - repo: https://github.com/pre-commit/pre-commit-hooks
17
+ rev: v4.3.0
18
+ hooks:
19
+ # - id: end-of-file-fixer
20
+ - id: trailing-whitespace
21
+ - id: check-case-conflict
22
+ - id: check-yaml
23
+ - id: check-toml
24
+ - id: pretty-format-json
25
+ - id: check-docstring-first
26
+
27
+ - repo: https://github.com/asottile/pyupgrade
28
+ rev: v2.37.3
29
+ hooks:
30
+ - id: pyupgrade
31
+ name: Upgrade code
32
+ args: [ --py37-plus ]
33
+
34
+ - repo: https://github.com/PyCQA/isort
35
+ rev: 5.10.1
36
+ hooks:
37
+ - id: isort
38
+ name: Sort imports
39
+
40
+ - repo: https://github.com/pre-commit/mirrors-yapf
41
+ rev: v0.32.0
42
+ hooks:
43
+ - id: yapf
44
+ name: YAPF formatting
45
+
46
+ - repo: https://github.com/executablebooks/mdformat
47
+ rev: 0.7.16
48
+ hooks:
49
+ - id: mdformat
50
+ name: MD formatting
51
+ additional_dependencies:
52
+ - mdformat-gfm
53
+ - mdformat-black
54
+ # exclude: "README.md|README.zh-CN.md|CONTRIBUTING.md"
55
+
56
+ - repo: https://github.com/PyCQA/flake8
57
+ rev: 5.0.4
58
+ hooks:
59
+ - id: flake8
60
+ name: PEP8
61
+
62
+ #- repo: https://github.com/asottile/yesqa
63
+ # rev: v1.4.0
64
+ # hooks:
65
+ # - id: yesqa
CONTRIBUTING.md ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Contributing to YOLOv8 🚀
2
+
3
+ We love your input! We want to make contributing to YOLOv8 as easy and transparent as possible, whether it's:
4
+
5
+ - Reporting a bug
6
+ - Discussing the current state of the code
7
+ - Submitting a fix
8
+ - Proposing a new feature
9
+ - Becoming a maintainer
10
+
11
+ YOLOv8 works so well due to our combined community effort, and for every small improvement you contribute you will be
12
+ helping push the frontiers of what's possible in AI 😃!
13
+
14
+ ## Submitting a Pull Request (PR) 🛠️
15
+
16
+ Submitting a PR is easy! This example shows how to submit a PR for updating `requirements.txt` in 4 steps:
17
+
18
+ ### 1. Select File to Update
19
+
20
+ Select `requirements.txt` to update by clicking on it in GitHub.
21
+
22
+ <p align="center"><img width="800" alt="PR_step1" src="https://user-images.githubusercontent.com/26833433/122260847-08be2600-ced4-11eb-828b-8287ace4136c.png"></p>
23
+
24
+ ### 2. Click 'Edit this file'
25
+
26
+ Button is in top-right corner.
27
+
28
+ <p align="center"><img width="800" alt="PR_step2" src="https://user-images.githubusercontent.com/26833433/122260844-06f46280-ced4-11eb-9eec-b8a24be519ca.png"></p>
29
+
30
+ ### 3. Make Changes
31
+
32
+ Change `matplotlib` version from `3.2.2` to `3.3`.
33
+
34
+ <p align="center"><img width="800" alt="PR_step3" src="https://user-images.githubusercontent.com/26833433/122260853-0a87e980-ced4-11eb-9fd2-3650fb6e0842.png"></p>
35
+
36
+ ### 4. Preview Changes and Submit PR
37
+
38
+ Click on the **Preview changes** tab to verify your updates. At the bottom of the screen select 'Create a **new branch**
39
+ for this commit', assign your branch a descriptive name such as `fix/matplotlib_version` and click the green **Propose
40
+ changes** button. All done, your PR is now submitted to YOLOv8 for review and approval 😃!
41
+
42
+ <p align="center"><img width="800" alt="PR_step4" src="https://user-images.githubusercontent.com/26833433/122260856-0b208000-ced4-11eb-8e8e-77b6151cbcc3.png"></p>
43
+
44
+ ### PR recommendations
45
+
46
+ To allow your work to be integrated as seamlessly as possible, we advise you to:
47
+
48
+ - ✅ Verify your PR is **up-to-date** with `ultralytics/ultralytics` `master` branch. If your PR is behind you can update
49
+ your code by clicking the 'Update branch' button or by running `git pull` and `git merge master` locally.
50
+
51
+ <p align="center"><img width="751" alt="Screenshot 2022-08-29 at 22 47 15" src="https://user-images.githubusercontent.com/26833433/187295893-50ed9f44-b2c9-4138-a614-de69bd1753d7.png"></p>
52
+
53
+ - ✅ Verify all YOLOv8 Continuous Integration (CI) **checks are passing**.
54
+
55
+ <p align="center"><img width="751" alt="Screenshot 2022-08-29 at 22 47 03" src="https://user-images.githubusercontent.com/26833433/187296922-545c5498-f64a-4d8c-8300-5fa764360da6.png"></p>
56
+
57
+ - ✅ Reduce changes to the absolute **minimum** required for your bug fix or feature addition. _"It is not daily increase
58
+ but daily decrease, hack away the unessential. The closer to the source, the less wastage there is."_ — Bruce Lee
59
+
60
+ ### Docstrings
61
+
62
+ Not all functions or classes require docstrings but when they do, we follow [google-stlye docstrings format](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings). Here is an example:
63
+
64
+ ```python
65
+ """
66
+ What the function does - performs nms on given detection predictions
67
+
68
+ Args:
69
+ arg1: The description of the 1st argument
70
+ arg2: The description of the 2nd argument
71
+
72
+ Returns:
73
+ What the function returns. Empty if nothing is returned
74
+
75
+ Raises:
76
+ Exception Class: When and why this exception can be raised by the function.
77
+ """
78
+ ```
79
+
80
+ ## Submitting a Bug Report 🐛
81
+
82
+ If you spot a problem with YOLOv8 please submit a Bug Report!
83
+
84
+ For us to start investigating a possible problem we need to be able to reproduce it ourselves first. We've created a few
85
+ short guidelines below to help users provide what we need in order to get started.
86
+
87
+ When asking a question, people will be better able to provide help if you provide **code** that they can easily
88
+ understand and use to **reproduce** the problem. This is referred to by community members as creating
89
+ a [minimum reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). Your code that reproduces
90
+ the problem should be:
91
+
92
+ - ✅ **Minimal** – Use as little code as possible that still produces the same problem
93
+ - ✅ **Complete** – Provide **all** parts someone else needs to reproduce your problem in the question itself
94
+ - ✅ **Reproducible** – Test the code you're about to provide to make sure it reproduces the problem
95
+
96
+ In addition to the above requirements, for [Ultralytics](https://ultralytics.com/) to provide assistance your code
97
+ should be:
98
+
99
+ - ✅ **Current** – Verify that your code is up-to-date with current
100
+ GitHub [master](https://github.com/ultralytics/ultralytics/tree/main), and if necessary `git pull` or `git clone` a new
101
+ copy to ensure your problem has not already been resolved by previous commits.
102
+ - ✅ **Unmodified** – Your problem must be reproducible without any modifications to the codebase in this
103
+ repository. [Ultralytics](https://ultralytics.com/) does not provide support for custom code ⚠️.
104
+
105
+ If you believe your problem meets all of the above criteria, please close this issue and raise a new one using the 🐛
106
+ **Bug Report** [template](https://github.com/ultralytics/ultralytics/issues/new/choose) and providing
107
+ a [minimum reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) to help us better
108
+ understand and diagnose your problem.
109
+
110
+ ## License
111
+
112
+ By contributing, you agree that your contributions will be licensed under
113
+ the [GPL-3.0 license](https://choosealicense.com/licenses/gpl-3.0/)
MANIFEST.in ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ include *.md
2
+ include requirements.txt
3
+ include LICENSE
4
+ include setup.py
5
+ recursive-include ultralytics *.yaml
README.md CHANGED
@@ -1,12 +1,82 @@
1
- ---
2
- title: YOLOv8 Real Time
3
- emoji: 🏢
4
- colorFrom: pink
5
- colorTo: green
6
- sdk: gradio
7
- sdk_version: 3.29.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <H1 align="center">
2
+ YOLOv8 Object Detection with DeepSORT Tracking(ID + Trails) </H1>
3
+
4
+ ## Google Colab File Link (A Single Click Solution)
5
+ The google colab file link for yolov8 object detection and tracking is provided below, you can check the implementation in Google Colab, and its a single click implementation, you just need to select the Run Time as GPU, and click on Run All.
6
+
7
+ [`Google Colab File`](https://colab.research.google.com/drive/1U6cnTQ0JwCg4kdHxYSl2NAhU4wK18oAu?usp=sharing)
8
+
9
+ ## Object Detection and Tracking (ID + Trails) using YOLOv8 on Custom Data
10
+ ## Google Colab File Link (A Single Click Solution)
11
+ [`Google Colab File`](https://colab.research.google.com/drive/1dEpI2k3m1i0vbvB4bNqPRQUO0gSBTz25?usp=sharing)
12
+
13
+ ## YOLOv8 Segmentation with DeepSORT Object Tracking
14
+
15
+ [`Github Repo Link`](https://github.com/MuhammadMoinFaisal/YOLOv8_Segmentation_DeepSORT_Object_Tracking.git)
16
+
17
+ ## Steps to run Code
18
+
19
+ - Clone the repository
20
+ ```
21
+ git clone https://github.com/MuhammadMoinFaisal/YOLOv8-DeepSORT-Object-Tracking.git
22
+ ```
23
+ - Goto the cloned folder.
24
+ ```
25
+ cd YOLOv8-DeepSORT-Object-Tracking
26
+ ```
27
+ - Install the dependecies
28
+ ```
29
+ pip install -e '.[dev]'
30
+
31
+ ```
32
+
33
+ - Setting the Directory.
34
+ ```
35
+ cd ultralytics/yolo/v8/detect
36
+
37
+ ```
38
+ - Downloading the DeepSORT Files From The Google Drive
39
+ ```
40
+
41
+ https://drive.google.com/drive/folders/1kna8eWGrSfzaR6DtNJ8_GchGgPMv3VC8?usp=sharing
42
+ ```
43
+ - After downloading the DeepSORT Zip file from the drive, unzip it go into the subfolders and place the deep_sort_pytorch folder into the yolo/v8/detect folder
44
+
45
+ - Downloading a Sample Video from the Google Drive
46
+ ```
47
+ gdown "https://drive.google.com/uc?id=1rjBn8Fl1E_9d0EMVtL24S9aNQOJAveR5&confirm=t"
48
+ ```
49
+
50
+ - Run the code with mentioned command below.
51
+
52
+ - For yolov8 object detection + Tracking
53
+ ```
54
+ python predict.py model=yolov8l.pt source="test3.mp4" show=True
55
+ ```
56
+ - For yolov8 object detection + Tracking + Vehicle Counting
57
+ - Download the updated predict.py file from the Google Drive and place it into ultralytics/yolo/v8/detect folder
58
+ - Google Drive Link
59
+ ```
60
+ https://drive.google.com/drive/folders/1awlzTGHBBAn_2pKCkLFADMd1EN_rJETW?usp=sharing
61
+ ```
62
+ - For yolov8 object detection + Tracking + Vehicle Counting
63
+ ```
64
+ python predict.py model=yolov8l.pt source="test3.mp4" show=True
65
+ ```
66
+
67
+ ### RESULTS
68
+
69
+ #### Vehicles Detection, Tracking and Counting
70
+ ![](./figure/figure1.png)
71
+
72
+ #### Vehicles Detection, Tracking and Counting
73
+
74
+ ![](./figure/figure3.png)
75
+
76
+ ### Watch the Complete Step by Step Explanation
77
+
78
+ - Video Tutorial Link [`YouTube Link`](https://www.youtube.com/watch?v=9jRRZ-WL698)
79
+
80
+
81
+ [![Watch the Complete Tutorial for the Step by Step Explanation](https://img.youtube.com/vi/9jRRZ-WL698/0.jpg)]([https://www.youtube.com/watch?v=StTqXEQ2l-Y](https://www.youtube.com/watch?v=9jRRZ-WL698))
82
+
YOLOv8_DeepSORT_TRACKING_SCRIPT.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c0918af0bfa0ef2e0e9d26d9a8b06e2d706f5a5685d4e19eb58877a8036092ac
3
+ size 16618677
YOLOv8_Detection_Tracking_CustomData_Complete.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3d514434f9b1d8f5f3a7fb72e782f82d3c136523a7fc7bb41c2a2a390f4aa783
3
+ size 22625415
figure/figure1.png ADDED

Git LFS Details

  • SHA256: 664385ae049b026377706815fe377fe731aef846900f0343d50a214a269b4707
  • Pointer size: 132 Bytes
  • Size of remote file: 2.81 MB
figure/figure2.png ADDED

Git LFS Details

  • SHA256: a2c383e5fcfc524b385e41d33b0bbf56320a3a81d3a96f9500f7f254009c8f03
  • Pointer size: 132 Bytes
  • Size of remote file: 2.63 MB
figure/figure3.png ADDED

Git LFS Details

  • SHA256: cb719fd4505ae476bebe57131165764d11e6193d165cdecf70a760100cf6551f
  • Pointer size: 132 Bytes
  • Size of remote file: 2.94 MB
mkdocs.yml ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ site_name: Ultralytics Docs
2
+ repo_url: https://github.com/ultralytics/ultralytics
3
+ repo_name: Ultralytics
4
+
5
+ theme:
6
+ name: "material"
7
+ logo: https://github.com/ultralytics/assets/raw/main/logo/Ultralytics-logomark-white.png
8
+ icon:
9
+ repo: fontawesome/brands/github
10
+ admonition:
11
+ note: octicons/tag-16
12
+ abstract: octicons/checklist-16
13
+ info: octicons/info-16
14
+ tip: octicons/squirrel-16
15
+ success: octicons/check-16
16
+ question: octicons/question-16
17
+ warning: octicons/alert-16
18
+ failure: octicons/x-circle-16
19
+ danger: octicons/zap-16
20
+ bug: octicons/bug-16
21
+ example: octicons/beaker-16
22
+ quote: octicons/quote-16
23
+
24
+ palette:
25
+ # Palette toggle for light mode
26
+ - scheme: default
27
+ toggle:
28
+ icon: material/brightness-7
29
+ name: Switch to dark mode
30
+
31
+ # Palette toggle for dark mode
32
+ - scheme: slate
33
+ toggle:
34
+ icon: material/brightness-4
35
+ name: Switch to light mode
36
+ features:
37
+ - content.code.annotate
38
+ - content.tooltips
39
+ - search.highlight
40
+ - search.share
41
+ - search.suggest
42
+ - toc.follow
43
+
44
+ extra_css:
45
+ - stylesheets/style.css
46
+
47
+ markdown_extensions:
48
+ # Div text decorators
49
+ - admonition
50
+ - pymdownx.details
51
+ - pymdownx.superfences
52
+ - tables
53
+ - attr_list
54
+ - def_list
55
+ # Syntax highlight
56
+ - pymdownx.highlight:
57
+ anchor_linenums: true
58
+ - pymdownx.inlinehilite
59
+ - pymdownx.snippets
60
+
61
+ # Button
62
+ - attr_list
63
+
64
+ # Content tabs
65
+ - pymdownx.superfences
66
+ - pymdownx.tabbed:
67
+ alternate_style: true
68
+
69
+ # Highlight
70
+ - pymdownx.critic
71
+ - pymdownx.caret
72
+ - pymdownx.keys
73
+ - pymdownx.mark
74
+ - pymdownx.tilde
75
+ plugins:
76
+ - mkdocstrings
77
+
78
+ # Primary navigation
79
+ nav:
80
+ - Quickstart: quickstart.md
81
+ - CLI: cli.md
82
+ - Python Interface: sdk.md
83
+ - Configuration: config.md
84
+ - Customization Guide: engine.md
85
+ - Ultralytics HUB: hub.md
86
+ - iOS and Android App: app.md
87
+ - Reference:
88
+ - Python Model interface: reference/model.md
89
+ - Engine:
90
+ - Trainer: reference/base_trainer.md
91
+ - Validator: reference/base_val.md
92
+ - Predictor: reference/base_pred.md
93
+ - Exporter: reference/exporter.md
94
+ - nn Module: reference/nn.md
95
+ - operations: reference/ops.md
requirements.txt ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics requirements
2
+ # Usage: pip install -r requirements.txt
3
+
4
+ # Base ----------------------------------------
5
+ hydra-core>=1.2.0
6
+ matplotlib>=3.2.2
7
+ numpy>=1.18.5
8
+ opencv-python>=4.1.1
9
+ Pillow>=7.1.2
10
+ PyYAML>=5.3.1
11
+ requests>=2.23.0
12
+ scipy>=1.4.1
13
+ torch>=1.7.0
14
+ torchvision>=0.8.1
15
+ tqdm>=4.64.0
16
+
17
+ # Logging -------------------------------------
18
+ tensorboard>=2.4.1
19
+ # clearml
20
+ # comet
21
+
22
+ # Plotting ------------------------------------
23
+ pandas>=1.1.4
24
+ seaborn>=0.11.0
25
+
26
+ # Export --------------------------------------
27
+ # coremltools>=6.0 # CoreML export
28
+ # onnx>=1.12.0 # ONNX export
29
+ # onnx-simplifier>=0.4.1 # ONNX simplifier
30
+ # nvidia-pyindex # TensorRT export
31
+ # nvidia-tensorrt # TensorRT export
32
+ # scikit-learn==0.19.2 # CoreML quantization
33
+ # tensorflow>=2.4.1 # TF exports (-cpu, -aarch64, -macos)
34
+ # tensorflowjs>=3.9.0 # TF.js export
35
+ # openvino-dev # OpenVINO export
36
+
37
+ # Extras --------------------------------------
38
+ ipython # interactive notebook
39
+ psutil # system utilization
40
+ thop>=0.1.1 # FLOPs computation
41
+ # albumentations>=1.0.3
42
+ # pycocotools>=2.0.6 # COCO mAP
43
+ # roboflow
44
+
45
+ # HUB -----------------------------------------
46
+ GitPython>=3.1.24
setup.cfg ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Project-wide configuration file, can be used for package metadata and other toll configurations
2
+ # Example usage: global configuration for PEP8 (via flake8) setting or default pytest arguments
3
+ # Local usage: pip install pre-commit, pre-commit run --all-files
4
+
5
+ [metadata]
6
+ license_file = LICENSE
7
+ description_file = README.md
8
+
9
+ [tool:pytest]
10
+ norecursedirs =
11
+ .git
12
+ dist
13
+ build
14
+ addopts =
15
+ --doctest-modules
16
+ --durations=25
17
+ --color=yes
18
+
19
+ [flake8]
20
+ max-line-length = 120
21
+ exclude = .tox,*.egg,build,temp
22
+ select = E,W,F
23
+ doctests = True
24
+ verbose = 2
25
+ # https://pep8.readthedocs.io/en/latest/intro.html#error-codes
26
+ format = pylint
27
+ # see: https://www.flake8rules.com/
28
+ ignore = E731,F405,E402,F401,W504,E127,E231,E501,F403
29
+ # E731: Do not assign a lambda expression, use a def
30
+ # F405: name may be undefined, or defined from star imports: module
31
+ # E402: module level import not at top of file
32
+ # F401: module imported but unused
33
+ # W504: line break after binary operator
34
+ # E127: continuation line over-indented for visual indent
35
+ # E231: missing whitespace after ‘,’, ‘;’, or ‘:’
36
+ # E501: line too long
37
+ # F403: ‘from module import *’ used; unable to detect undefined names
38
+
39
+ [isort]
40
+ # https://pycqa.github.io/isort/docs/configuration/options.html
41
+ line_length = 120
42
+ # see: https://pycqa.github.io/isort/docs/configuration/multi_line_output_modes.html
43
+ multi_line_output = 0
44
+
45
+ [yapf]
46
+ based_on_style = pep8
47
+ spaces_before_comment = 2
48
+ COLUMN_LIMIT = 120
49
+ COALESCE_BRACKETS = True
50
+ SPACES_AROUND_POWER_OPERATOR = True
51
+ SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET = False
52
+ SPLIT_BEFORE_CLOSING_BRACKET = False
53
+ SPLIT_BEFORE_FIRST_ARGUMENT = False
54
+ # EACH_DICT_ENTRY_ON_SEPARATE_LINE = False
setup.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import re
4
+ from pathlib import Path
5
+
6
+ import pkg_resources as pkg
7
+ from setuptools import find_packages, setup
8
+
9
+ # Settings
10
+ FILE = Path(__file__).resolve()
11
+ ROOT = FILE.parent # root directory
12
+ README = (ROOT / "README.md").read_text(encoding="utf-8")
13
+ REQUIREMENTS = [f'{x.name}{x.specifier}' for x in pkg.parse_requirements((ROOT / 'requirements.txt').read_text())]
14
+
15
+
16
+ def get_version():
17
+ file = ROOT / 'ultralytics/__init__.py'
18
+ return re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', file.read_text(), re.M)[1]
19
+
20
+
21
+ setup(
22
+ name="ultralytics", # name of pypi package
23
+ version=get_version(), # version of pypi package
24
+ python_requires=">=3.7.0",
25
+ license='GPL-3.0',
26
+ description='Ultralytics YOLOv8 and HUB',
27
+ long_description=README,
28
+ long_description_content_type="text/markdown",
29
+ url="https://github.com/ultralytics/ultralytics",
30
+ project_urls={
31
+ 'Bug Reports': 'https://github.com/ultralytics/ultralytics/issues',
32
+ 'Funding': 'https://ultralytics.com',
33
+ 'Source': 'https://github.com/ultralytics/ultralytics',},
34
+ author="Ultralytics",
35
+ author_email='hello@ultralytics.com',
36
+ packages=find_packages(), # required
37
+ include_package_data=True,
38
+ install_requires=REQUIREMENTS,
39
+ extras_require={
40
+ 'dev':
41
+ ['check-manifest', 'pytest', 'pytest-cov', 'coverage', 'mkdocs', 'mkdocstrings[python]', 'mkdocs-material'],},
42
+ classifiers=[
43
+ "Intended Audience :: Developers", "Intended Audience :: Science/Research",
44
+ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python :: 3",
45
+ "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8",
46
+ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10",
47
+ "Topic :: Software Development", "Topic :: Scientific/Engineering",
48
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
49
+ "Topic :: Scientific/Engineering :: Image Recognition", "Operating System :: POSIX :: Linux",
50
+ "Operating System :: MacOS", "Operating System :: Microsoft :: Windows"],
51
+ keywords="machine-learning, deep-learning, vision, ML, DL, AI, YOLO, YOLOv3, YOLOv5, YOLOv8, HUB, Ultralytics",
52
+ entry_points={
53
+ 'console_scripts': ['yolo = ultralytics.yolo.cli:cli', 'ultralytics = ultralytics.yolo.cli:cli'],})
ultralytics/__init__.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ __version__ = "8.0.3"
4
+
5
+ from ultralytics.hub import checks
6
+ from ultralytics.yolo.engine.model import YOLO
7
+ from ultralytics.yolo.utils import ops
8
+
9
+ __all__ = ["__version__", "YOLO", "hub", "checks"] # allow simpler import
ultralytics/hub/__init__.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import os
4
+ import shutil
5
+
6
+ import psutil
7
+ import requests
8
+ from IPython import display # to display images and clear console output
9
+
10
+ from ultralytics.hub.auth import Auth
11
+ from ultralytics.hub.session import HubTrainingSession
12
+ from ultralytics.hub.utils import PREFIX, split_key
13
+ from ultralytics.yolo.utils import LOGGER, emojis, is_colab
14
+ from ultralytics.yolo.utils.torch_utils import select_device
15
+ from ultralytics.yolo.v8.detect import DetectionTrainer
16
+
17
+
18
+ def checks(verbose=True):
19
+ if is_colab():
20
+ shutil.rmtree('sample_data', ignore_errors=True) # remove colab /sample_data directory
21
+
22
+ if verbose:
23
+ # System info
24
+ gib = 1 << 30 # bytes per GiB
25
+ ram = psutil.virtual_memory().total
26
+ total, used, free = shutil.disk_usage("/")
27
+ display.clear_output()
28
+ s = f'({os.cpu_count()} CPUs, {ram / gib:.1f} GB RAM, {(total - free) / gib:.1f}/{total / gib:.1f} GB disk)'
29
+ else:
30
+ s = ''
31
+
32
+ select_device(newline=False)
33
+ LOGGER.info(f'Setup complete ✅ {s}')
34
+
35
+
36
+ def start(key=''):
37
+ # Start training models with Ultralytics HUB. Usage: from src.ultralytics import start; start('API_KEY')
38
+ def request_api_key(attempts=0):
39
+ """Prompt the user to input their API key"""
40
+ import getpass
41
+
42
+ max_attempts = 3
43
+ tries = f"Attempt {str(attempts + 1)} of {max_attempts}" if attempts > 0 else ""
44
+ LOGGER.info(f"{PREFIX}Login. {tries}")
45
+ input_key = getpass.getpass("Enter your Ultralytics HUB API key:\n")
46
+ auth.api_key, model_id = split_key(input_key)
47
+ if not auth.authenticate():
48
+ attempts += 1
49
+ LOGGER.warning(f"{PREFIX}Invalid API key ⚠️\n")
50
+ if attempts < max_attempts:
51
+ return request_api_key(attempts)
52
+ raise ConnectionError(emojis(f"{PREFIX}Failed to authenticate ❌"))
53
+ else:
54
+ return model_id
55
+
56
+ try:
57
+ api_key, model_id = split_key(key)
58
+ auth = Auth(api_key) # attempts cookie login if no api key is present
59
+ attempts = 1 if len(key) else 0
60
+ if not auth.get_state():
61
+ if len(key):
62
+ LOGGER.warning(f"{PREFIX}Invalid API key ⚠️\n")
63
+ model_id = request_api_key(attempts)
64
+ LOGGER.info(f"{PREFIX}Authenticated ✅")
65
+ if not model_id:
66
+ raise ConnectionError(emojis('Connecting with global API key is not currently supported. ❌'))
67
+ session = HubTrainingSession(model_id=model_id, auth=auth)
68
+ session.check_disk_space()
69
+
70
+ # TODO: refactor, hardcoded for v8
71
+ args = session.model.copy()
72
+ args.pop("id")
73
+ args.pop("status")
74
+ args.pop("weights")
75
+ args["data"] = "coco128.yaml"
76
+ args["model"] = "yolov8n.yaml"
77
+ args["batch_size"] = 16
78
+ args["imgsz"] = 64
79
+
80
+ trainer = DetectionTrainer(overrides=args)
81
+ session.register_callbacks(trainer)
82
+ setattr(trainer, 'hub_session', session)
83
+ trainer.train()
84
+ except Exception as e:
85
+ LOGGER.warning(f"{PREFIX}{e}")
86
+
87
+
88
+ def reset_model(key=''):
89
+ # Reset a trained model to an untrained state
90
+ api_key, model_id = split_key(key)
91
+ r = requests.post('https://api.ultralytics.com/model-reset', json={"apiKey": api_key, "modelId": model_id})
92
+
93
+ if r.status_code == 200:
94
+ LOGGER.info(f"{PREFIX}model reset successfully")
95
+ return
96
+ LOGGER.warning(f"{PREFIX}model reset failure {r.status_code} {r.reason}")
97
+
98
+
99
+ def export_model(key='', format='torchscript'):
100
+ # Export a model to all formats
101
+ api_key, model_id = split_key(key)
102
+ formats = ('torchscript', 'onnx', 'openvino', 'engine', 'coreml', 'saved_model', 'pb', 'tflite', 'edgetpu', 'tfjs',
103
+ 'ultralytics_tflite', 'ultralytics_coreml')
104
+ assert format in formats, f"ERROR: Unsupported export format '{format}' passed, valid formats are {formats}"
105
+
106
+ r = requests.post('https://api.ultralytics.com/export',
107
+ json={
108
+ "apiKey": api_key,
109
+ "modelId": model_id,
110
+ "format": format})
111
+ assert r.status_code == 200, f"{PREFIX}{format} export failure {r.status_code} {r.reason}"
112
+ LOGGER.info(f"{PREFIX}{format} export started ✅")
113
+
114
+
115
+ def get_export(key='', format='torchscript'):
116
+ # Get an exported model dictionary with download URL
117
+ api_key, model_id = split_key(key)
118
+ formats = ('torchscript', 'onnx', 'openvino', 'engine', 'coreml', 'saved_model', 'pb', 'tflite', 'edgetpu', 'tfjs',
119
+ 'ultralytics_tflite', 'ultralytics_coreml')
120
+ assert format in formats, f"ERROR: Unsupported export format '{format}' passed, valid formats are {formats}"
121
+
122
+ r = requests.post('https://api.ultralytics.com/get-export',
123
+ json={
124
+ "apiKey": api_key,
125
+ "modelId": model_id,
126
+ "format": format})
127
+ assert r.status_code == 200, f"{PREFIX}{format} get_export failure {r.status_code} {r.reason}"
128
+ return r.json()
129
+
130
+
131
+ # temp. For checking
132
+ if __name__ == "__main__":
133
+ start(key="b3fba421be84a20dbe68644e14436d1cce1b0a0aaa_HeMfHgvHsseMPhdq7Ylz")
ultralytics/hub/auth.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import requests
4
+
5
+ from ultralytics.hub.utils import HUB_API_ROOT, request_with_credentials
6
+ from ultralytics.yolo.utils import is_colab
7
+
8
+ API_KEY_PATH = "https://hub.ultralytics.com/settings?tab=api+keys"
9
+
10
+
11
+ class Auth:
12
+ id_token = api_key = model_key = False
13
+
14
+ def __init__(self, api_key=None):
15
+ self.api_key = self._clean_api_key(api_key)
16
+ self.authenticate() if self.api_key else self.auth_with_cookies()
17
+
18
+ @staticmethod
19
+ def _clean_api_key(key: str) -> str:
20
+ """Strip model from key if present"""
21
+ separator = "_"
22
+ return key.split(separator)[0] if separator in key else key
23
+
24
+ def authenticate(self) -> bool:
25
+ """Attempt to authenticate with server"""
26
+ try:
27
+ header = self.get_auth_header()
28
+ if header:
29
+ r = requests.post(f"{HUB_API_ROOT}/v1/auth", headers=header)
30
+ if not r.json().get('success', False):
31
+ raise ConnectionError("Unable to authenticate.")
32
+ return True
33
+ raise ConnectionError("User has not authenticated locally.")
34
+ except ConnectionError:
35
+ self.id_token = self.api_key = False # reset invalid
36
+ return False
37
+
38
+ def auth_with_cookies(self) -> bool:
39
+ """
40
+ Attempt to fetch authentication via cookies and set id_token.
41
+ User must be logged in to HUB and running in a supported browser.
42
+ """
43
+ if not is_colab():
44
+ return False # Currently only works with Colab
45
+ try:
46
+ authn = request_with_credentials(f"{HUB_API_ROOT}/v1/auth/auto")
47
+ if authn.get("success", False):
48
+ self.id_token = authn.get("data", {}).get("idToken", None)
49
+ self.authenticate()
50
+ return True
51
+ raise ConnectionError("Unable to fetch browser authentication details.")
52
+ except ConnectionError:
53
+ self.id_token = False # reset invalid
54
+ return False
55
+
56
+ def get_auth_header(self):
57
+ if self.id_token:
58
+ return {"authorization": f"Bearer {self.id_token}"}
59
+ elif self.api_key:
60
+ return {"x-api-key": self.api_key}
61
+ else:
62
+ return None
63
+
64
+ def get_state(self) -> bool:
65
+ """Get the authentication state"""
66
+ return self.id_token or self.api_key
67
+
68
+ def set_api_key(self, key: str):
69
+ """Get the authentication state"""
70
+ self.api_key = key
ultralytics/hub/session.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import signal
4
+ import sys
5
+ from pathlib import Path
6
+ from time import sleep
7
+
8
+ import requests
9
+
10
+ from ultralytics import __version__
11
+ from ultralytics.hub.utils import HUB_API_ROOT, check_dataset_disk_space, smart_request
12
+ from ultralytics.yolo.utils import LOGGER, is_colab, threaded
13
+
14
+ AGENT_NAME = f'python-{__version__}-colab' if is_colab() else f'python-{__version__}-local'
15
+
16
+ session = None
17
+
18
+
19
+ def signal_handler(signum, frame):
20
+ """ Confirm exit """
21
+ global hub_logger
22
+ LOGGER.info(f'Signal received. {signum} {frame}')
23
+ if isinstance(session, HubTrainingSession):
24
+ hub_logger.alive = False
25
+ del hub_logger
26
+ sys.exit(signum)
27
+
28
+
29
+ signal.signal(signal.SIGTERM, signal_handler)
30
+ signal.signal(signal.SIGINT, signal_handler)
31
+
32
+
33
+ class HubTrainingSession:
34
+
35
+ def __init__(self, model_id, auth):
36
+ self.agent_id = None # identifies which instance is communicating with server
37
+ self.model_id = model_id
38
+ self.api_url = f'{HUB_API_ROOT}/v1/models/{model_id}'
39
+ self.auth_header = auth.get_auth_header()
40
+ self.rate_limits = {'metrics': 3.0, 'ckpt': 900.0, 'heartbeat': 300.0} # rate limits (seconds)
41
+ self.t = {} # rate limit timers (seconds)
42
+ self.metrics_queue = {} # metrics queue
43
+ self.alive = True # for heartbeats
44
+ self.model = self._get_model()
45
+ self._heartbeats() # start heartbeats
46
+
47
+ def __del__(self):
48
+ # Class destructor
49
+ self.alive = False
50
+
51
+ def upload_metrics(self):
52
+ payload = {"metrics": self.metrics_queue.copy(), "type": "metrics"}
53
+ smart_request(f'{self.api_url}', json=payload, headers=self.auth_header, code=2)
54
+
55
+ def upload_model(self, epoch, weights, is_best=False, map=0.0, final=False):
56
+ # Upload a model to HUB
57
+ file = None
58
+ if Path(weights).is_file():
59
+ with open(weights, "rb") as f:
60
+ file = f.read()
61
+ if final:
62
+ smart_request(f'{self.api_url}/upload',
63
+ data={
64
+ "epoch": epoch,
65
+ "type": "final",
66
+ "map": map},
67
+ files={"best.pt": file},
68
+ headers=self.auth_header,
69
+ retry=10,
70
+ timeout=3600,
71
+ code=4)
72
+ else:
73
+ smart_request(f'{self.api_url}/upload',
74
+ data={
75
+ "epoch": epoch,
76
+ "type": "epoch",
77
+ "isBest": bool(is_best)},
78
+ headers=self.auth_header,
79
+ files={"last.pt": file},
80
+ code=3)
81
+
82
+ def _get_model(self):
83
+ # Returns model from database by id
84
+ api_url = f"{HUB_API_ROOT}/v1/models/{self.model_id}"
85
+ headers = self.auth_header
86
+
87
+ try:
88
+ r = smart_request(api_url, method="get", headers=headers, thread=False, code=0)
89
+ data = r.json().get("data", None)
90
+ if not data:
91
+ return
92
+ assert data['data'], 'ERROR: Dataset may still be processing. Please wait a minute and try again.' # RF fix
93
+ self.model_id = data["id"]
94
+
95
+ return data
96
+ except requests.exceptions.ConnectionError as e:
97
+ raise ConnectionRefusedError('ERROR: The HUB server is not online. Please try again later.') from e
98
+
99
+ def check_disk_space(self):
100
+ if not check_dataset_disk_space(self.model['data']):
101
+ raise MemoryError("Not enough disk space")
102
+
103
+ # COMMENT: Should not be needed as HUB is now considered an integration and is in integrations_callbacks
104
+ # import ultralytics.yolo.utils.callbacks.hub as hub_callbacks
105
+ # @staticmethod
106
+ # def register_callbacks(trainer):
107
+ # for k, v in hub_callbacks.callbacks.items():
108
+ # trainer.add_callback(k, v)
109
+
110
+ @threaded
111
+ def _heartbeats(self):
112
+ while self.alive:
113
+ r = smart_request(f'{HUB_API_ROOT}/v1/agent/heartbeat/models/{self.model_id}',
114
+ json={
115
+ "agent": AGENT_NAME,
116
+ "agentId": self.agent_id},
117
+ headers=self.auth_header,
118
+ retry=0,
119
+ code=5,
120
+ thread=False)
121
+ self.agent_id = r.json().get('data', {}).get('agentId', None)
122
+ sleep(self.rate_limits['heartbeat'])
ultralytics/hub/utils.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import os
4
+ import shutil
5
+ import threading
6
+ import time
7
+
8
+ import requests
9
+
10
+ from ultralytics.yolo.utils import DEFAULT_CONFIG_DICT, LOGGER, RANK, SETTINGS, TryExcept, colorstr, emojis
11
+
12
+ PREFIX = colorstr('Ultralytics: ')
13
+ HELP_MSG = 'If this issue persists please visit https://github.com/ultralytics/hub/issues for assistance.'
14
+ HUB_API_ROOT = os.environ.get("ULTRALYTICS_HUB_API", "https://api.ultralytics.com")
15
+
16
+
17
+ def check_dataset_disk_space(url='https://github.com/ultralytics/yolov5/releases/download/v1.0/coco128.zip', sf=2.0):
18
+ # Check that url fits on disk with safety factor sf, i.e. require 2GB free if url size is 1GB with sf=2.0
19
+ gib = 1 << 30 # bytes per GiB
20
+ data = int(requests.head(url).headers['Content-Length']) / gib # dataset size (GB)
21
+ total, used, free = (x / gib for x in shutil.disk_usage("/")) # bytes
22
+ LOGGER.info(f'{PREFIX}{data:.3f} GB dataset, {free:.1f}/{total:.1f} GB free disk space')
23
+ if data * sf < free:
24
+ return True # sufficient space
25
+ LOGGER.warning(f'{PREFIX}WARNING: Insufficient free disk space {free:.1f} GB < {data * sf:.3f} GB required, '
26
+ f'training cancelled ❌. Please free {data * sf - free:.1f} GB additional disk space and try again.')
27
+ return False # insufficient space
28
+
29
+
30
+ def request_with_credentials(url: str) -> any:
31
+ """ Make an ajax request with cookies attached """
32
+ from google.colab import output # noqa
33
+ from IPython import display # noqa
34
+ display.display(
35
+ display.Javascript("""
36
+ window._hub_tmp = new Promise((resolve, reject) => {
37
+ const timeout = setTimeout(() => reject("Failed authenticating existing browser session"), 5000)
38
+ fetch("%s", {
39
+ method: 'POST',
40
+ credentials: 'include'
41
+ })
42
+ .then((response) => resolve(response.json()))
43
+ .then((json) => {
44
+ clearTimeout(timeout);
45
+ }).catch((err) => {
46
+ clearTimeout(timeout);
47
+ reject(err);
48
+ });
49
+ });
50
+ """ % url))
51
+ return output.eval_js("_hub_tmp")
52
+
53
+
54
+ # Deprecated TODO: eliminate this function?
55
+ def split_key(key=''):
56
+ """
57
+ Verify and split a 'api_key[sep]model_id' string, sep is one of '.' or '_'
58
+
59
+ Args:
60
+ key (str): The model key to split. If not provided, the user will be prompted to enter it.
61
+
62
+ Returns:
63
+ Tuple[str, str]: A tuple containing the API key and model ID.
64
+ """
65
+
66
+ import getpass
67
+
68
+ error_string = emojis(f'{PREFIX}Invalid API key ⚠️\n') # error string
69
+ if not key:
70
+ key = getpass.getpass('Enter model key: ')
71
+ sep = '_' if '_' in key else '.' if '.' in key else None # separator
72
+ assert sep, error_string
73
+ api_key, model_id = key.split(sep)
74
+ assert len(api_key) and len(model_id), error_string
75
+ return api_key, model_id
76
+
77
+
78
+ def smart_request(*args, retry=3, timeout=30, thread=True, code=-1, method="post", verbose=True, **kwargs):
79
+ """
80
+ Makes an HTTP request using the 'requests' library, with exponential backoff retries up to a specified timeout.
81
+
82
+ Args:
83
+ *args: Positional arguments to be passed to the requests function specified in method.
84
+ retry (int, optional): Number of retries to attempt before giving up. Default is 3.
85
+ timeout (int, optional): Timeout in seconds after which the function will give up retrying. Default is 30.
86
+ thread (bool, optional): Whether to execute the request in a separate daemon thread. Default is True.
87
+ code (int, optional): An identifier for the request, used for logging purposes. Default is -1.
88
+ method (str, optional): The HTTP method to use for the request. Choices are 'post' and 'get'. Default is 'post'.
89
+ verbose (bool, optional): A flag to determine whether to print out to console or not. Default is True.
90
+ **kwargs: Keyword arguments to be passed to the requests function specified in method.
91
+
92
+ Returns:
93
+ requests.Response: The HTTP response object. If the request is executed in a separate thread, returns None.
94
+ """
95
+ retry_codes = (408, 500) # retry only these codes
96
+
97
+ def func(*func_args, **func_kwargs):
98
+ r = None # response
99
+ t0 = time.time() # initial time for timer
100
+ for i in range(retry + 1):
101
+ if (time.time() - t0) > timeout:
102
+ break
103
+ if method == 'post':
104
+ r = requests.post(*func_args, **func_kwargs) # i.e. post(url, data, json, files)
105
+ elif method == 'get':
106
+ r = requests.get(*func_args, **func_kwargs) # i.e. get(url, data, json, files)
107
+ if r.status_code == 200:
108
+ break
109
+ try:
110
+ m = r.json().get('message', 'No JSON message.')
111
+ except AttributeError:
112
+ m = 'Unable to read JSON.'
113
+ if i == 0:
114
+ if r.status_code in retry_codes:
115
+ m += f' Retrying {retry}x for {timeout}s.' if retry else ''
116
+ elif r.status_code == 429: # rate limit
117
+ h = r.headers # response headers
118
+ m = f"Rate limit reached ({h['X-RateLimit-Remaining']}/{h['X-RateLimit-Limit']}). " \
119
+ f"Please retry after {h['Retry-After']}s."
120
+ if verbose:
121
+ LOGGER.warning(f"{PREFIX}{m} {HELP_MSG} ({r.status_code} #{code})")
122
+ if r.status_code not in retry_codes:
123
+ return r
124
+ time.sleep(2 ** i) # exponential standoff
125
+ return r
126
+
127
+ if thread:
128
+ threading.Thread(target=func, args=args, kwargs=kwargs, daemon=True).start()
129
+ else:
130
+ return func(*args, **kwargs)
131
+
132
+
133
+ @TryExcept()
134
+ def sync_analytics(cfg, all_keys=False, enabled=False):
135
+ """
136
+ Sync analytics data if enabled in the global settings
137
+
138
+ Args:
139
+ cfg (DictConfig): Configuration for the task and mode.
140
+ all_keys (bool): Sync all items, not just non-default values.
141
+ enabled (bool): For debugging.
142
+ """
143
+ if SETTINGS['sync'] and RANK in {-1, 0} and enabled:
144
+ cfg = dict(cfg) # convert type from DictConfig to dict
145
+ if not all_keys:
146
+ cfg = {k: v for k, v in cfg.items() if v != DEFAULT_CONFIG_DICT.get(k, None)} # retain non-default values
147
+ cfg['uuid'] = SETTINGS['uuid'] # add the device UUID to the configuration data
148
+
149
+ # Send a request to the HUB API to sync analytics
150
+ smart_request(f'{HUB_API_ROOT}/v1/usage/anonymous', json=cfg, headers=None, code=3, retry=0, verbose=False)
ultralytics/models/README.md ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Models
2
+
3
+ Welcome to the Ultralytics Models directory! Here you will find a wide variety of pre-configured model configuration
4
+ files (`*.yaml`s) that can be used to create custom YOLO models. The models in this directory have been expertly crafted
5
+ and fine-tuned by the Ultralytics team to provide the best performance for a wide range of object detection and image
6
+ segmentation tasks.
7
+
8
+ These model configurations cover a wide range of scenarios, from simple object detection to more complex tasks like
9
+ instance segmentation and object tracking. They are also designed to run efficiently on a variety of hardware platforms,
10
+ from CPUs to GPUs. Whether you are a seasoned machine learning practitioner or just getting started with YOLO, this
11
+ directory provides a great starting point for your custom model development needs.
12
+
13
+ To get started, simply browse through the models in this directory and find one that best suits your needs. Once you've
14
+ selected a model, you can use the provided `*.yaml` file to train and deploy your custom YOLO model with ease. See full
15
+ details at the Ultralytics [Docs](https://docs.ultralytics.com), and if you need help or have any questions, feel free
16
+ to reach out to the Ultralytics team for support. So, don't wait, start creating your custom YOLO model now!
17
+
18
+ ### Usage
19
+
20
+ Model `*.yaml` files may be used directly in the Command Line Interface (CLI) with a `yolo` command:
21
+
22
+ ```bash
23
+ yolo task=detect mode=train model=yolov8n.yaml data=coco128.yaml epochs=100
24
+ ```
25
+
26
+ They may also be used directly in a Python environment, and accepts the same
27
+ [arguments](https://docs.ultralytics.com/config/) as in the CLI example above:
28
+
29
+ ```python
30
+ from ultralytics import YOLO
31
+
32
+ model = YOLO("yolov8n.yaml") # build a YOLOv8n model from scratch
33
+
34
+ model.info() # display model information
35
+ model.train(data="coco128.yaml", epochs=100) # train the model
36
+ ```
ultralytics/models/v3/yolov3-spp.yaml ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.0 # model depth multiple
6
+ width_multiple: 1.0 # layer channel multiple
7
+
8
+ # darknet53 backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [32, 3, 1]], # 0
12
+ [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
13
+ [-1, 1, Bottleneck, [64]],
14
+ [-1, 1, Conv, [128, 3, 2]], # 3-P2/4
15
+ [-1, 2, Bottleneck, [128]],
16
+ [-1, 1, Conv, [256, 3, 2]], # 5-P3/8
17
+ [-1, 8, Bottleneck, [256]],
18
+ [-1, 1, Conv, [512, 3, 2]], # 7-P4/16
19
+ [-1, 8, Bottleneck, [512]],
20
+ [-1, 1, Conv, [1024, 3, 2]], # 9-P5/32
21
+ [-1, 4, Bottleneck, [1024]], # 10
22
+ ]
23
+
24
+ # YOLOv3-SPP head
25
+ head:
26
+ [[-1, 1, Bottleneck, [1024, False]],
27
+ [-1, 1, SPP, [512, [5, 9, 13]]],
28
+ [-1, 1, Conv, [1024, 3, 1]],
29
+ [-1, 1, Conv, [512, 1, 1]],
30
+ [-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large)
31
+
32
+ [-2, 1, Conv, [256, 1, 1]],
33
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
34
+ [[-1, 8], 1, Concat, [1]], # cat backbone P4
35
+ [-1, 1, Bottleneck, [512, False]],
36
+ [-1, 1, Bottleneck, [512, False]],
37
+ [-1, 1, Conv, [256, 1, 1]],
38
+ [-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium)
39
+
40
+ [-2, 1, Conv, [128, 1, 1]],
41
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
42
+ [[-1, 6], 1, Concat, [1]], # cat backbone P3
43
+ [-1, 1, Bottleneck, [256, False]],
44
+ [-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small)
45
+
46
+ [[27, 22, 15], 1, Detect, [nc]], # Detect(P3, P4, P5)
47
+ ]
ultralytics/models/v3/yolov3-tiny.yaml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.0 # model depth multiple
6
+ width_multiple: 1.0 # layer channel multiple
7
+
8
+ # YOLOv3-tiny backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [16, 3, 1]], # 0
12
+ [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 1-P1/2
13
+ [-1, 1, Conv, [32, 3, 1]],
14
+ [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 3-P2/4
15
+ [-1, 1, Conv, [64, 3, 1]],
16
+ [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 5-P3/8
17
+ [-1, 1, Conv, [128, 3, 1]],
18
+ [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 7-P4/16
19
+ [-1, 1, Conv, [256, 3, 1]],
20
+ [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 9-P5/32
21
+ [-1, 1, Conv, [512, 3, 1]],
22
+ [-1, 1, nn.ZeroPad2d, [[0, 1, 0, 1]]], # 11
23
+ [-1, 1, nn.MaxPool2d, [2, 1, 0]], # 12
24
+ ]
25
+
26
+ # YOLOv3-tiny head
27
+ head:
28
+ [[-1, 1, Conv, [1024, 3, 1]],
29
+ [-1, 1, Conv, [256, 1, 1]],
30
+ [-1, 1, Conv, [512, 3, 1]], # 15 (P5/32-large)
31
+
32
+ [-2, 1, Conv, [128, 1, 1]],
33
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
34
+ [[-1, 8], 1, Concat, [1]], # cat backbone P4
35
+ [-1, 1, Conv, [256, 3, 1]], # 19 (P4/16-medium)
36
+
37
+ [[19, 15], 1, Detect, [nc]], # Detect(P4, P5)
38
+ ]
ultralytics/models/v3/yolov3.yaml ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.0 # model depth multiple
6
+ width_multiple: 1.0 # layer channel multiple
7
+
8
+ # darknet53 backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [32, 3, 1]], # 0
12
+ [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
13
+ [-1, 1, Bottleneck, [64]],
14
+ [-1, 1, Conv, [128, 3, 2]], # 3-P2/4
15
+ [-1, 2, Bottleneck, [128]],
16
+ [-1, 1, Conv, [256, 3, 2]], # 5-P3/8
17
+ [-1, 8, Bottleneck, [256]],
18
+ [-1, 1, Conv, [512, 3, 2]], # 7-P4/16
19
+ [-1, 8, Bottleneck, [512]],
20
+ [-1, 1, Conv, [1024, 3, 2]], # 9-P5/32
21
+ [-1, 4, Bottleneck, [1024]], # 10
22
+ ]
23
+
24
+ # YOLOv3 head
25
+ head:
26
+ [[-1, 1, Bottleneck, [1024, False]],
27
+ [-1, 1, Conv, [512, 1, 1]],
28
+ [-1, 1, Conv, [1024, 3, 1]],
29
+ [-1, 1, Conv, [512, 1, 1]],
30
+ [-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large)
31
+
32
+ [-2, 1, Conv, [256, 1, 1]],
33
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
34
+ [[-1, 8], 1, Concat, [1]], # cat backbone P4
35
+ [-1, 1, Bottleneck, [512, False]],
36
+ [-1, 1, Bottleneck, [512, False]],
37
+ [-1, 1, Conv, [256, 1, 1]],
38
+ [-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium)
39
+
40
+ [-2, 1, Conv, [128, 1, 1]],
41
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
42
+ [[-1, 6], 1, Concat, [1]], # cat backbone P3
43
+ [-1, 1, Bottleneck, [256, False]],
44
+ [-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small)
45
+
46
+ [[27, 22, 15], 1, Detect, [nc]], # Detect(P3, P4, P5)
47
+ ]
ultralytics/models/v5/yolov5l.yaml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.0 # model depth multiple
6
+ width_multiple: 1.0 # layer channel multiple
7
+
8
+ # YOLOv5 v6.0 backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
12
+ [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
13
+ [-1, 3, C3, [128]],
14
+ [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
15
+ [-1, 6, C3, [256]],
16
+ [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
17
+ [-1, 9, C3, [512]],
18
+ [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
19
+ [-1, 3, C3, [1024]],
20
+ [-1, 1, SPPF, [1024, 5]], # 9
21
+ ]
22
+
23
+ # YOLOv5 v6.0 head
24
+ head:
25
+ [[-1, 1, Conv, [512, 1, 1]],
26
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
27
+ [[-1, 6], 1, Concat, [1]], # cat backbone P4
28
+ [-1, 3, C3, [512, False]], # 13
29
+
30
+ [-1, 1, Conv, [256, 1, 1]],
31
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
32
+ [[-1, 4], 1, Concat, [1]], # cat backbone P3
33
+ [-1, 3, C3, [256, False]], # 17 (P3/8-small)
34
+
35
+ [-1, 1, Conv, [256, 3, 2]],
36
+ [[-1, 14], 1, Concat, [1]], # cat head P4
37
+ [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
38
+
39
+ [-1, 1, Conv, [512, 3, 2]],
40
+ [[-1, 10], 1, Concat, [1]], # cat head P5
41
+ [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
42
+
43
+ [[17, 20, 23], 1, Detect, [nc]], # Detect(P3, P4, P5)
44
+ ]
ultralytics/models/v5/yolov5m.yaml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.67 # model depth multiple
6
+ width_multiple: 0.75 # layer channel multiple
7
+
8
+ # YOLOv5 v6.0 backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
12
+ [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
13
+ [-1, 3, C3, [128]],
14
+ [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
15
+ [-1, 6, C3, [256]],
16
+ [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
17
+ [-1, 9, C3, [512]],
18
+ [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
19
+ [-1, 3, C3, [1024]],
20
+ [-1, 1, SPPF, [1024, 5]], # 9
21
+ ]
22
+
23
+ # YOLOv5 v6.0 head
24
+ head:
25
+ [[-1, 1, Conv, [512, 1, 1]],
26
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
27
+ [[-1, 6], 1, Concat, [1]], # cat backbone P4
28
+ [-1, 3, C3, [512, False]], # 13
29
+
30
+ [-1, 1, Conv, [256, 1, 1]],
31
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
32
+ [[-1, 4], 1, Concat, [1]], # cat backbone P3
33
+ [-1, 3, C3, [256, False]], # 17 (P3/8-small)
34
+
35
+ [-1, 1, Conv, [256, 3, 2]],
36
+ [[-1, 14], 1, Concat, [1]], # cat head P4
37
+ [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
38
+
39
+ [-1, 1, Conv, [512, 3, 2]],
40
+ [[-1, 10], 1, Concat, [1]], # cat head P5
41
+ [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
42
+
43
+ [[17, 20, 23], 1, Detect, [nc]], # Detect(P3, P4, P5)
44
+ ]
ultralytics/models/v5/yolov5n.yaml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.33 # model depth multiple
6
+ width_multiple: 0.25 # layer channel multiple
7
+
8
+ # YOLOv5 v6.0 backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
12
+ [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
13
+ [-1, 3, C3, [128]],
14
+ [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
15
+ [-1, 6, C3, [256]],
16
+ [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
17
+ [-1, 9, C3, [512]],
18
+ [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
19
+ [-1, 3, C3, [1024]],
20
+ [-1, 1, SPPF, [1024, 5]], # 9
21
+ ]
22
+
23
+ # YOLOv5 v6.0 head
24
+ head:
25
+ [[-1, 1, Conv, [512, 1, 1]],
26
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
27
+ [[-1, 6], 1, Concat, [1]], # cat backbone P4
28
+ [-1, 3, C3, [512, False]], # 13
29
+
30
+ [-1, 1, Conv, [256, 1, 1]],
31
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
32
+ [[-1, 4], 1, Concat, [1]], # cat backbone P3
33
+ [-1, 3, C3, [256, False]], # 17 (P3/8-small)
34
+
35
+ [-1, 1, Conv, [256, 3, 2]],
36
+ [[-1, 14], 1, Concat, [1]], # cat head P4
37
+ [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
38
+
39
+ [-1, 1, Conv, [512, 3, 2]],
40
+ [[-1, 10], 1, Concat, [1]], # cat head P5
41
+ [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
42
+
43
+ [[17, 20, 23], 1, Detect, [nc]], # Detect(P3, P4, P5)
44
+ ]
ultralytics/models/v5/yolov5s.yaml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.33 # model depth multiple
6
+ width_multiple: 0.50 # layer channel multiple
7
+
8
+
9
+ # YOLOv5 v6.0 backbone
10
+ backbone:
11
+ # [from, number, module, args]
12
+ [[-1, 1, Conv, [64, 6, 2, 2]], # 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, 6, 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, 3, C3, [1024]],
21
+ [-1, 1, SPPF, [1024, 5]], # 9
22
+ ]
23
+
24
+ # YOLOv5 v6.0 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, [256, 3, 2]],
37
+ [[-1, 14], 1, Concat, [1]], # cat head P4
38
+ [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
39
+
40
+ [-1, 1, Conv, [512, 3, 2]],
41
+ [[-1, 10], 1, Concat, [1]], # cat head P5
42
+ [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
43
+
44
+ [[17, 20, 23], 1, Detect, [nc]], # Detect(P3, P4, P5)
45
+ ]
ultralytics/models/v5/yolov5x.yaml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.33 # model depth multiple
6
+ width_multiple: 1.25 # layer channel multiple
7
+
8
+ # YOLOv5 v6.0 backbone
9
+ backbone:
10
+ # [from, number, module, args]
11
+ [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
12
+ [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
13
+ [-1, 3, C3, [128]],
14
+ [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
15
+ [-1, 6, C3, [256]],
16
+ [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
17
+ [-1, 9, C3, [512]],
18
+ [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
19
+ [-1, 3, C3, [1024]],
20
+ [-1, 1, SPPF, [1024, 5]], # 9
21
+ ]
22
+
23
+ # YOLOv5 v6.0 head
24
+ head:
25
+ [[-1, 1, Conv, [512, 1, 1]],
26
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
27
+ [[-1, 6], 1, Concat, [1]], # cat backbone P4
28
+ [-1, 3, C3, [512, False]], # 13
29
+
30
+ [-1, 1, Conv, [256, 1, 1]],
31
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
32
+ [[-1, 4], 1, Concat, [1]], # cat backbone P3
33
+ [-1, 3, C3, [256, False]], # 17 (P3/8-small)
34
+
35
+ [-1, 1, Conv, [256, 3, 2]],
36
+ [[-1, 14], 1, Concat, [1]], # cat head P4
37
+ [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
38
+
39
+ [-1, 1, Conv, [512, 3, 2]],
40
+ [[-1, 10], 1, Concat, [1]], # cat head P5
41
+ [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
42
+
43
+ [[17, 20, 23], 1, Detect, [nc]], # Detect(P3, P4, P5)
44
+ ]
ultralytics/models/v8/cls/yolov8l-cls.yaml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 1000 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.00 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+
21
+ # YOLOv8.0n head
22
+ head:
23
+ - [-1, 1, Classify, [nc]]
ultralytics/models/v8/cls/yolov8m-cls.yaml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 1000 # number of classes
5
+ depth_multiple: 0.67 # scales module repeats
6
+ width_multiple: 0.75 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+
21
+ # YOLOv8.0n head
22
+ head:
23
+ - [-1, 1, Classify, [nc]]
ultralytics/models/v8/cls/yolov8n-cls.yaml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 1000 # number of classes
5
+ depth_multiple: 0.33 # scales module repeats
6
+ width_multiple: 0.25 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+
21
+ # YOLOv8.0n head
22
+ head:
23
+ - [-1, 1, Classify, [nc]]
ultralytics/models/v8/cls/yolov8s-cls.yaml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 1000 # number of classes
5
+ depth_multiple: 0.33 # scales module repeats
6
+ width_multiple: 0.50 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+
21
+ # YOLOv8.0n head
22
+ head:
23
+ - [-1, 1, Classify, [nc]]
ultralytics/models/v8/cls/yolov8x-cls.yaml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 1000 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.25 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+
21
+ # YOLOv8.0n head
22
+ head:
23
+ - [-1, 1, Classify, [nc]]
ultralytics/models/v8/seg/yolov8l-seg.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.00 # scales convolution channels
7
+
8
+ # YOLOv8.0l backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [512, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [512, True]]
20
+ - [-1, 1, SPPF, [512, 5]] # 9
21
+
22
+ # YOLOv8.0l head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [512]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Detect(P3, P4, P5)
ultralytics/models/v8/seg/yolov8m-seg.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.67 # scales module repeats
6
+ width_multiple: 0.75 # scales convolution channels
7
+
8
+ # YOLOv8.0m backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [768, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [768, True]]
20
+ - [-1, 1, SPPF, [768, 5]] # 9
21
+
22
+ # YOLOv8.0m head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [768]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Detect(P3, P4, P5)
ultralytics/models/v8/seg/yolov8n-seg.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.33 # scales module repeats
6
+ width_multiple: 0.25 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+ - [-1, 1, SPPF, [1024, 5]] # 9
21
+
22
+ # YOLOv8.0n head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [1024]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Detect(P3, P4, P5)
ultralytics/models/v8/seg/yolov8s-seg.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.33 # scales module repeats
6
+ width_multiple: 0.50 # scales convolution channels
7
+
8
+ # YOLOv8.0s backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+ - [-1, 1, SPPF, [1024, 5]] # 9
21
+
22
+ # YOLOv8.0s head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [1024]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Detect(P3, P4, P5)
ultralytics/models/v8/seg/yolov8x-seg.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.25 # scales convolution channels
7
+
8
+ # YOLOv8.0x backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [512, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [512, True]]
20
+ - [-1, 1, SPPF, [512, 5]] # 9
21
+
22
+ # YOLOv8.0x head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [512]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Detect(P3, P4, P5)
ultralytics/models/v8/yolov8l.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.00 # scales convolution channels
7
+
8
+ # YOLOv8.0l backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [512, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [512, True]]
20
+ - [-1, 1, SPPF, [512, 5]] # 9
21
+
22
+ # YOLOv8.0l head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [512]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
ultralytics/models/v8/yolov8m.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.67 # scales module repeats
6
+ width_multiple: 0.75 # scales convolution channels
7
+
8
+ # YOLOv8.0m backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [768, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [768, True]]
20
+ - [-1, 1, SPPF, [768, 5]] # 9
21
+
22
+ # YOLOv8.0m head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [768]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
ultralytics/models/v8/yolov8n.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.33 # scales module repeats
6
+ width_multiple: 0.25 # scales convolution channels
7
+
8
+ # YOLOv8.0n backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+ - [-1, 1, SPPF, [1024, 5]] # 9
21
+
22
+ # YOLOv8.0n head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [1024]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
ultralytics/models/v8/yolov8s.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 0.33 # scales module repeats
6
+ width_multiple: 0.50 # scales convolution channels
7
+
8
+ # YOLOv8.0s backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [1024, True]]
20
+ - [-1, 1, SPPF, [1024, 5]] # 9
21
+
22
+ # YOLOv8.0s head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [1024]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
ultralytics/models/v8/yolov8x.yaml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.25 # scales convolution channels
7
+
8
+ # YOLOv8.0x backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [512, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [512, True]]
20
+ - [-1, 1, SPPF, [512, 5]] # 9
21
+
22
+ # YOLOv8.0x head
23
+ head:
24
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
25
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
26
+ - [-1, 3, C2f, [512]] # 13
27
+
28
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
29
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
30
+ - [-1, 3, C2f, [256]] # 17 (P3/8-small)
31
+
32
+ - [-1, 1, Conv, [256, 3, 2]]
33
+ - [[-1, 12], 1, Concat, [1]] # cat head P4
34
+ - [-1, 3, C2f, [512]] # 20 (P4/16-medium)
35
+
36
+ - [-1, 1, Conv, [512, 3, 2]]
37
+ - [[-1, 9], 1, Concat, [1]] # cat head P5
38
+ - [-1, 3, C2f, [512]] # 23 (P5/32-large)
39
+
40
+ - [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
ultralytics/models/v8/yolov8x6.yaml ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ # Parameters
4
+ nc: 80 # number of classes
5
+ depth_multiple: 1.00 # scales module repeats
6
+ width_multiple: 1.25 # scales convolution channels
7
+
8
+ # YOLOv8.0x6 backbone
9
+ backbone:
10
+ # [from, repeats, module, args]
11
+ - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
12
+ - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
13
+ - [-1, 3, C2f, [128, True]]
14
+ - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
15
+ - [-1, 6, C2f, [256, True]]
16
+ - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
17
+ - [-1, 6, C2f, [512, True]]
18
+ - [-1, 1, Conv, [512, 3, 2]] # 7-P5/32
19
+ - [-1, 3, C2f, [512, True]]
20
+ - [-1, 1, Conv, [512, 3, 2]] # 9-P6/64
21
+ - [-1, 3, C2f, [512, True]]
22
+ - [-1, 1, SPPF, [512, 5]] # 11
23
+
24
+ # YOLOv8.0x6 head
25
+ head:
26
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
27
+ - [[-1, 8], 1, Concat, [1]] # cat backbone P5
28
+ - [-1, 3, C2, [512, False]] # 14
29
+
30
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
31
+ - [[-1, 6], 1, Concat, [1]] # cat backbone P4
32
+ - [-1, 3, C2, [512, False]] # 17
33
+
34
+ - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
35
+ - [[-1, 4], 1, Concat, [1]] # cat backbone P3
36
+ - [-1, 3, C2, [256, False]] # 20 (P3/8-small)
37
+
38
+ - [-1, 1, Conv, [256, 3, 2]]
39
+ - [[-1, 17], 1, Concat, [1]] # cat head P4
40
+ - [-1, 3, C2, [512, False]] # 23 (P4/16-medium)
41
+
42
+ - [-1, 1, Conv, [512, 3, 2]]
43
+ - [[-1, 14], 1, Concat, [1]] # cat head P5
44
+ - [-1, 3, C2, [512, False]] # 26 (P5/32-large)
45
+
46
+ - [-1, 1, Conv, [512, 3, 2]]
47
+ - [[-1, 11], 1, Concat, [1]] # cat head P6
48
+ - [-1, 3, C2, [512, False]] # 29 (P6/64-xlarge)
49
+
50
+ - [[20, 23, 26, 29], 1, Detect, [nc]] # Detect(P3, P4, P5, P6)
ultralytics/nn/__init__.py ADDED
File without changes
ultralytics/nn/autobackend.py ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import json
4
+ import platform
5
+ from collections import OrderedDict, namedtuple
6
+ from pathlib import Path
7
+ from urllib.parse import urlparse
8
+
9
+ import cv2
10
+ import numpy as np
11
+ import torch
12
+ import torch.nn as nn
13
+ from PIL import Image
14
+
15
+ from ultralytics.yolo.utils import LOGGER, ROOT, yaml_load
16
+ from ultralytics.yolo.utils.checks import check_requirements, check_suffix, check_version
17
+ from ultralytics.yolo.utils.downloads import attempt_download, is_url
18
+ from ultralytics.yolo.utils.ops import xywh2xyxy
19
+
20
+
21
+ class AutoBackend(nn.Module):
22
+
23
+ def __init__(self, weights='yolov8n.pt', device=torch.device('cpu'), dnn=False, data=None, fp16=False, fuse=True):
24
+ """
25
+ Ultralytics YOLO MultiBackend class for python inference on various backends
26
+
27
+ Args:
28
+ weights: the path to the weights file. Defaults to yolov8n.pt
29
+ device: The device to run the model on.
30
+ dnn: If you want to use OpenCV's DNN module to run the inference, set this to True. Defaults to
31
+ False
32
+ data: a dictionary containing the following keys:
33
+ fp16: If true, will use half precision. Defaults to False
34
+ fuse: whether to fuse the model or not. Defaults to True
35
+
36
+ Supported format and their usage:
37
+ | Platform | weights |
38
+ |-----------------------|------------------|
39
+ | PyTorch | *.pt |
40
+ | TorchScript | *.torchscript |
41
+ | ONNX Runtime | *.onnx |
42
+ | ONNX OpenCV DNN | *.onnx --dnn |
43
+ | OpenVINO | *.xml |
44
+ | CoreML | *.mlmodel |
45
+ | TensorRT | *.engine |
46
+ | TensorFlow SavedModel | *_saved_model |
47
+ | TensorFlow GraphDef | *.pb |
48
+ | TensorFlow Lite | *.tflite |
49
+ | TensorFlow Edge TPU | *_edgetpu.tflite |
50
+ | PaddlePaddle | *_paddle_model |
51
+ """
52
+ super().__init__()
53
+ w = str(weights[0] if isinstance(weights, list) else weights)
54
+ nn_module = isinstance(weights, torch.nn.Module)
55
+ pt, jit, onnx, xml, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs, paddle, triton = self._model_type(w)
56
+ fp16 &= pt or jit or onnx or engine or nn_module # FP16
57
+ nhwc = coreml or saved_model or pb or tflite or edgetpu # BHWC formats (vs torch BCWH)
58
+ stride = 32 # default stride
59
+ cuda = torch.cuda.is_available() and device.type != 'cpu' # use CUDA
60
+ if not (pt or triton or nn_module):
61
+ w = attempt_download(w) # download if not local
62
+
63
+ # NOTE: special case: in-memory pytorch model
64
+ if nn_module:
65
+ model = weights.to(device)
66
+ model = model.fuse() if fuse else model
67
+ names = model.module.names if hasattr(model, 'module') else model.names # get class names
68
+ model.half() if fp16 else model.float()
69
+ self.model = model # explicitly assign for to(), cpu(), cuda(), half()
70
+ pt = True
71
+ elif pt: # PyTorch
72
+ from ultralytics.nn.tasks import attempt_load_weights
73
+ model = attempt_load_weights(weights if isinstance(weights, list) else w,
74
+ device=device,
75
+ inplace=True,
76
+ fuse=fuse)
77
+ stride = max(int(model.stride.max()), 32) # model stride
78
+ names = model.module.names if hasattr(model, 'module') else model.names # get class names
79
+ model.half() if fp16 else model.float()
80
+ self.model = model # explicitly assign for to(), cpu(), cuda(), half()
81
+ elif jit: # TorchScript
82
+ LOGGER.info(f'Loading {w} for TorchScript inference...')
83
+ extra_files = {'config.txt': ''} # model metadata
84
+ model = torch.jit.load(w, _extra_files=extra_files, map_location=device)
85
+ model.half() if fp16 else model.float()
86
+ if extra_files['config.txt']: # load metadata dict
87
+ d = json.loads(extra_files['config.txt'],
88
+ object_hook=lambda d: {int(k) if k.isdigit() else k: v
89
+ for k, v in d.items()})
90
+ stride, names = int(d['stride']), d['names']
91
+ elif dnn: # ONNX OpenCV DNN
92
+ LOGGER.info(f'Loading {w} for ONNX OpenCV DNN inference...')
93
+ check_requirements('opencv-python>=4.5.4')
94
+ net = cv2.dnn.readNetFromONNX(w)
95
+ elif onnx: # ONNX Runtime
96
+ LOGGER.info(f'Loading {w} for ONNX Runtime inference...')
97
+ check_requirements(('onnx', 'onnxruntime-gpu' if cuda else 'onnxruntime'))
98
+ import onnxruntime
99
+ providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if cuda else ['CPUExecutionProvider']
100
+ session = onnxruntime.InferenceSession(w, providers=providers)
101
+ output_names = [x.name for x in session.get_outputs()]
102
+ meta = session.get_modelmeta().custom_metadata_map # metadata
103
+ if 'stride' in meta:
104
+ stride, names = int(meta['stride']), eval(meta['names'])
105
+ elif xml: # OpenVINO
106
+ LOGGER.info(f'Loading {w} for OpenVINO inference...')
107
+ check_requirements('openvino') # requires openvino-dev: https://pypi.org/project/openvino-dev/
108
+ from openvino.runtime import Core, Layout, get_batch # noqa
109
+ ie = Core()
110
+ if not Path(w).is_file(): # if not *.xml
111
+ w = next(Path(w).glob('*.xml')) # get *.xml file from *_openvino_model dir
112
+ network = ie.read_model(model=w, weights=Path(w).with_suffix('.bin'))
113
+ if network.get_parameters()[0].get_layout().empty:
114
+ network.get_parameters()[0].set_layout(Layout("NCHW"))
115
+ batch_dim = get_batch(network)
116
+ if batch_dim.is_static:
117
+ batch_size = batch_dim.get_length()
118
+ executable_network = ie.compile_model(network, device_name="CPU") # device_name="MYRIAD" for Intel NCS2
119
+ stride, names = self._load_metadata(Path(w).with_suffix('.yaml')) # load metadata
120
+ elif engine: # TensorRT
121
+ LOGGER.info(f'Loading {w} for TensorRT inference...')
122
+ import tensorrt as trt # https://developer.nvidia.com/nvidia-tensorrt-download
123
+ check_version(trt.__version__, '7.0.0', hard=True) # require tensorrt>=7.0.0
124
+ if device.type == 'cpu':
125
+ device = torch.device('cuda:0')
126
+ Binding = namedtuple('Binding', ('name', 'dtype', 'shape', 'data', 'ptr'))
127
+ logger = trt.Logger(trt.Logger.INFO)
128
+ with open(w, 'rb') as f, trt.Runtime(logger) as runtime:
129
+ model = runtime.deserialize_cuda_engine(f.read())
130
+ context = model.create_execution_context()
131
+ bindings = OrderedDict()
132
+ output_names = []
133
+ fp16 = False # default updated below
134
+ dynamic = False
135
+ for i in range(model.num_bindings):
136
+ name = model.get_binding_name(i)
137
+ dtype = trt.nptype(model.get_binding_dtype(i))
138
+ if model.binding_is_input(i):
139
+ if -1 in tuple(model.get_binding_shape(i)): # dynamic
140
+ dynamic = True
141
+ context.set_binding_shape(i, tuple(model.get_profile_shape(0, i)[2]))
142
+ if dtype == np.float16:
143
+ fp16 = True
144
+ else: # output
145
+ output_names.append(name)
146
+ shape = tuple(context.get_binding_shape(i))
147
+ im = torch.from_numpy(np.empty(shape, dtype=dtype)).to(device)
148
+ bindings[name] = Binding(name, dtype, shape, im, int(im.data_ptr()))
149
+ binding_addrs = OrderedDict((n, d.ptr) for n, d in bindings.items())
150
+ batch_size = bindings['images'].shape[0] # if dynamic, this is instead max batch size
151
+ elif coreml: # CoreML
152
+ LOGGER.info(f'Loading {w} for CoreML inference...')
153
+ import coremltools as ct
154
+ model = ct.models.MLModel(w)
155
+ elif saved_model: # TF SavedModel
156
+ LOGGER.info(f'Loading {w} for TensorFlow SavedModel inference...')
157
+ import tensorflow as tf
158
+ keras = False # assume TF1 saved_model
159
+ model = tf.keras.models.load_model(w) if keras else tf.saved_model.load(w)
160
+ elif pb: # GraphDef https://www.tensorflow.org/guide/migrate#a_graphpb_or_graphpbtxt
161
+ LOGGER.info(f'Loading {w} for TensorFlow GraphDef inference...')
162
+ import tensorflow as tf
163
+
164
+ def wrap_frozen_graph(gd, inputs, outputs):
165
+ x = tf.compat.v1.wrap_function(lambda: tf.compat.v1.import_graph_def(gd, name=""), []) # wrapped
166
+ ge = x.graph.as_graph_element
167
+ return x.prune(tf.nest.map_structure(ge, inputs), tf.nest.map_structure(ge, outputs))
168
+
169
+ def gd_outputs(gd):
170
+ name_list, input_list = [], []
171
+ for node in gd.node: # tensorflow.core.framework.node_def_pb2.NodeDef
172
+ name_list.append(node.name)
173
+ input_list.extend(node.input)
174
+ return sorted(f'{x}:0' for x in list(set(name_list) - set(input_list)) if not x.startswith('NoOp'))
175
+
176
+ gd = tf.Graph().as_graph_def() # TF GraphDef
177
+ with open(w, 'rb') as f:
178
+ gd.ParseFromString(f.read())
179
+ frozen_func = wrap_frozen_graph(gd, inputs="x:0", outputs=gd_outputs(gd))
180
+ elif tflite or edgetpu: # https://www.tensorflow.org/lite/guide/python#install_tensorflow_lite_for_python
181
+ try: # https://coral.ai/docs/edgetpu/tflite-python/#update-existing-tf-lite-code-for-the-edge-tpu
182
+ from tflite_runtime.interpreter import Interpreter, load_delegate
183
+ except ImportError:
184
+ import tensorflow as tf
185
+ Interpreter, load_delegate = tf.lite.Interpreter, tf.lite.experimental.load_delegate,
186
+ if edgetpu: # TF Edge TPU https://coral.ai/software/#edgetpu-runtime
187
+ LOGGER.info(f'Loading {w} for TensorFlow Lite Edge TPU inference...')
188
+ delegate = {
189
+ 'Linux': 'libedgetpu.so.1',
190
+ 'Darwin': 'libedgetpu.1.dylib',
191
+ 'Windows': 'edgetpu.dll'}[platform.system()]
192
+ interpreter = Interpreter(model_path=w, experimental_delegates=[load_delegate(delegate)])
193
+ else: # TFLite
194
+ LOGGER.info(f'Loading {w} for TensorFlow Lite inference...')
195
+ interpreter = Interpreter(model_path=w) # load TFLite model
196
+ interpreter.allocate_tensors() # allocate
197
+ input_details = interpreter.get_input_details() # inputs
198
+ output_details = interpreter.get_output_details() # outputs
199
+ elif tfjs: # TF.js
200
+ raise NotImplementedError('ERROR: YOLOv5 TF.js inference is not supported')
201
+ elif paddle: # PaddlePaddle
202
+ LOGGER.info(f'Loading {w} for PaddlePaddle inference...')
203
+ check_requirements('paddlepaddle-gpu' if cuda else 'paddlepaddle')
204
+ import paddle.inference as pdi
205
+ if not Path(w).is_file(): # if not *.pdmodel
206
+ w = next(Path(w).rglob('*.pdmodel')) # get *.xml file from *_openvino_model dir
207
+ weights = Path(w).with_suffix('.pdiparams')
208
+ config = pdi.Config(str(w), str(weights))
209
+ if cuda:
210
+ config.enable_use_gpu(memory_pool_init_size_mb=2048, device_id=0)
211
+ predictor = pdi.create_predictor(config)
212
+ input_handle = predictor.get_input_handle(predictor.get_input_names()[0])
213
+ output_names = predictor.get_output_names()
214
+ elif triton: # NVIDIA Triton Inference Server
215
+ LOGGER.info('Triton Inference Server not supported...')
216
+ '''
217
+ TODO:
218
+ check_requirements('tritonclient[all]')
219
+ from utils.triton import TritonRemoteModel
220
+ model = TritonRemoteModel(url=w)
221
+ nhwc = model.runtime.startswith("tensorflow")
222
+ '''
223
+ else:
224
+ raise NotImplementedError(f'ERROR: {w} is not a supported format')
225
+
226
+ # class names
227
+ if 'names' not in locals():
228
+ names = yaml_load(data)['names'] if data else {i: f'class{i}' for i in range(999)}
229
+ if names[0] == 'n01440764' and len(names) == 1000: # ImageNet
230
+ names = yaml_load(ROOT / 'yolo/data/datasets/ImageNet.yaml')['names'] # human-readable names
231
+
232
+ self.__dict__.update(locals()) # assign all variables to self
233
+
234
+ def forward(self, im, augment=False, visualize=False):
235
+ """
236
+ Runs inference on the given model
237
+
238
+ Args:
239
+ im: the image tensor
240
+ augment: whether to augment the image. Defaults to False
241
+ visualize: if True, then the network will output the feature maps of the last convolutional layer.
242
+ Defaults to False
243
+ """
244
+ # YOLOv5 MultiBackend inference
245
+ b, ch, h, w = im.shape # batch, channel, height, width
246
+ if self.fp16 and im.dtype != torch.float16:
247
+ im = im.half() # to FP16
248
+ if self.nhwc:
249
+ im = im.permute(0, 2, 3, 1) # torch BCHW to numpy BHWC shape(1,320,192,3)
250
+
251
+ if self.pt or self.nn_module: # PyTorch
252
+ y = self.model(im, augment=augment, visualize=visualize) if augment or visualize else self.model(im)
253
+ elif self.jit: # TorchScript
254
+ y = self.model(im)
255
+ elif self.dnn: # ONNX OpenCV DNN
256
+ im = im.cpu().numpy() # torch to numpy
257
+ self.net.setInput(im)
258
+ y = self.net.forward()
259
+ elif self.onnx: # ONNX Runtime
260
+ im = im.cpu().numpy() # torch to numpy
261
+ y = self.session.run(self.output_names, {self.session.get_inputs()[0].name: im})
262
+ elif self.xml: # OpenVINO
263
+ im = im.cpu().numpy() # FP32
264
+ y = list(self.executable_network([im]).values())
265
+ elif self.engine: # TensorRT
266
+ if self.dynamic and im.shape != self.bindings['images'].shape:
267
+ i = self.model.get_binding_index('images')
268
+ self.context.set_binding_shape(i, im.shape) # reshape if dynamic
269
+ self.bindings['images'] = self.bindings['images']._replace(shape=im.shape)
270
+ for name in self.output_names:
271
+ i = self.model.get_binding_index(name)
272
+ self.bindings[name].data.resize_(tuple(self.context.get_binding_shape(i)))
273
+ s = self.bindings['images'].shape
274
+ assert im.shape == s, f"input size {im.shape} {'>' if self.dynamic else 'not equal to'} max model size {s}"
275
+ self.binding_addrs['images'] = int(im.data_ptr())
276
+ self.context.execute_v2(list(self.binding_addrs.values()))
277
+ y = [self.bindings[x].data for x in sorted(self.output_names)]
278
+ elif self.coreml: # CoreML
279
+ im = im.cpu().numpy()
280
+ im = Image.fromarray((im[0] * 255).astype('uint8'))
281
+ # im = im.resize((192, 320), Image.ANTIALIAS)
282
+ y = self.model.predict({'image': im}) # coordinates are xywh normalized
283
+ if 'confidence' in y:
284
+ box = xywh2xyxy(y['coordinates'] * [[w, h, w, h]]) # xyxy pixels
285
+ conf, cls = y['confidence'].max(1), y['confidence'].argmax(1).astype(np.float)
286
+ y = np.concatenate((box, conf.reshape(-1, 1), cls.reshape(-1, 1)), 1)
287
+ else:
288
+ y = list(reversed(y.values())) # reversed for segmentation models (pred, proto)
289
+ elif self.paddle: # PaddlePaddle
290
+ im = im.cpu().numpy().astype(np.float32)
291
+ self.input_handle.copy_from_cpu(im)
292
+ self.predictor.run()
293
+ y = [self.predictor.get_output_handle(x).copy_to_cpu() for x in self.output_names]
294
+ elif self.triton: # NVIDIA Triton Inference Server
295
+ y = self.model(im)
296
+ else: # TensorFlow (SavedModel, GraphDef, Lite, Edge TPU)
297
+ im = im.cpu().numpy()
298
+ if self.saved_model: # SavedModel
299
+ y = self.model(im, training=False) if self.keras else self.model(im)
300
+ elif self.pb: # GraphDef
301
+ y = self.frozen_func(x=self.tf.constant(im))
302
+ else: # Lite or Edge TPU
303
+ input = self.input_details[0]
304
+ int8 = input['dtype'] == np.uint8 # is TFLite quantized uint8 model
305
+ if int8:
306
+ scale, zero_point = input['quantization']
307
+ im = (im / scale + zero_point).astype(np.uint8) # de-scale
308
+ self.interpreter.set_tensor(input['index'], im)
309
+ self.interpreter.invoke()
310
+ y = []
311
+ for output in self.output_details:
312
+ x = self.interpreter.get_tensor(output['index'])
313
+ if int8:
314
+ scale, zero_point = output['quantization']
315
+ x = (x.astype(np.float32) - zero_point) * scale # re-scale
316
+ y.append(x)
317
+ y = [x if isinstance(x, np.ndarray) else x.numpy() for x in y]
318
+ y[0][..., :4] *= [w, h, w, h] # xywh normalized to pixels
319
+
320
+ if isinstance(y, (list, tuple)):
321
+ return self.from_numpy(y[0]) if len(y) == 1 else [self.from_numpy(x) for x in y]
322
+ else:
323
+ return self.from_numpy(y)
324
+
325
+ def from_numpy(self, x):
326
+ """
327
+ `from_numpy` converts a numpy array to a tensor
328
+
329
+ Args:
330
+ x: the numpy array to convert
331
+ """
332
+ return torch.from_numpy(x).to(self.device) if isinstance(x, np.ndarray) else x
333
+
334
+ def warmup(self, imgsz=(1, 3, 640, 640)):
335
+ """
336
+ Warmup model by running inference once
337
+
338
+ Args:
339
+ imgsz: the size of the image you want to run inference on.
340
+ """
341
+ warmup_types = self.pt, self.jit, self.onnx, self.engine, self.saved_model, self.pb, self.triton, self.nn_module
342
+ if any(warmup_types) and (self.device.type != 'cpu' or self.triton):
343
+ im = torch.empty(*imgsz, dtype=torch.half if self.fp16 else torch.float, device=self.device) # input
344
+ for _ in range(2 if self.jit else 1): #
345
+ self.forward(im) # warmup
346
+
347
+ @staticmethod
348
+ def _model_type(p='path/to/model.pt'):
349
+ """
350
+ This function takes a path to a model file and returns the model type
351
+
352
+ Args:
353
+ p: path to the model file. Defaults to path/to/model.pt
354
+ """
355
+ # Return model type from model path, i.e. path='path/to/model.onnx' -> type=onnx
356
+ # types = [pt, jit, onnx, xml, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs, paddle]
357
+ from ultralytics.yolo.engine.exporter import export_formats
358
+ sf = list(export_formats().Suffix) # export suffixes
359
+ if not is_url(p, check=False) and not isinstance(p, str):
360
+ check_suffix(p, sf) # checks
361
+ url = urlparse(p) # if url may be Triton inference server
362
+ types = [s in Path(p).name for s in sf]
363
+ types[8] &= not types[9] # tflite &= not edgetpu
364
+ triton = not any(types) and all([any(s in url.scheme for s in ["http", "grpc"]), url.netloc])
365
+ return types + [triton]
366
+
367
+ @staticmethod
368
+ def _load_metadata(f=Path('path/to/meta.yaml')):
369
+ """
370
+ > Loads the metadata from a yaml file
371
+
372
+ Args:
373
+ f: The path to the metadata file.
374
+ """
375
+ from ultralytics.yolo.utils.files import yaml_load
376
+
377
+ # Load metadata from meta.yaml if it exists
378
+ if f.exists():
379
+ d = yaml_load(f)
380
+ return d['stride'], d['names'] # assign stride, names
381
+ return None, None
ultralytics/nn/modules.py ADDED
@@ -0,0 +1,688 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+ """
3
+ Common modules
4
+ """
5
+
6
+ import math
7
+ import warnings
8
+ from copy import copy
9
+ from pathlib import Path
10
+
11
+ import cv2
12
+ import numpy as np
13
+ import pandas as pd
14
+ import requests
15
+ import torch
16
+ import torch.nn as nn
17
+ from PIL import Image, ImageOps
18
+ from torch.cuda import amp
19
+
20
+ from ultralytics.nn.autobackend import AutoBackend
21
+ from ultralytics.yolo.data.augment import LetterBox
22
+ from ultralytics.yolo.utils import LOGGER, colorstr
23
+ from ultralytics.yolo.utils.files import increment_path
24
+ from ultralytics.yolo.utils.ops import Profile, make_divisible, non_max_suppression, scale_boxes, xyxy2xywh
25
+ from ultralytics.yolo.utils.plotting import Annotator, colors, save_one_box
26
+ from ultralytics.yolo.utils.tal import dist2bbox, make_anchors
27
+ from ultralytics.yolo.utils.torch_utils import copy_attr, smart_inference_mode
28
+
29
+ # from utils.plots import feature_visualization TODO
30
+
31
+
32
+ def autopad(k, p=None, d=1): # kernel, padding, dilation
33
+ # Pad to 'same' shape outputs
34
+ if d > 1:
35
+ k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k] # actual kernel-size
36
+ if p is None:
37
+ p = k // 2 if isinstance(k, int) else [x // 2 for x in k] # auto-pad
38
+ return p
39
+
40
+
41
+ class Conv(nn.Module):
42
+ # Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)
43
+ default_act = nn.SiLU() # default activation
44
+
45
+ def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
46
+ super().__init__()
47
+ self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
48
+ self.bn = nn.BatchNorm2d(c2)
49
+ self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
50
+
51
+ def forward(self, x):
52
+ return self.act(self.bn(self.conv(x)))
53
+
54
+ def forward_fuse(self, x):
55
+ return self.act(self.conv(x))
56
+
57
+
58
+ class DWConv(Conv):
59
+ # Depth-wise convolution
60
+ def __init__(self, c1, c2, k=1, s=1, d=1, act=True): # ch_in, ch_out, kernel, stride, dilation, activation
61
+ super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), d=d, act=act)
62
+
63
+
64
+ class DWConvTranspose2d(nn.ConvTranspose2d):
65
+ # Depth-wise transpose convolution
66
+ def __init__(self, c1, c2, k=1, s=1, p1=0, p2=0): # ch_in, ch_out, kernel, stride, padding, padding_out
67
+ super().__init__(c1, c2, k, s, p1, p2, groups=math.gcd(c1, c2))
68
+
69
+
70
+ class ConvTranspose(nn.Module):
71
+ # Convolution transpose 2d layer
72
+ default_act = nn.SiLU() # default activation
73
+
74
+ def __init__(self, c1, c2, k=2, s=2, p=0, bn=True, act=True):
75
+ super().__init__()
76
+ self.conv_transpose = nn.ConvTranspose2d(c1, c2, k, s, p, bias=not bn)
77
+ self.bn = nn.BatchNorm2d(c2) if bn else nn.Identity()
78
+ self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
79
+
80
+ def forward(self, x):
81
+ return self.act(self.bn(self.conv_transpose(x)))
82
+
83
+
84
+ class DFL(nn.Module):
85
+ # DFL module
86
+ def __init__(self, c1=16):
87
+ super().__init__()
88
+ self.conv = nn.Conv2d(c1, 1, 1, bias=False).requires_grad_(False)
89
+ x = torch.arange(c1, dtype=torch.float)
90
+ self.conv.weight.data[:] = nn.Parameter(x.view(1, c1, 1, 1))
91
+ self.c1 = c1
92
+
93
+ def forward(self, x):
94
+ b, c, a = x.shape # batch, channels, anchors
95
+ return self.conv(x.view(b, 4, self.c1, a).transpose(2, 1).softmax(1)).view(b, 4, a)
96
+ # return self.conv(x.view(b, self.c1, 4, a).softmax(1)).view(b, 4, a)
97
+
98
+
99
+ class TransformerLayer(nn.Module):
100
+ # Transformer layer https://arxiv.org/abs/2010.11929 (LayerNorm layers removed for better performance)
101
+ def __init__(self, c, num_heads):
102
+ super().__init__()
103
+ self.q = nn.Linear(c, c, bias=False)
104
+ self.k = nn.Linear(c, c, bias=False)
105
+ self.v = nn.Linear(c, c, bias=False)
106
+ self.ma = nn.MultiheadAttention(embed_dim=c, num_heads=num_heads)
107
+ self.fc1 = nn.Linear(c, c, bias=False)
108
+ self.fc2 = nn.Linear(c, c, bias=False)
109
+
110
+ def forward(self, x):
111
+ x = self.ma(self.q(x), self.k(x), self.v(x))[0] + x
112
+ x = self.fc2(self.fc1(x)) + x
113
+ return x
114
+
115
+
116
+ class TransformerBlock(nn.Module):
117
+ # Vision Transformer https://arxiv.org/abs/2010.11929
118
+ def __init__(self, c1, c2, num_heads, num_layers):
119
+ super().__init__()
120
+ self.conv = None
121
+ if c1 != c2:
122
+ self.conv = Conv(c1, c2)
123
+ self.linear = nn.Linear(c2, c2) # learnable position embedding
124
+ self.tr = nn.Sequential(*(TransformerLayer(c2, num_heads) for _ in range(num_layers)))
125
+ self.c2 = c2
126
+
127
+ def forward(self, x):
128
+ if self.conv is not None:
129
+ x = self.conv(x)
130
+ b, _, w, h = x.shape
131
+ p = x.flatten(2).permute(2, 0, 1)
132
+ return self.tr(p + self.linear(p)).permute(1, 2, 0).reshape(b, self.c2, w, h)
133
+
134
+
135
+ class Bottleneck(nn.Module):
136
+ # Standard bottleneck
137
+ def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5): # ch_in, ch_out, shortcut, kernels, groups, expand
138
+ super().__init__()
139
+ c_ = int(c2 * e) # hidden channels
140
+ self.cv1 = Conv(c1, c_, k[0], 1)
141
+ self.cv2 = Conv(c_, c2, k[1], 1, g=g)
142
+ self.add = shortcut and c1 == c2
143
+
144
+ def forward(self, x):
145
+ return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
146
+
147
+
148
+ class BottleneckCSP(nn.Module):
149
+ # CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
150
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
151
+ super().__init__()
152
+ c_ = int(c2 * e) # hidden channels
153
+ self.cv1 = Conv(c1, c_, 1, 1)
154
+ self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)
155
+ self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False)
156
+ self.cv4 = Conv(2 * c_, c2, 1, 1)
157
+ self.bn = nn.BatchNorm2d(2 * c_) # applied to cat(cv2, cv3)
158
+ self.act = nn.SiLU()
159
+ self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
160
+
161
+ def forward(self, x):
162
+ y1 = self.cv3(self.m(self.cv1(x)))
163
+ y2 = self.cv2(x)
164
+ return self.cv4(self.act(self.bn(torch.cat((y1, y2), 1))))
165
+
166
+
167
+ class C3(nn.Module):
168
+ # CSP Bottleneck with 3 convolutions
169
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
170
+ super().__init__()
171
+ c_ = int(c2 * e) # hidden channels
172
+ self.cv1 = Conv(c1, c_, 1, 1)
173
+ self.cv2 = Conv(c1, c_, 1, 1)
174
+ self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2)
175
+ self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
176
+
177
+ def forward(self, x):
178
+ return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
179
+
180
+
181
+ class C2(nn.Module):
182
+ # CSP Bottleneck with 2 convolutions
183
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
184
+ super().__init__()
185
+ self.c = int(c2 * e) # hidden channels
186
+ self.cv1 = Conv(c1, 2 * self.c, 1, 1)
187
+ self.cv2 = Conv(2 * self.c, c2, 1) # optional act=FReLU(c2)
188
+ # self.attention = ChannelAttention(2 * self.c) # or SpatialAttention()
189
+ self.m = nn.Sequential(*(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n)))
190
+
191
+ def forward(self, x):
192
+ a, b = self.cv1(x).split((self.c, self.c), 1)
193
+ return self.cv2(torch.cat((self.m(a), b), 1))
194
+
195
+
196
+ class C2f(nn.Module):
197
+ # CSP Bottleneck with 2 convolutions
198
+ def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
199
+ super().__init__()
200
+ self.c = int(c2 * e) # hidden channels
201
+ self.cv1 = Conv(c1, 2 * self.c, 1, 1)
202
+ self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
203
+ self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
204
+
205
+ def forward(self, x):
206
+ y = list(self.cv1(x).split((self.c, self.c), 1))
207
+ y.extend(m(y[-1]) for m in self.m)
208
+ return self.cv2(torch.cat(y, 1))
209
+
210
+
211
+ class ChannelAttention(nn.Module):
212
+ # Channel-attention module https://github.com/open-mmlab/mmdetection/tree/v3.0.0rc1/configs/rtmdet
213
+ def __init__(self, channels: int) -> None:
214
+ super().__init__()
215
+ self.pool = nn.AdaptiveAvgPool2d(1)
216
+ self.fc = nn.Conv2d(channels, channels, 1, 1, 0, bias=True)
217
+ self.act = nn.Sigmoid()
218
+
219
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
220
+ return x * self.act(self.fc(self.pool(x)))
221
+
222
+
223
+ class SpatialAttention(nn.Module):
224
+ # Spatial-attention module
225
+ def __init__(self, kernel_size=7):
226
+ super().__init__()
227
+ assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
228
+ padding = 3 if kernel_size == 7 else 1
229
+ self.cv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
230
+ self.act = nn.Sigmoid()
231
+
232
+ def forward(self, x):
233
+ return x * self.act(self.cv1(torch.cat([torch.mean(x, 1, keepdim=True), torch.max(x, 1, keepdim=True)[0]], 1)))
234
+
235
+
236
+ class CBAM(nn.Module):
237
+ # CSP Bottleneck with 3 convolutions
238
+ def __init__(self, c1, ratio=16, kernel_size=7): # ch_in, ch_out, number, shortcut, groups, expansion
239
+ super().__init__()
240
+ self.channel_attention = ChannelAttention(c1)
241
+ self.spatial_attention = SpatialAttention(kernel_size)
242
+
243
+ def forward(self, x):
244
+ return self.spatial_attention(self.channel_attention(x))
245
+
246
+
247
+ class C1(nn.Module):
248
+ # CSP Bottleneck with 3 convolutions
249
+ def __init__(self, c1, c2, n=1): # ch_in, ch_out, number, shortcut, groups, expansion
250
+ super().__init__()
251
+ self.cv1 = Conv(c1, c2, 1, 1)
252
+ self.m = nn.Sequential(*(Conv(c2, c2, 3) for _ in range(n)))
253
+
254
+ def forward(self, x):
255
+ y = self.cv1(x)
256
+ return self.m(y) + y
257
+
258
+
259
+ class C3x(C3):
260
+ # C3 module with cross-convolutions
261
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
262
+ super().__init__(c1, c2, n, shortcut, g, e)
263
+ self.c_ = int(c2 * e)
264
+ self.m = nn.Sequential(*(Bottleneck(self.c_, self.c_, shortcut, g, k=((1, 3), (3, 1)), e=1) for _ in range(n)))
265
+
266
+
267
+ class C3TR(C3):
268
+ # C3 module with TransformerBlock()
269
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
270
+ super().__init__(c1, c2, n, shortcut, g, e)
271
+ c_ = int(c2 * e)
272
+ self.m = TransformerBlock(c_, c_, 4, n)
273
+
274
+
275
+ class C3Ghost(C3):
276
+ # C3 module with GhostBottleneck()
277
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
278
+ super().__init__(c1, c2, n, shortcut, g, e)
279
+ c_ = int(c2 * e) # hidden channels
280
+ self.m = nn.Sequential(*(GhostBottleneck(c_, c_) for _ in range(n)))
281
+
282
+
283
+ class SPP(nn.Module):
284
+ # Spatial Pyramid Pooling (SPP) layer https://arxiv.org/abs/1406.4729
285
+ def __init__(self, c1, c2, k=(5, 9, 13)):
286
+ super().__init__()
287
+ c_ = c1 // 2 # hidden channels
288
+ self.cv1 = Conv(c1, c_, 1, 1)
289
+ self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
290
+ self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
291
+
292
+ def forward(self, x):
293
+ x = self.cv1(x)
294
+ with warnings.catch_warnings():
295
+ warnings.simplefilter('ignore') # suppress torch 1.9.0 max_pool2d() warning
296
+ return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))
297
+
298
+
299
+ class SPPF(nn.Module):
300
+ # Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
301
+ def __init__(self, c1, c2, k=5): # equivalent to SPP(k=(5, 9, 13))
302
+ super().__init__()
303
+ c_ = c1 // 2 # hidden channels
304
+ self.cv1 = Conv(c1, c_, 1, 1)
305
+ self.cv2 = Conv(c_ * 4, c2, 1, 1)
306
+ self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
307
+
308
+ def forward(self, x):
309
+ x = self.cv1(x)
310
+ with warnings.catch_warnings():
311
+ warnings.simplefilter('ignore') # suppress torch 1.9.0 max_pool2d() warning
312
+ y1 = self.m(x)
313
+ y2 = self.m(y1)
314
+ return self.cv2(torch.cat((x, y1, y2, self.m(y2)), 1))
315
+
316
+
317
+ class Focus(nn.Module):
318
+ # Focus wh information into c-space
319
+ def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
320
+ super().__init__()
321
+ self.conv = Conv(c1 * 4, c2, k, s, p, g, act=act)
322
+ # self.contract = Contract(gain=2)
323
+
324
+ def forward(self, x): # x(b,c,w,h) -> y(b,4c,w/2,h/2)
325
+ return self.conv(torch.cat((x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]), 1))
326
+ # return self.conv(self.contract(x))
327
+
328
+
329
+ class GhostConv(nn.Module):
330
+ # Ghost Convolution https://github.com/huawei-noah/ghostnet
331
+ def __init__(self, c1, c2, k=1, s=1, g=1, act=True): # ch_in, ch_out, kernel, stride, groups
332
+ super().__init__()
333
+ c_ = c2 // 2 # hidden channels
334
+ self.cv1 = Conv(c1, c_, k, s, None, g, act=act)
335
+ self.cv2 = Conv(c_, c_, 5, 1, None, c_, act=act)
336
+
337
+ def forward(self, x):
338
+ y = self.cv1(x)
339
+ return torch.cat((y, self.cv2(y)), 1)
340
+
341
+
342
+ class GhostBottleneck(nn.Module):
343
+ # Ghost Bottleneck https://github.com/huawei-noah/ghostnet
344
+ def __init__(self, c1, c2, k=3, s=1): # ch_in, ch_out, kernel, stride
345
+ super().__init__()
346
+ c_ = c2 // 2
347
+ self.conv = nn.Sequential(
348
+ GhostConv(c1, c_, 1, 1), # pw
349
+ DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(), # dw
350
+ GhostConv(c_, c2, 1, 1, act=False)) # pw-linear
351
+ self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False), Conv(c1, c2, 1, 1,
352
+ act=False)) if s == 2 else nn.Identity()
353
+
354
+ def forward(self, x):
355
+ return self.conv(x) + self.shortcut(x)
356
+
357
+
358
+ class Concat(nn.Module):
359
+ # Concatenate a list of tensors along dimension
360
+ def __init__(self, dimension=1):
361
+ super().__init__()
362
+ self.d = dimension
363
+
364
+ def forward(self, x):
365
+ return torch.cat(x, self.d)
366
+
367
+
368
+ class AutoShape(nn.Module):
369
+ # YOLOv5 input-robust model wrapper for passing cv2/np/PIL/torch inputs. Includes preprocessing, inference and NMS
370
+ conf = 0.25 # NMS confidence threshold
371
+ iou = 0.45 # NMS IoU threshold
372
+ agnostic = False # NMS class-agnostic
373
+ multi_label = False # NMS multiple labels per box
374
+ classes = None # (optional list) filter by class, i.e. = [0, 15, 16] for COCO persons, cats and dogs
375
+ max_det = 1000 # maximum number of detections per image
376
+ amp = False # Automatic Mixed Precision (AMP) inference
377
+
378
+ def __init__(self, model, verbose=True):
379
+ super().__init__()
380
+ if verbose:
381
+ LOGGER.info('Adding AutoShape... ')
382
+ copy_attr(self, model, include=('yaml', 'nc', 'hyp', 'names', 'stride', 'abc'), exclude=()) # copy attributes
383
+ self.dmb = isinstance(model, AutoBackend) # DetectMultiBackend() instance
384
+ self.pt = not self.dmb or model.pt # PyTorch model
385
+ self.model = model.eval()
386
+ if self.pt:
387
+ m = self.model.model.model[-1] if self.dmb else self.model.model[-1] # Detect()
388
+ m.inplace = False # Detect.inplace=False for safe multithread inference
389
+ m.export = True # do not output loss values
390
+
391
+ def _apply(self, fn):
392
+ # Apply to(), cpu(), cuda(), half() to model tensors that are not parameters or registered buffers
393
+ self = super()._apply(fn)
394
+ if self.pt:
395
+ m = self.model.model.model[-1] if self.dmb else self.model.model[-1] # Detect()
396
+ m.stride = fn(m.stride)
397
+ m.grid = list(map(fn, m.grid))
398
+ if isinstance(m.anchor_grid, list):
399
+ m.anchor_grid = list(map(fn, m.anchor_grid))
400
+ return self
401
+
402
+ @smart_inference_mode()
403
+ def forward(self, ims, size=640, augment=False, profile=False):
404
+ # Inference from various sources. For size(height=640, width=1280), RGB images example inputs are:
405
+ # file: ims = 'data/images/zidane.jpg' # str or PosixPath
406
+ # URI: = 'https://ultralytics.com/images/zidane.jpg'
407
+ # OpenCV: = cv2.imread('image.jpg')[:,:,::-1] # HWC BGR to RGB x(640,1280,3)
408
+ # PIL: = Image.open('image.jpg') or ImageGrab.grab() # HWC x(640,1280,3)
409
+ # numpy: = np.zeros((640,1280,3)) # HWC
410
+ # torch: = torch.zeros(16,3,320,640) # BCHW (scaled to size=640, 0-1 values)
411
+ # multiple: = [Image.open('image1.jpg'), Image.open('image2.jpg'), ...] # list of images
412
+
413
+ dt = (Profile(), Profile(), Profile())
414
+ with dt[0]:
415
+ if isinstance(size, int): # expand
416
+ size = (size, size)
417
+ p = next(self.model.parameters()) if self.pt else torch.empty(1, device=self.model.device) # param
418
+ autocast = self.amp and (p.device.type != 'cpu') # Automatic Mixed Precision (AMP) inference
419
+ if isinstance(ims, torch.Tensor): # torch
420
+ with amp.autocast(autocast):
421
+ return self.model(ims.to(p.device).type_as(p), augment=augment) # inference
422
+
423
+ # Pre-process
424
+ n, ims = (len(ims), list(ims)) if isinstance(ims, (list, tuple)) else (1, [ims]) # number, list of images
425
+ shape0, shape1, files = [], [], [] # image and inference shapes, filenames
426
+ for i, im in enumerate(ims):
427
+ f = f'image{i}' # filename
428
+ if isinstance(im, (str, Path)): # filename or uri
429
+ im, f = Image.open(requests.get(im, stream=True).raw if str(im).startswith('http') else im), im
430
+ im = np.asarray(ImageOps.exif_transpose(im))
431
+ elif isinstance(im, Image.Image): # PIL Image
432
+ im, f = np.asarray(ImageOps.exif_transpose(im)), getattr(im, 'filename', f) or f
433
+ files.append(Path(f).with_suffix('.jpg').name)
434
+ if im.shape[0] < 5: # image in CHW
435
+ im = im.transpose((1, 2, 0)) # reverse dataloader .transpose(2, 0, 1)
436
+ im = im[..., :3] if im.ndim == 3 else cv2.cvtColor(im, cv2.COLOR_GRAY2BGR) # enforce 3ch input
437
+ s = im.shape[:2] # HWC
438
+ shape0.append(s) # image shape
439
+ g = max(size) / max(s) # gain
440
+ shape1.append([y * g for y in s])
441
+ ims[i] = im if im.data.contiguous else np.ascontiguousarray(im) # update
442
+ shape1 = [make_divisible(x, self.stride) for x in np.array(shape1).max(0)] if self.pt else size # inf shape
443
+ x = [LetterBox(shape1, auto=False)(image=im)["img"] for im in ims] # pad
444
+ x = np.ascontiguousarray(np.array(x).transpose((0, 3, 1, 2))) # stack and BHWC to BCHW
445
+ x = torch.from_numpy(x).to(p.device).type_as(p) / 255 # uint8 to fp16/32
446
+
447
+ with amp.autocast(autocast):
448
+ # Inference
449
+ with dt[1]:
450
+ y = self.model(x, augment=augment) # forward
451
+
452
+ # Post-process
453
+ with dt[2]:
454
+ y = non_max_suppression(y if self.dmb else y[0],
455
+ self.conf,
456
+ self.iou,
457
+ self.classes,
458
+ self.agnostic,
459
+ self.multi_label,
460
+ max_det=self.max_det) # NMS
461
+ for i in range(n):
462
+ scale_boxes(shape1, y[i][:, :4], shape0[i])
463
+
464
+ return Detections(ims, y, files, dt, self.names, x.shape)
465
+
466
+
467
+ class Detections:
468
+ # YOLOv5 detections class for inference results
469
+ def __init__(self, ims, pred, files, times=(0, 0, 0), names=None, shape=None):
470
+ super().__init__()
471
+ d = pred[0].device # device
472
+ gn = [torch.tensor([*(im.shape[i] for i in [1, 0, 1, 0]), 1, 1], device=d) for im in ims] # normalizations
473
+ self.ims = ims # list of images as numpy arrays
474
+ self.pred = pred # list of tensors pred[0] = (xyxy, conf, cls)
475
+ self.names = names # class names
476
+ self.files = files # image filenames
477
+ self.times = times # profiling times
478
+ self.xyxy = pred # xyxy pixels
479
+ self.xywh = [xyxy2xywh(x) for x in pred] # xywh pixels
480
+ self.xyxyn = [x / g for x, g in zip(self.xyxy, gn)] # xyxy normalized
481
+ self.xywhn = [x / g for x, g in zip(self.xywh, gn)] # xywh normalized
482
+ self.n = len(self.pred) # number of images (batch size)
483
+ self.t = tuple(x.t / self.n * 1E3 for x in times) # timestamps (ms)
484
+ self.s = tuple(shape) # inference BCHW shape
485
+
486
+ def _run(self, pprint=False, show=False, save=False, crop=False, render=False, labels=True, save_dir=Path('')):
487
+ s, crops = '', []
488
+ for i, (im, pred) in enumerate(zip(self.ims, self.pred)):
489
+ s += f'\nimage {i + 1}/{len(self.pred)}: {im.shape[0]}x{im.shape[1]} ' # string
490
+ if pred.shape[0]:
491
+ for c in pred[:, -1].unique():
492
+ n = (pred[:, -1] == c).sum() # detections per class
493
+ s += f"{n} {self.names[int(c)]}{'s' * (n > 1)}, " # add to string
494
+ s = s.rstrip(', ')
495
+ if show or save or render or crop:
496
+ annotator = Annotator(im, example=str(self.names))
497
+ for *box, conf, cls in reversed(pred): # xyxy, confidence, class
498
+ label = f'{self.names[int(cls)]} {conf:.2f}'
499
+ if crop:
500
+ file = save_dir / 'crops' / self.names[int(cls)] / self.files[i] if save else None
501
+ crops.append({
502
+ 'box': box,
503
+ 'conf': conf,
504
+ 'cls': cls,
505
+ 'label': label,
506
+ 'im': save_one_box(box, im, file=file, save=save)})
507
+ else: # all others
508
+ annotator.box_label(box, label if labels else '', color=colors(cls))
509
+ im = annotator.im
510
+ else:
511
+ s += '(no detections)'
512
+
513
+ im = Image.fromarray(im.astype(np.uint8)) if isinstance(im, np.ndarray) else im # from np
514
+ if show:
515
+ im.show(self.files[i]) # show
516
+ if save:
517
+ f = self.files[i]
518
+ im.save(save_dir / f) # save
519
+ if i == self.n - 1:
520
+ LOGGER.info(f"Saved {self.n} image{'s' * (self.n > 1)} to {colorstr('bold', save_dir)}")
521
+ if render:
522
+ self.ims[i] = np.asarray(im)
523
+ if pprint:
524
+ s = s.lstrip('\n')
525
+ return f'{s}\nSpeed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {self.s}' % self.t
526
+ if crop:
527
+ if save:
528
+ LOGGER.info(f'Saved results to {save_dir}\n')
529
+ return crops
530
+
531
+ def show(self, labels=True):
532
+ self._run(show=True, labels=labels) # show results
533
+
534
+ def save(self, labels=True, save_dir='runs/detect/exp', exist_ok=False):
535
+ save_dir = increment_path(save_dir, exist_ok, mkdir=True) # increment save_dir
536
+ self._run(save=True, labels=labels, save_dir=save_dir) # save results
537
+
538
+ def crop(self, save=True, save_dir='runs/detect/exp', exist_ok=False):
539
+ save_dir = increment_path(save_dir, exist_ok, mkdir=True) if save else None
540
+ return self._run(crop=True, save=save, save_dir=save_dir) # crop results
541
+
542
+ def render(self, labels=True):
543
+ self._run(render=True, labels=labels) # render results
544
+ return self.ims
545
+
546
+ def pandas(self):
547
+ # return detections as pandas DataFrames, i.e. print(results.pandas().xyxy[0])
548
+ new = copy(self) # return copy
549
+ ca = 'xmin', 'ymin', 'xmax', 'ymax', 'confidence', 'class', 'name' # xyxy columns
550
+ cb = 'xcenter', 'ycenter', 'width', 'height', 'confidence', 'class', 'name' # xywh columns
551
+ for k, c in zip(['xyxy', 'xyxyn', 'xywh', 'xywhn'], [ca, ca, cb, cb]):
552
+ a = [[x[:5] + [int(x[5]), self.names[int(x[5])]] for x in x.tolist()] for x in getattr(self, k)] # update
553
+ setattr(new, k, [pd.DataFrame(x, columns=c) for x in a])
554
+ return new
555
+
556
+ def tolist(self):
557
+ # return a list of Detections objects, i.e. 'for result in results.tolist():'
558
+ r = range(self.n) # iterable
559
+ x = [Detections([self.ims[i]], [self.pred[i]], [self.files[i]], self.times, self.names, self.s) for i in r]
560
+ # for d in x:
561
+ # for k in ['ims', 'pred', 'xyxy', 'xyxyn', 'xywh', 'xywhn']:
562
+ # setattr(d, k, getattr(d, k)[0]) # pop out of list
563
+ return x
564
+
565
+ def print(self):
566
+ LOGGER.info(self.__str__())
567
+
568
+ def __len__(self): # override len(results)
569
+ return self.n
570
+
571
+ def __str__(self): # override print(results)
572
+ return self._run(pprint=True) # print results
573
+
574
+ def __repr__(self):
575
+ return f'YOLOv5 {self.__class__} instance\n' + self.__str__()
576
+
577
+
578
+ class Proto(nn.Module):
579
+ # YOLOv8 mask Proto module for segmentation models
580
+ def __init__(self, c1, c_=256, c2=32): # ch_in, number of protos, number of masks
581
+ super().__init__()
582
+ self.cv1 = Conv(c1, c_, k=3)
583
+ self.upsample = nn.ConvTranspose2d(c_, c_, 2, 2, 0, bias=True) # nn.Upsample(scale_factor=2, mode='nearest')
584
+ self.cv2 = Conv(c_, c_, k=3)
585
+ self.cv3 = Conv(c_, c2)
586
+
587
+ def forward(self, x):
588
+ return self.cv3(self.cv2(self.upsample(self.cv1(x))))
589
+
590
+
591
+ class Ensemble(nn.ModuleList):
592
+ # Ensemble of models
593
+ def __init__(self):
594
+ super().__init__()
595
+
596
+ def forward(self, x, augment=False, profile=False, visualize=False):
597
+ y = [module(x, augment, profile, visualize)[0] for module in self]
598
+ # y = torch.stack(y).max(0)[0] # max ensemble
599
+ # y = torch.stack(y).mean(0) # mean ensemble
600
+ y = torch.cat(y, 1) # nms ensemble
601
+ return y, None # inference, train output
602
+
603
+
604
+ # heads
605
+ class Detect(nn.Module):
606
+ # YOLOv5 Detect head for detection models
607
+ dynamic = False # force grid reconstruction
608
+ export = False # export mode
609
+ shape = None
610
+ anchors = torch.empty(0) # init
611
+ strides = torch.empty(0) # init
612
+
613
+ def __init__(self, nc=80, ch=()): # detection layer
614
+ super().__init__()
615
+ self.nc = nc # number of classes
616
+ self.nl = len(ch) # number of detection layers
617
+ self.reg_max = 16 # DFL channels (ch[0] // 16 to scale 4/8/12/16/20 for n/s/m/l/x)
618
+ self.no = nc + self.reg_max * 4 # number of outputs per anchor
619
+ self.stride = torch.zeros(self.nl) # strides computed during build
620
+
621
+ c2, c3 = max((16, ch[0] // 4, self.reg_max * 4)), max(ch[0], self.nc) # channels
622
+ self.cv2 = nn.ModuleList(
623
+ nn.Sequential(Conv(x, c2, 3), Conv(c2, c2, 3), nn.Conv2d(c2, 4 * self.reg_max, 1)) for x in ch)
624
+ self.cv3 = nn.ModuleList(nn.Sequential(Conv(x, c3, 3), Conv(c3, c3, 3), nn.Conv2d(c3, self.nc, 1)) for x in ch)
625
+ self.dfl = DFL(self.reg_max) if self.reg_max > 1 else nn.Identity()
626
+
627
+ def forward(self, x):
628
+ shape = x[0].shape # BCHW
629
+ for i in range(self.nl):
630
+ x[i] = torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)
631
+ if self.training:
632
+ return x
633
+ elif self.dynamic or self.shape != shape:
634
+ self.anchors, self.strides = (x.transpose(0, 1) for x in make_anchors(x, self.stride, 0.5))
635
+ self.shape = shape
636
+
637
+ box, cls = torch.cat([xi.view(shape[0], self.no, -1) for xi in x], 2).split((self.reg_max * 4, self.nc), 1)
638
+ dbox = dist2bbox(self.dfl(box), self.anchors.unsqueeze(0), xywh=True, dim=1) * self.strides
639
+ y = torch.cat((dbox, cls.sigmoid()), 1)
640
+ return y if self.export else (y, x)
641
+
642
+ def bias_init(self):
643
+ # Initialize Detect() biases, WARNING: requires stride availability
644
+ m = self # self.model[-1] # Detect() module
645
+ # cf = torch.bincount(torch.tensor(np.concatenate(dataset.labels, 0)[:, 0]).long(), minlength=nc) + 1
646
+ # ncf = math.log(0.6 / (m.nc - 0.999999)) if cf is None else torch.log(cf / cf.sum()) # nominal class frequency
647
+ for a, b, s in zip(m.cv2, m.cv3, m.stride): # from
648
+ a[-1].bias.data[:] = 1.0 # box
649
+ b[-1].bias.data[:m.nc] = math.log(5 / m.nc / (640 / s) ** 2) # cls (.01 objects, 80 classes, 640 img)
650
+
651
+
652
+ class Segment(Detect):
653
+ # YOLOv5 Segment head for segmentation models
654
+ def __init__(self, nc=80, nm=32, npr=256, ch=()):
655
+ super().__init__(nc, ch)
656
+ self.nm = nm # number of masks
657
+ self.npr = npr # number of protos
658
+ self.proto = Proto(ch[0], self.npr, self.nm) # protos
659
+ self.detect = Detect.forward
660
+
661
+ c4 = max(ch[0] // 4, self.nm)
662
+ self.cv4 = nn.ModuleList(nn.Sequential(Conv(x, c4, 3), Conv(c4, c4, 3), nn.Conv2d(c4, self.nm, 1)) for x in ch)
663
+
664
+ def forward(self, x):
665
+ p = self.proto(x[0]) # mask protos
666
+ bs = p.shape[0] # batch size
667
+
668
+ mc = torch.cat([self.cv4[i](x[i]).view(bs, self.nm, -1) for i in range(self.nl)], 2) # mask coefficients
669
+ x = self.detect(self, x)
670
+ if self.training:
671
+ return x, mc, p
672
+ return (torch.cat([x, mc], 1), p) if self.export else (torch.cat([x[0], mc], 1), (x[1], mc, p))
673
+
674
+
675
+ class Classify(nn.Module):
676
+ # YOLOv5 classification head, i.e. x(b,c1,20,20) to x(b,c2)
677
+ def __init__(self, c1, c2, k=1, s=1, p=None, g=1): # ch_in, ch_out, kernel, stride, padding, groups
678
+ super().__init__()
679
+ c_ = 1280 # efficientnet_b0 size
680
+ self.conv = Conv(c1, c_, k, s, autopad(k, p), g)
681
+ self.pool = nn.AdaptiveAvgPool2d(1) # to x(b,c_,1,1)
682
+ self.drop = nn.Dropout(p=0.0, inplace=True)
683
+ self.linear = nn.Linear(c_, c2) # to x(b,c2)
684
+
685
+ def forward(self, x):
686
+ if isinstance(x, list):
687
+ x = torch.cat(x, 1)
688
+ return self.linear(self.drop(self.pool(self.conv(x)).flatten(1)))
ultralytics/nn/tasks.py ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import contextlib
4
+ from copy import deepcopy
5
+
6
+ import thop
7
+ import torch
8
+ import torch.nn as nn
9
+
10
+ from ultralytics.nn.modules import (C1, C2, C3, C3TR, SPP, SPPF, Bottleneck, BottleneckCSP, C2f, C3Ghost, C3x, Classify,
11
+ Concat, Conv, ConvTranspose, Detect, DWConv, DWConvTranspose2d, Ensemble, Focus,
12
+ GhostBottleneck, GhostConv, Segment)
13
+ from ultralytics.yolo.utils import DEFAULT_CONFIG_DICT, DEFAULT_CONFIG_KEYS, LOGGER, colorstr, yaml_load
14
+ from ultralytics.yolo.utils.checks import check_yaml
15
+ from ultralytics.yolo.utils.torch_utils import (fuse_conv_and_bn, initialize_weights, intersect_dicts, make_divisible,
16
+ model_info, scale_img, time_sync)
17
+
18
+
19
+ class BaseModel(nn.Module):
20
+ '''
21
+ The BaseModel class is a base class for all the models in the Ultralytics YOLO family.
22
+ '''
23
+
24
+ def forward(self, x, profile=False, visualize=False):
25
+ """
26
+ > `forward` is a wrapper for `_forward_once` that runs the model on a single scale
27
+
28
+ Args:
29
+ x: the input image
30
+ profile: whether to profile the model. Defaults to False
31
+ visualize: if True, will return the intermediate feature maps. Defaults to False
32
+
33
+ Returns:
34
+ The output of the network.
35
+ """
36
+ return self._forward_once(x, profile, visualize)
37
+
38
+ def _forward_once(self, x, profile=False, visualize=False):
39
+ """
40
+ > Forward pass of the network
41
+
42
+ Args:
43
+ x: input to the model
44
+ profile: if True, the time taken for each layer will be printed. Defaults to False
45
+ visualize: If True, it will save the feature maps of the model. Defaults to False
46
+
47
+ Returns:
48
+ The last layer of the model.
49
+ """
50
+ y, dt = [], [] # outputs
51
+ for m in self.model:
52
+ if m.f != -1: # if not from previous layer
53
+ x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f] # from earlier layers
54
+ if profile:
55
+ self._profile_one_layer(m, x, dt)
56
+ x = m(x) # run
57
+ y.append(x if m.i in self.save else None) # save output
58
+ if visualize:
59
+ pass
60
+ # TODO: feature_visualization(x, m.type, m.i, save_dir=visualize)
61
+ return x
62
+
63
+ def _profile_one_layer(self, m, x, dt):
64
+ """
65
+ It takes a model, an input, and a list of times, and it profiles the model on the input, appending
66
+ the time to the list
67
+
68
+ Args:
69
+ m: the model
70
+ x: the input image
71
+ dt: list of time taken for each layer
72
+ """
73
+ c = m == self.model[-1] # is final layer, copy input as inplace fix
74
+ o = thop.profile(m, inputs=(x.copy() if c else x,), verbose=False)[0] / 1E9 * 2 if thop else 0 # FLOPs
75
+ t = time_sync()
76
+ for _ in range(10):
77
+ m(x.copy() if c else x)
78
+ dt.append((time_sync() - t) * 100)
79
+ if m == self.model[0]:
80
+ LOGGER.info(f"{'time (ms)':>10s} {'GFLOPs':>10s} {'params':>10s} module")
81
+ LOGGER.info(f'{dt[-1]:10.2f} {o:10.2f} {m.np:10.0f} {m.type}')
82
+ if c:
83
+ LOGGER.info(f"{sum(dt):10.2f} {'-':>10s} {'-':>10s} Total")
84
+
85
+ def fuse(self):
86
+ """
87
+ > It takes a model and fuses the Conv2d() and BatchNorm2d() layers into a single layer
88
+
89
+ Returns:
90
+ The model is being returned.
91
+ """
92
+ LOGGER.info('Fusing layers... ')
93
+ for m in self.model.modules():
94
+ if isinstance(m, (Conv, DWConv)) and hasattr(m, 'bn'):
95
+ m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
96
+ delattr(m, 'bn') # remove batchnorm
97
+ m.forward = m.forward_fuse # update forward
98
+ self.info()
99
+ return self
100
+
101
+ def info(self, verbose=False, imgsz=640):
102
+ """
103
+ Prints model information
104
+
105
+ Args:
106
+ verbose: if True, prints out the model information. Defaults to False
107
+ imgsz: the size of the image that the model will be trained on. Defaults to 640
108
+ """
109
+ model_info(self, verbose, imgsz)
110
+
111
+ def _apply(self, fn):
112
+ """
113
+ `_apply()` is a function that applies a function to all the tensors in the model that are not
114
+ parameters or registered buffers
115
+
116
+ Args:
117
+ fn: the function to apply to the model
118
+
119
+ Returns:
120
+ A model that is a Detect() object.
121
+ """
122
+ self = super()._apply(fn)
123
+ m = self.model[-1] # Detect()
124
+ if isinstance(m, (Detect, Segment)):
125
+ m.stride = fn(m.stride)
126
+ m.anchors = fn(m.anchors)
127
+ m.strides = fn(m.strides)
128
+ return self
129
+
130
+ def load(self, weights):
131
+ """
132
+ > This function loads the weights of the model from a file
133
+
134
+ Args:
135
+ weights: The weights to load into the model.
136
+ """
137
+ # Force all tasks to implement this function
138
+ raise NotImplementedError("This function needs to be implemented by derived classes!")
139
+
140
+
141
+ class DetectionModel(BaseModel):
142
+ # YOLOv5 detection model
143
+ def __init__(self, cfg='yolov8n.yaml', ch=3, nc=None, verbose=True): # model, input channels, number of classes
144
+ super().__init__()
145
+ self.yaml = cfg if isinstance(cfg, dict) else yaml_load(check_yaml(cfg), append_filename=True) # cfg dict
146
+
147
+ # Define model
148
+ ch = self.yaml['ch'] = self.yaml.get('ch', ch) # input channels
149
+ if nc and nc != self.yaml['nc']:
150
+ LOGGER.info(f"Overriding model.yaml nc={self.yaml['nc']} with nc={nc}")
151
+ self.yaml['nc'] = nc # override yaml value
152
+ self.model, self.save = parse_model(deepcopy(self.yaml), ch=[ch], verbose=verbose) # model, savelist
153
+ self.names = {i: f'{i}' for i in range(self.yaml['nc'])} # default names dict
154
+ self.inplace = self.yaml.get('inplace', True)
155
+
156
+ # Build strides
157
+ m = self.model[-1] # Detect()
158
+ if isinstance(m, (Detect, Segment)):
159
+ s = 256 # 2x min stride
160
+ m.inplace = self.inplace
161
+ forward = lambda x: self.forward(x)[0] if isinstance(m, Segment) else self.forward(x)
162
+ m.stride = torch.tensor([s / x.shape[-2] for x in forward(torch.zeros(1, ch, s, s))]) # forward
163
+ self.stride = m.stride
164
+ m.bias_init() # only run once
165
+
166
+ # Init weights, biases
167
+ initialize_weights(self)
168
+ if verbose:
169
+ self.info()
170
+ LOGGER.info('')
171
+
172
+ def forward(self, x, augment=False, profile=False, visualize=False):
173
+ if augment:
174
+ return self._forward_augment(x) # augmented inference, None
175
+ return self._forward_once(x, profile, visualize) # single-scale inference, train
176
+
177
+ def _forward_augment(self, x):
178
+ img_size = x.shape[-2:] # height, width
179
+ s = [1, 0.83, 0.67] # scales
180
+ f = [None, 3, None] # flips (2-ud, 3-lr)
181
+ y = [] # outputs
182
+ for si, fi in zip(s, f):
183
+ xi = scale_img(x.flip(fi) if fi else x, si, gs=int(self.stride.max()))
184
+ yi = self._forward_once(xi)[0] # forward
185
+ # cv2.imwrite(f'img_{si}.jpg', 255 * xi[0].cpu().numpy().transpose((1, 2, 0))[:, :, ::-1]) # save
186
+ yi = self._descale_pred(yi, fi, si, img_size)
187
+ y.append(yi)
188
+ y = self._clip_augmented(y) # clip augmented tails
189
+ return torch.cat(y, -1), None # augmented inference, train
190
+
191
+ @staticmethod
192
+ def _descale_pred(p, flips, scale, img_size, dim=1):
193
+ # de-scale predictions following augmented inference (inverse operation)
194
+ p[:, :4] /= scale # de-scale
195
+ x, y, wh, cls = p.split((1, 1, 2, p.shape[dim] - 4), dim)
196
+ if flips == 2:
197
+ y = img_size[0] - y # de-flip ud
198
+ elif flips == 3:
199
+ x = img_size[1] - x # de-flip lr
200
+ return torch.cat((x, y, wh, cls), dim)
201
+
202
+ def _clip_augmented(self, y):
203
+ # Clip YOLOv5 augmented inference tails
204
+ nl = self.model[-1].nl # number of detection layers (P3-P5)
205
+ g = sum(4 ** x for x in range(nl)) # grid points
206
+ e = 1 # exclude layer count
207
+ i = (y[0].shape[-1] // g) * sum(4 ** x for x in range(e)) # indices
208
+ y[0] = y[0][..., :-i] # large
209
+ i = (y[-1].shape[-1] // g) * sum(4 ** (nl - 1 - x) for x in range(e)) # indices
210
+ y[-1] = y[-1][..., i:] # small
211
+ return y
212
+
213
+ def load(self, weights, verbose=True):
214
+ csd = weights.float().state_dict() # checkpoint state_dict as FP32
215
+ csd = intersect_dicts(csd, self.state_dict()) # intersect
216
+ self.load_state_dict(csd, strict=False) # load
217
+ if verbose:
218
+ LOGGER.info(f'Transferred {len(csd)}/{len(self.model.state_dict())} items from pretrained weights')
219
+
220
+
221
+ class SegmentationModel(DetectionModel):
222
+ # YOLOv5 segmentation model
223
+ def __init__(self, cfg='yolov8n-seg.yaml', ch=3, nc=None, verbose=True):
224
+ super().__init__(cfg, ch, nc, verbose)
225
+
226
+
227
+ class ClassificationModel(BaseModel):
228
+ # YOLOv5 classification model
229
+ def __init__(self,
230
+ cfg=None,
231
+ model=None,
232
+ ch=3,
233
+ nc=1000,
234
+ cutoff=10,
235
+ verbose=True): # yaml, model, number of classes, cutoff index
236
+ super().__init__()
237
+ self._from_detection_model(model, nc, cutoff) if model is not None else self._from_yaml(cfg, ch, nc, verbose)
238
+
239
+ def _from_detection_model(self, model, nc=1000, cutoff=10):
240
+ # Create a YOLOv5 classification model from a YOLOv5 detection model
241
+ from ultralytics.nn.autobackend import AutoBackend
242
+ if isinstance(model, AutoBackend):
243
+ model = model.model # unwrap DetectMultiBackend
244
+ model.model = model.model[:cutoff] # backbone
245
+ m = model.model[-1] # last layer
246
+ ch = m.conv.in_channels if hasattr(m, 'conv') else m.cv1.conv.in_channels # ch into module
247
+ c = Classify(ch, nc) # Classify()
248
+ c.i, c.f, c.type = m.i, m.f, 'models.common.Classify' # index, from, type
249
+ model.model[-1] = c # replace
250
+ self.model = model.model
251
+ self.stride = model.stride
252
+ self.save = []
253
+ self.nc = nc
254
+
255
+ def _from_yaml(self, cfg, ch, nc, verbose):
256
+ self.yaml = cfg if isinstance(cfg, dict) else yaml_load(check_yaml(cfg), append_filename=True) # cfg dict
257
+ # Define model
258
+ ch = self.yaml['ch'] = self.yaml.get('ch', ch) # input channels
259
+ if nc and nc != self.yaml['nc']:
260
+ LOGGER.info(f"Overriding model.yaml nc={self.yaml['nc']} with nc={nc}")
261
+ self.yaml['nc'] = nc # override yaml value
262
+ self.model, self.save = parse_model(deepcopy(self.yaml), ch=[ch], verbose=verbose) # model, savelist
263
+ self.names = {i: f'{i}' for i in range(self.yaml['nc'])} # default names dict
264
+ self.info()
265
+
266
+ def load(self, weights):
267
+ model = weights["model"] if isinstance(weights, dict) else weights # torchvision models are not dicts
268
+ csd = model.float().state_dict()
269
+ csd = intersect_dicts(csd, self.state_dict()) # intersect
270
+ self.load_state_dict(csd, strict=False) # load
271
+
272
+ @staticmethod
273
+ def reshape_outputs(model, nc):
274
+ # Update a TorchVision classification model to class count 'n' if required
275
+ name, m = list((model.model if hasattr(model, 'model') else model).named_children())[-1] # last module
276
+ if isinstance(m, Classify): # YOLO Classify() head
277
+ if m.linear.out_features != nc:
278
+ m.linear = nn.Linear(m.linear.in_features, nc)
279
+ elif isinstance(m, nn.Linear): # ResNet, EfficientNet
280
+ if m.out_features != nc:
281
+ setattr(model, name, nn.Linear(m.in_features, nc))
282
+ elif isinstance(m, nn.Sequential):
283
+ types = [type(x) for x in m]
284
+ if nn.Linear in types:
285
+ i = types.index(nn.Linear) # nn.Linear index
286
+ if m[i].out_features != nc:
287
+ m[i] = nn.Linear(m[i].in_features, nc)
288
+ elif nn.Conv2d in types:
289
+ i = types.index(nn.Conv2d) # nn.Conv2d index
290
+ if m[i].out_channels != nc:
291
+ m[i] = nn.Conv2d(m[i].in_channels, nc, m[i].kernel_size, m[i].stride, bias=m[i].bias is not None)
292
+
293
+
294
+ # Functions ------------------------------------------------------------------------------------------------------------
295
+
296
+
297
+ def attempt_load_weights(weights, device=None, inplace=True, fuse=False):
298
+ # Loads an ensemble of models weights=[a,b,c] or a single model weights=[a] or weights=a
299
+ from ultralytics.yolo.utils.downloads import attempt_download
300
+
301
+ model = Ensemble()
302
+ for w in weights if isinstance(weights, list) else [weights]:
303
+ ckpt = torch.load(attempt_download(w), map_location='cpu') # load
304
+ args = {**DEFAULT_CONFIG_DICT, **ckpt['train_args']} # combine model and default args, preferring model args
305
+ ckpt = (ckpt.get('ema') or ckpt['model']).to(device).float() # FP32 model
306
+
307
+ # Model compatibility updates
308
+ ckpt.args = {k: v for k, v in args.items() if k in DEFAULT_CONFIG_KEYS} # attach args to model
309
+ ckpt.pt_path = weights # attach *.pt file path to model
310
+ if not hasattr(ckpt, 'stride'):
311
+ ckpt.stride = torch.tensor([32.])
312
+
313
+ # Append
314
+ model.append(ckpt.fuse().eval() if fuse and hasattr(ckpt, 'fuse') else ckpt.eval()) # model in eval mode
315
+
316
+ # Module compatibility updates
317
+ for m in model.modules():
318
+ t = type(m)
319
+ if t in (nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, Detect, Segment):
320
+ m.inplace = inplace # torch 1.7.0 compatibility
321
+ elif t is nn.Upsample and not hasattr(m, 'recompute_scale_factor'):
322
+ m.recompute_scale_factor = None # torch 1.11.0 compatibility
323
+
324
+ # Return model
325
+ if len(model) == 1:
326
+ return model[-1]
327
+
328
+ # Return ensemble
329
+ print(f'Ensemble created with {weights}\n')
330
+ for k in 'names', 'nc', 'yaml':
331
+ setattr(model, k, getattr(model[0], k))
332
+ model.stride = model[torch.argmax(torch.tensor([m.stride.max() for m in model])).int()].stride # max stride
333
+ assert all(model[0].nc == m.nc for m in model), f'Models have different class counts: {[m.nc for m in model]}'
334
+ return model
335
+
336
+
337
+ def attempt_load_one_weight(weight, device=None, inplace=True, fuse=False):
338
+ # Loads a single model weights
339
+ from ultralytics.yolo.utils.downloads import attempt_download
340
+
341
+ ckpt = torch.load(attempt_download(weight), map_location='cpu') # load
342
+ args = {**DEFAULT_CONFIG_DICT, **ckpt['train_args']} # combine model and default args, preferring model args
343
+ model = (ckpt.get('ema') or ckpt['model']).to(device).float() # FP32 model
344
+
345
+ # Model compatibility updates
346
+ model.args = {k: v for k, v in args.items() if k in DEFAULT_CONFIG_KEYS} # attach args to model
347
+ model.pt_path = weight # attach *.pt file path to model
348
+ if not hasattr(model, 'stride'):
349
+ model.stride = torch.tensor([32.])
350
+
351
+ model = model.fuse().eval() if fuse and hasattr(model, 'fuse') else model.eval() # model in eval mode
352
+
353
+ # Module compatibility updates
354
+ for m in model.modules():
355
+ t = type(m)
356
+ if t in (nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, Detect, Segment):
357
+ m.inplace = inplace # torch 1.7.0 compatibility
358
+ elif t is nn.Upsample and not hasattr(m, 'recompute_scale_factor'):
359
+ m.recompute_scale_factor = None # torch 1.11.0 compatibility
360
+
361
+ # Return model and ckpt
362
+ return model, ckpt
363
+
364
+
365
+ def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)
366
+ # Parse a YOLO model.yaml dictionary
367
+ if verbose:
368
+ LOGGER.info(f"\n{'':>3}{'from':>20}{'n':>3}{'params':>10} {'module':<45}{'arguments':<30}")
369
+ nc, gd, gw, act = d['nc'], d['depth_multiple'], d['width_multiple'], d.get('activation')
370
+ if act:
371
+ Conv.default_act = eval(act) # redefine default activation, i.e. Conv.default_act = nn.SiLU()
372
+ if verbose:
373
+ LOGGER.info(f"{colorstr('activation:')} {act}") # print
374
+
375
+ layers, save, c2 = [], [], ch[-1] # layers, savelist, ch out
376
+ for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']): # from, number, module, args
377
+ m = eval(m) if isinstance(m, str) else m # eval strings
378
+ for j, a in enumerate(args):
379
+ with contextlib.suppress(NameError):
380
+ args[j] = eval(a) if isinstance(a, str) else a # eval strings
381
+
382
+ n = n_ = max(round(n * gd), 1) if n > 1 else n # depth gain
383
+ if m in {
384
+ Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
385
+ BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x}:
386
+ c1, c2 = ch[f], args[0]
387
+ if c2 != nc: # if c2 not equal to number of classes (i.e. for Classify() output)
388
+ c2 = make_divisible(c2 * gw, 8)
389
+
390
+ args = [c1, c2, *args[1:]]
391
+ if m in {BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, C3x}:
392
+ args.insert(2, n) # number of repeats
393
+ n = 1
394
+ elif m is nn.BatchNorm2d:
395
+ args = [ch[f]]
396
+ elif m is Concat:
397
+ c2 = sum(ch[x] for x in f)
398
+ elif m in {Detect, Segment}:
399
+ args.append([ch[x] for x in f])
400
+ if m is Segment:
401
+ args[2] = make_divisible(args[2] * gw, 8)
402
+ else:
403
+ c2 = ch[f]
404
+
405
+ m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args) # module
406
+ t = str(m)[8:-2].replace('__main__.', '') # module type
407
+ m.np = sum(x.numel() for x in m_.parameters()) # number params
408
+ m_.i, m_.f, m_.type = i, f, t # attach index, 'from' index, type
409
+ if verbose:
410
+ LOGGER.info(f'{i:>3}{str(f):>20}{n_:>3}{m.np:10.0f} {t:<45}{str(args):<30}') # print
411
+ save.extend(x % i for x in ([f] if isinstance(f, int) else f) if x != -1) # append to savelist
412
+ layers.append(m_)
413
+ if i == 0:
414
+ ch = []
415
+ ch.append(c2)
416
+ return nn.Sequential(*layers), sorted(save)
ultralytics/yolo/cli.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics YOLO 🚀, GPL-3.0 license
2
+
3
+ import shutil
4
+ from pathlib import Path
5
+
6
+ import hydra
7
+
8
+ from ultralytics import hub, yolo
9
+ from ultralytics.yolo.utils import DEFAULT_CONFIG, LOGGER, colorstr
10
+
11
+ DIR = Path(__file__).parent
12
+
13
+
14
+ @hydra.main(version_base=None, config_path=str(DEFAULT_CONFIG.parent.relative_to(DIR)), config_name=DEFAULT_CONFIG.name)
15
+ def cli(cfg):
16
+ """
17
+ Run a specified task and mode with the given configuration.
18
+
19
+ Args:
20
+ cfg (DictConfig): Configuration for the task and mode.
21
+ """
22
+ # LOGGER.info(f"{colorstr(f'Ultralytics YOLO v{ultralytics.__version__}')}")
23
+ task, mode = cfg.task.lower(), cfg.mode.lower()
24
+
25
+ # Special case for initializing the configuration
26
+ if task == "init":
27
+ shutil.copy2(DEFAULT_CONFIG, Path.cwd())
28
+ LOGGER.info(f"""
29
+ {colorstr("YOLO:")} configuration saved to {Path.cwd() / DEFAULT_CONFIG.name}.
30
+ To run experiments using custom configuration:
31
+ yolo task='task' mode='mode' --config-name config_file.yaml
32
+ """)
33
+ return
34
+
35
+ # Mapping from task to module
36
+ task_module_map = {"detect": yolo.v8.detect, "segment": yolo.v8.segment, "classify": yolo.v8.classify}
37
+ module = task_module_map.get(task)
38
+ if not module:
39
+ raise SyntaxError(f"task not recognized. Choices are {', '.join(task_module_map.keys())}")
40
+
41
+ # Mapping from mode to function
42
+ mode_func_map = {
43
+ "train": module.train,
44
+ "val": module.val,
45
+ "predict": module.predict,
46
+ "export": yolo.engine.exporter.export,
47
+ "checks": hub.checks}
48
+ func = mode_func_map.get(mode)
49
+ if not func:
50
+ raise SyntaxError(f"mode not recognized. Choices are {', '.join(mode_func_map.keys())}")
51
+
52
+ func(cfg)