├── README.md
├── autolabelImg.py
├── data
└── predefined_classes.txt
├── libs
├── __init__.py
├── canvas.py
├── colorDialog.py
├── combobox.py
├── constants.py
├── create_ml_io.py
├── hashableQListWidgetItem.py
├── labelDialog.py
├── labelFile.py
├── pascal_voc_io.py
├── resources.py
├── settings.py
├── shape.py
├── stringBundle.py
├── toolBar.py
├── ustr.py
├── utils.py
├── yolo_io.py
└── zoomWidget.py
├── requirements.txt
├── resources.qrc
├── resources
├── icons
│ ├── app.icns
│ ├── app.png
│ ├── app.svg
│ ├── autolabel-all.png
│ ├── autolabel.png
│ ├── cancel.png
│ ├── close.png
│ ├── color.png
│ ├── color_line.png
│ ├── copy.png
│ ├── delete.png
│ ├── done.png
│ ├── done.svg
│ ├── edit.png
│ ├── expert1.png
│ ├── expert2.png
│ ├── eye.png
│ ├── feBlend-icon.png
│ ├── file.png
│ ├── fit-width.png
│ ├── fit-window.png
│ ├── fit.png
│ ├── format_createml.png
│ ├── format_voc.png
│ ├── format_yolo.png
│ ├── help.png
│ ├── labels.png
│ ├── labels.svg
│ ├── new.png
│ ├── next.png
│ ├── objects.png
│ ├── open.png
│ ├── open.svg
│ ├── prev.png
│ ├── quit.png
│ ├── resetall.png
│ ├── save-as.png
│ ├── save-as.svg
│ ├── save.png
│ ├── save.svg
│ ├── undo-cross.png
│ ├── undo.png
│ ├── verify.png
│ ├── zoom-in.png
│ ├── zoom-out.png
│ └── zoom.png
└── strings
│ ├── strings-ja-JP.properties
│ ├── strings-zh-CN.properties
│ ├── strings-zh-TW.properties
│ └── strings.properties
├── tools
├── change_labels.py
├── label_to_csv.py
└── repeat_filter.py
└── ultralytics
├── __init__.py
├── cfg
├── __init__.py
├── datasets
│ ├── Argoverse.yaml
│ ├── GlobalWheat2020.yaml
│ ├── ImageNet.yaml
│ ├── Objects365.yaml
│ ├── SKU-110K.yaml
│ ├── VOC.yaml
│ ├── VisDrone.yaml
│ ├── coco-pose.yaml
│ ├── coco.yaml
│ ├── coco128-seg.yaml
│ ├── coco128.yaml
│ ├── coco8-pose.yaml
│ ├── coco8-seg.yaml
│ ├── coco8.yaml
│ └── xView.yaml
├── default.yaml
├── models
│ ├── rt-detr
│ │ ├── rtdetr-l.yaml
│ │ └── rtdetr-x.yaml
│ ├── v3
│ │ ├── yolov3-spp.yaml
│ │ ├── yolov3-tiny.yaml
│ │ └── yolov3.yaml
│ ├── v5
│ │ ├── yolov5-p6.yaml
│ │ └── yolov5.yaml
│ ├── v6
│ │ └── yolov6.yaml
│ └── v8
│ │ ├── yolov8-cls.yaml
│ │ ├── yolov8-p2.yaml
│ │ ├── yolov8-p6.yaml
│ │ ├── yolov8-pose-p6.yaml
│ │ ├── yolov8-pose.yaml
│ │ ├── yolov8-rtdetr.yaml
│ │ ├── yolov8-seg.yaml
│ │ └── yolov8.yaml
└── trackers
│ ├── botsort.yaml
│ └── bytetrack.yaml
├── data
├── __init__.py
├── annotator.py
├── augment.py
├── base.py
├── build.py
├── converter.py
├── dataloaders
│ └── __init__.py
├── dataset.py
├── loaders.py
├── scripts
│ ├── download_weights.sh
│ ├── get_coco.sh
│ ├── get_coco128.sh
│ └── get_imagenet.sh
└── utils.py
├── engine
├── __init__.py
├── exporter.py
├── model.py
├── predictor.py
├── results.py
├── trainer.py
└── validator.py
├── hub
├── __init__.py
├── auth.py
├── session.py
└── utils.py
├── models
├── __init__.py
├── fastsam
│ ├── __init__.py
│ ├── model.py
│ ├── predict.py
│ ├── prompt.py
│ ├── utils.py
│ └── val.py
├── nas
│ ├── __init__.py
│ ├── model.py
│ ├── predict.py
│ └── val.py
├── rtdetr
│ ├── __init__.py
│ ├── model.py
│ ├── predict.py
│ ├── train.py
│ └── val.py
├── sam
│ ├── __init__.py
│ ├── amg.py
│ ├── build.py
│ ├── model.py
│ ├── modules
│ │ ├── __init__.py
│ │ ├── decoders.py
│ │ ├── encoders.py
│ │ ├── sam.py
│ │ ├── tiny_encoder.py
│ │ └── transformer.py
│ └── predict.py
├── utils
│ ├── __init__.py
│ ├── loss.py
│ └── ops.py
└── yolo
│ ├── __init__.py
│ ├── classify
│ ├── __init__.py
│ ├── predict.py
│ ├── train.py
│ └── val.py
│ ├── detect
│ ├── __init__.py
│ ├── predict.py
│ ├── train.py
│ └── val.py
│ ├── model.py
│ ├── pose
│ ├── __init__.py
│ ├── predict.py
│ ├── train.py
│ └── val.py
│ └── segment
│ ├── __init__.py
│ ├── predict.py
│ ├── train.py
│ └── val.py
├── nn
├── __init__.py
├── autobackend.py
├── modules
│ ├── __init__.py
│ ├── block.py
│ ├── conv.py
│ ├── head.py
│ ├── transformer.py
│ └── utils.py
└── tasks.py
├── trackers
├── __init__.py
├── basetrack.py
├── bot_sort.py
├── byte_tracker.py
└── track.py
├── utils
├── __init__.py
├── autobatch.py
├── benchmarks.py
├── callbacks
│ ├── __init__.py
│ ├── base.py
│ ├── clearml.py
│ ├── comet.py
│ ├── dvc.py
│ ├── hub.py
│ ├── mlflow.py
│ ├── neptune.py
│ ├── raytune.py
│ ├── tensorboard.py
│ └── wb.py
├── checks.py
├── dist.py
├── downloads.py
├── errors.py
├── files.py
├── instance.py
├── loss.py
├── metrics.py
├── ops.py
├── patches.py
├── plotting.py
├── tal.py
├── torch_utils.py
└── tuner.py
└── yolo
├── __init__.py
├── cfg
└── __init__.py
├── data
└── __init__.py
├── engine
└── __init__.py
├── utils
└── __init__.py
└── v8
└── __init__.py
/README.md:
--------------------------------------------------------------------------------
1 | # AutoLabelImg
2 | [labelImg](https://github.com/HumanSignal/labelImg),内置基于 [YOLOv8](https://github.com/ultralytics/ultralytics) 的自动检测功能。
3 | 目前为英文版,未汉化。
4 |
5 | Built-in labelImg with YOLOv8 based automatic detection function.
6 | Currently in English version, without localization.
7 |
8 | ## 预览图
9 |
10 | 
11 |
12 |
13 | ## 新增功能:
14 | 对应快捷键如下所示。
15 |
16 | ### 1.自动标注
17 | (1).Auto Label:当前图片
18 | (2).Auto Label All:
19 | Current image and after:自动标注当前及之后的图片
20 | All images:自动标注全部图片
21 | Index range of images:自动标注指定序号(包含)间的图片
22 |
23 | ### 2.一键载入
24 | load_data:快速载入上次标注记录点
25 |
26 | ### 3.重框筛选(Label Filter)
27 | filterate计算iou筛选得到列表,Prev、Next前后载入疑似重框标注data。
28 |
29 | ## 使用
30 | (1).default.yaml自动生成
31 | (2).自动标注使用前**确认参数**
32 | - parameter_settings:含conf、iou、classes参数
33 | - model_selection:支持yolov8n、yolov8s、yolov8m、yolov8l、yolov8x
34 | - "./tools/change_labels.py"修改检测类别序号(coco --> 当前任务)
35 | - def rework_classes(default=False):禁用修改
36 | - def replace(line):按任务及使用情况灵活修改,默认2,5,7 --> 2。
37 | (3).重框筛选使用前**确认参数**
38 | filter_conf、check_ls两个参数,在default.yaml中修改
39 |
40 | ## Installation
41 | #### Windows + Anaconda
42 | 个人配置:NVIDIA GTX 1650 + cuda11.7
43 |
44 | 1.配置环境:
45 | ```pythonscript
46 | conda create -n yourvenv python=3.8
47 | conda activate yourvenv
48 | pip install pyqt5
49 | conda install -c anaconda lxml
50 | 安装torch:https://pytorch.org/
51 |
52 | cd "your dir path"
53 | pip install -r requirements.txt
54 | pyrcc5 -o libs/resources.py resources.qrc
55 | python labelImg.py
56 | ```
57 |
58 | 2.下载模型:
59 | 根目录创建models文件夹,从[YOLOv8](https://github.com/ultralytics/ultralytics)中下载pt权重文件并放至文件夹内。
60 |
61 | 注:python3.10以上易崩,labelimg标框所用库数据格式不兼容等原因。
62 |
63 | ## Hotkeys
64 |
65 | 快捷键 | 功能
66 | -------- | -----
67 | Ctrl + u | 从文件夹路径加载图片
68 | Ctrl + r | 设置保存路径
69 | Ctrl + s | 保存
70 | Ctrl + d | 复制矩形框
71 | Ctrl + Shift + d | 删除当前图像
72 | w | 创建一个矩形框
73 | d | 下一张图像
74 | a | 上一张图像
75 | del | 删除所选矩形框
76 | ↑→↓← | 移动选定矩形框
77 |
78 | 新增快捷键 | 对应项
79 | -------- | -----
80 | Ctrl + p | Auto Label
81 | Ctrl + m | Auto Label All
82 | F5 | load_data
83 | filterate | F8
84 | Prev | F10
85 | Next | F12
86 |
87 | ## 程序崩溃原因
88 |
89 | 1."./data/predefined_classes.txt"与classes.txt不一致。
90 | 2.载入崩溃:删除C:\Users\用户名路径下的.labelImgSettings.pkl文件。
91 | 3.小概率画框/调框/删框时崩溃,未解决。重启、F5载入即可。
92 |
93 |
94 |
95 | ## Contact information
96 |
97 | *WeChat*:SW_7396
98 | *Email 163*:personalmailboxbyT@163.com
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/data/predefined_classes.txt:
--------------------------------------------------------------------------------
1 | person
2 | car
3 | bicycle
4 | bus
--------------------------------------------------------------------------------
/libs/__init__.py:
--------------------------------------------------------------------------------
1 | __version_info__ = ('1', '8', '5')
2 | __version__ = '.'.join(__version_info__)
3 |
--------------------------------------------------------------------------------
/libs/colorDialog.py:
--------------------------------------------------------------------------------
1 | try:
2 | from PyQt5.QtGui import *
3 | from PyQt5.QtCore import *
4 | from PyQt5.QtWidgets import QColorDialog, QDialogButtonBox
5 | except ImportError:
6 | from PyQt4.QtGui import *
7 | from PyQt4.QtCore import *
8 |
9 | BB = QDialogButtonBox
10 |
11 |
12 | class ColorDialog(QColorDialog):
13 |
14 | def __init__(self, parent=None):
15 | super(ColorDialog, self).__init__(parent)
16 | self.setOption(QColorDialog.ShowAlphaChannel)
17 | # The Mac native dialog does not support our restore button.
18 | self.setOption(QColorDialog.DontUseNativeDialog)
19 | # Add a restore defaults button.
20 | # The default is set at invocation time, so that it
21 | # works across dialogs for different elements.
22 | self.default = None
23 | self.bb = self.layout().itemAt(1).widget()
24 | self.bb.addButton(BB.RestoreDefaults)
25 | self.bb.clicked.connect(self.check_restore)
26 |
27 | def getColor(self, value=None, title=None, default=None):
28 | self.default = default
29 | if title:
30 | self.setWindowTitle(title)
31 | if value:
32 | self.setCurrentColor(value)
33 | return self.currentColor() if self.exec_() else None
34 |
35 | def check_restore(self, button):
36 | if self.bb.buttonRole(button) & BB.ResetRole and self.default:
37 | self.setCurrentColor(self.default)
38 |
--------------------------------------------------------------------------------
/libs/combobox.py:
--------------------------------------------------------------------------------
1 | import sys
2 | try:
3 | from PyQt5.QtWidgets import QWidget, QHBoxLayout, QComboBox
4 | except ImportError:
5 | # needed for py3+qt4
6 | # Ref:
7 | # http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html
8 | # http://stackoverflow.com/questions/21217399/pyqt4-qtcore-qvariant-object-instead-of-a-string
9 | if sys.version_info.major >= 3:
10 | import sip
11 | sip.setapi('QVariant', 2)
12 | from PyQt4.QtGui import QWidget, QHBoxLayout, QComboBox
13 |
14 |
15 | class ComboBox(QWidget):
16 | def __init__(self, parent=None, items=[]):
17 | super(ComboBox, self).__init__(parent)
18 |
19 | layout = QHBoxLayout()
20 | self.cb = QComboBox()
21 | self.items = items
22 | self.cb.addItems(self.items)
23 |
24 | self.cb.currentIndexChanged.connect(parent.combo_selection_changed)
25 |
26 | layout.addWidget(self.cb)
27 | self.setLayout(layout)
28 |
29 | def update_items(self, items):
30 | self.items = items
31 |
32 | self.cb.clear()
33 | self.cb.addItems(self.items)
34 |
--------------------------------------------------------------------------------
/libs/constants.py:
--------------------------------------------------------------------------------
1 | SETTING_FILENAME = 'filename'
2 | SETTING_RECENT_FILES = 'recentFiles'
3 | SETTING_WIN_SIZE = 'window/size'
4 | SETTING_WIN_POSE = 'window/position'
5 | SETTING_WIN_GEOMETRY = 'window/geometry'
6 | SETTING_LINE_COLOR = 'line/color'
7 | SETTING_FILL_COLOR = 'fill/color'
8 | SETTING_ADVANCE_MODE = 'advanced'
9 | SETTING_WIN_STATE = 'window/state'
10 | SETTING_SAVE_DIR = 'savedir'
11 | SETTING_PAINT_LABEL = 'paintlabel'
12 | SETTING_LAST_OPEN_DIR = 'lastOpenDir'
13 | SETTING_AUTO_SAVE = 'autosave'
14 | SETTING_SINGLE_CLASS = 'singleclass'
15 | FORMAT_PASCALVOC='PascalVOC'
16 | FORMAT_YOLO='YOLO'
17 | FORMAT_CREATEML='CreateML'
18 | SETTING_DRAW_SQUARE = 'draw/square'
19 | SETTING_LABEL_FILE_FORMAT= 'labelFileFormat'
20 | DEFAULT_ENCODING = 'utf-8'
21 |
--------------------------------------------------------------------------------
/libs/create_ml_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf8 -*-
3 | import json
4 | from pathlib import Path
5 |
6 | from libs.constants import DEFAULT_ENCODING
7 | import os
8 |
9 | JSON_EXT = '.json'
10 | ENCODE_METHOD = DEFAULT_ENCODING
11 |
12 |
13 | class CreateMLWriter:
14 | def __init__(self, folder_name, filename, img_size, shapes, output_file, database_src='Unknown', local_img_path=None):
15 | self.folder_name = folder_name
16 | self.filename = filename
17 | self.database_src = database_src
18 | self.img_size = img_size
19 | self.box_list = []
20 | self.local_img_path = local_img_path
21 | self.verified = False
22 | self.shapes = shapes
23 | self.output_file = output_file
24 |
25 | def write(self):
26 | if os.path.isfile(self.output_file):
27 | with open(self.output_file, "r") as file:
28 | input_data = file.read()
29 | output_dict = json.loads(input_data)
30 | else:
31 | output_dict = []
32 |
33 | output_image_dict = {
34 | "image": self.filename,
35 | "annotations": []
36 | }
37 |
38 | for shape in self.shapes:
39 | points = shape["points"]
40 |
41 | x1 = points[0][0]
42 | y1 = points[0][1]
43 | x2 = points[1][0]
44 | y2 = points[2][1]
45 |
46 | height, width, x, y = self.calculate_coordinates(x1, x2, y1, y2)
47 |
48 | shape_dict = {
49 | "label": shape["label"],
50 | "coordinates": {
51 | "x": x,
52 | "y": y,
53 | "width": width,
54 | "height": height
55 | }
56 | }
57 | output_image_dict["annotations"].append(shape_dict)
58 |
59 | # check if image already in output
60 | exists = False
61 | for i in range(0, len(output_dict)):
62 | if output_dict[i]["image"] == output_image_dict["image"]:
63 | exists = True
64 | output_dict[i] = output_image_dict
65 | break
66 |
67 | if not exists:
68 | output_dict.append(output_image_dict)
69 |
70 | Path(self.output_file).write_text(json.dumps(output_dict), ENCODE_METHOD)
71 |
72 | def calculate_coordinates(self, x1, x2, y1, y2):
73 | if x1 < x2:
74 | x_min = x1
75 | x_max = x2
76 | else:
77 | x_min = x2
78 | x_max = x1
79 | if y1 < y2:
80 | y_min = y1
81 | y_max = y2
82 | else:
83 | y_min = y2
84 | y_max = y1
85 | width = x_max - x_min
86 | if width < 0:
87 | width = width * -1
88 | height = y_max - y_min
89 | # x and y from center of rect
90 | x = x_min + width / 2
91 | y = y_min + height / 2
92 | return height, width, x, y
93 |
94 |
95 | class CreateMLReader:
96 | def __init__(self, json_path, file_path):
97 | self.json_path = json_path
98 | self.shapes = []
99 | self.verified = False
100 | self.filename = os.path.basename(file_path)
101 | try:
102 | self.parse_json()
103 | except ValueError:
104 | print("JSON decoding failed")
105 |
106 | def parse_json(self):
107 | with open(self.json_path, "r") as file:
108 | input_data = file.read()
109 |
110 | output_dict = json.loads(input_data)
111 | self.verified = True
112 |
113 | if len(self.shapes) > 0:
114 | self.shapes = []
115 | for image in output_dict:
116 | if image["image"] == self.filename:
117 | for shape in image["annotations"]:
118 | self.add_shape(shape["label"], shape["coordinates"])
119 |
120 | def add_shape(self, label, bnd_box):
121 | x_min = bnd_box["x"] - (bnd_box["width"] / 2)
122 | y_min = bnd_box["y"] - (bnd_box["height"] / 2)
123 |
124 | x_max = bnd_box["x"] + (bnd_box["width"] / 2)
125 | y_max = bnd_box["y"] + (bnd_box["height"] / 2)
126 |
127 | points = [(x_min, y_min), (x_max, y_min), (x_max, y_max), (x_min, y_max)]
128 | self.shapes.append((label, points, None, None, True))
129 |
130 | def get_shapes(self):
131 | return self.shapes
132 |
--------------------------------------------------------------------------------
/libs/hashableQListWidgetItem.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | import sys
4 | try:
5 | from PyQt5.QtGui import *
6 | from PyQt5.QtCore import *
7 | from PyQt5.QtWidgets import *
8 | except ImportError:
9 | # needed for py3+qt4
10 | # Ref:
11 | # http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html
12 | # http://stackoverflow.com/questions/21217399/pyqt4-qtcore-qvariant-object-instead-of-a-string
13 | if sys.version_info.major >= 3:
14 | import sip
15 | sip.setapi('QVariant', 2)
16 | from PyQt4.QtGui import *
17 | from PyQt4.QtCore import *
18 |
19 | # PyQt5: TypeError: unhashable type: 'QListWidgetItem'
20 |
21 |
22 | class HashableQListWidgetItem(QListWidgetItem):
23 |
24 | def __init__(self, *args):
25 | super(HashableQListWidgetItem, self).__init__(*args)
26 |
27 | def __hash__(self):
28 | return hash(id(self))
29 |
--------------------------------------------------------------------------------
/libs/labelDialog.py:
--------------------------------------------------------------------------------
1 | try:
2 | from PyQt5.QtGui import *
3 | from PyQt5.QtCore import *
4 | from PyQt5.QtWidgets import *
5 | except ImportError:
6 | from PyQt4.QtGui import *
7 | from PyQt4.QtCore import *
8 |
9 | from libs.utils import new_icon, label_validator
10 |
11 | BB = QDialogButtonBox
12 |
13 |
14 | class LabelDialog(QDialog):
15 |
16 | def __init__(self, text="Enter object label", parent=None, list_item=None):
17 | super(LabelDialog, self).__init__(parent)
18 |
19 | self.edit = QLineEdit()
20 | self.edit.setText(text)
21 | self.edit.setValidator(label_validator())
22 | self.edit.editingFinished.connect(self.post_process)
23 |
24 | model = QStringListModel()
25 | model.setStringList(list_item)
26 | completer = QCompleter()
27 | completer.setModel(model)
28 | self.edit.setCompleter(completer)
29 |
30 | layout = QVBoxLayout()
31 | layout.addWidget(self.edit)
32 | self.button_box = bb = BB(BB.Ok | BB.Cancel, Qt.Horizontal, self)
33 | bb.button(BB.Ok).setIcon(new_icon('done'))
34 | bb.button(BB.Cancel).setIcon(new_icon('undo'))
35 | bb.accepted.connect(self.validate)
36 | bb.rejected.connect(self.reject)
37 | layout.addWidget(bb)
38 |
39 | if list_item is not None and len(list_item) > 0:
40 | self.list_widget = QListWidget(self)
41 | for item in list_item:
42 | self.list_widget.addItem(item)
43 | self.list_widget.itemClicked.connect(self.list_item_click)
44 | self.list_widget.itemDoubleClicked.connect(self.list_item_double_click)
45 | layout.addWidget(self.list_widget)
46 |
47 | self.setLayout(layout)
48 |
49 | def validate(self):
50 | try:
51 | if self.edit.text().trimmed():
52 | self.accept()
53 | except AttributeError:
54 | # PyQt5: AttributeError: 'str' object has no attribute 'trimmed'
55 | if self.edit.text().strip():
56 | self.accept()
57 |
58 | def post_process(self):
59 | try:
60 | self.edit.setText(self.edit.text().trimmed())
61 | except AttributeError:
62 | # PyQt5: AttributeError: 'str' object has no attribute 'trimmed'
63 | self.edit.setText(self.edit.text())
64 |
65 | def pop_up(self, text='', move=True):
66 | self.edit.setText(text)
67 | self.edit.setSelection(0, len(text))
68 | self.edit.setFocus(Qt.PopupFocusReason)
69 | if move:
70 | cursor_pos = QCursor.pos()
71 | parent_bottom_right = self.parentWidget().geometry()
72 | max_x = parent_bottom_right.x() + parent_bottom_right.width() - self.sizeHint().width()
73 | max_y = parent_bottom_right.y() + parent_bottom_right.height() - self.sizeHint().height()
74 | max_global = self.parentWidget().mapToGlobal(QPoint(max_x, max_y))
75 | if cursor_pos.x() > max_global.x():
76 | cursor_pos.setX(max_global.x())
77 | if cursor_pos.y() > max_global.y():
78 | cursor_pos.setY(max_global.y())
79 | self.move(cursor_pos)
80 | return self.edit.text() if self.exec_() else None
81 |
82 | def list_item_click(self, t_qlist_widget_item):
83 | try:
84 | text = t_qlist_widget_item.text().trimmed()
85 | except AttributeError:
86 | # PyQt5: AttributeError: 'str' object has no attribute 'trimmed'
87 | text = t_qlist_widget_item.text().strip()
88 | self.edit.setText(text)
89 |
90 | def list_item_double_click(self, t_qlist_widget_item):
91 | self.list_item_click(t_qlist_widget_item)
92 | self.validate()
93 |
--------------------------------------------------------------------------------
/libs/settings.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 | import sys
4 |
5 |
6 | class Settings(object):
7 | def __init__(self):
8 | # Be default, the home will be in the same folder as labelImg
9 | home = os.path.expanduser("~")
10 | self.data = {}
11 | self.path = os.path.join(home, '.labelImgSettings.pkl')
12 |
13 | def __setitem__(self, key, value):
14 | self.data[key] = value
15 |
16 | def __getitem__(self, key):
17 | return self.data[key]
18 |
19 | def get(self, key, default=None):
20 | if key in self.data:
21 | return self.data[key]
22 | return default
23 |
24 | def save(self):
25 | if self.path:
26 | with open(self.path, 'wb') as f:
27 | pickle.dump(self.data, f, pickle.HIGHEST_PROTOCOL)
28 | return True
29 | return False
30 |
31 | def load(self):
32 | try:
33 | if os.path.exists(self.path):
34 | with open(self.path, 'rb') as f:
35 | self.data = pickle.load(f)
36 | return True
37 | except:
38 | print('Loading setting failed')
39 | return False
40 |
41 | def reset(self):
42 | if os.path.exists(self.path):
43 | os.remove(self.path)
44 | print('Remove setting pkl file ${0}'.format(self.path))
45 | self.data = {}
46 | self.path = None
47 |
--------------------------------------------------------------------------------
/libs/stringBundle.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | if items were added in files in the resources/strings folder,
5 | then execute "pyrcc5 resources.qrc -o resources.py" in the root directory
6 | and execute "pyrcc5 ../resources.qrc -o resources.py" in the libs directory
7 | """
8 | import re
9 | import os
10 | import sys
11 | import locale
12 | from libs.ustr import ustr
13 |
14 | try:
15 | from PyQt5.QtCore import *
16 | except ImportError:
17 | if sys.version_info.major >= 3:
18 | import sip
19 | sip.setapi('QVariant', 2)
20 | from PyQt4.QtCore import *
21 |
22 |
23 | class StringBundle:
24 |
25 | __create_key = object()
26 |
27 | def __init__(self, create_key, locale_str):
28 | assert(create_key == StringBundle.__create_key), "StringBundle must be created using StringBundle.getBundle"
29 | self.id_to_message = {}
30 | paths = self.__create_lookup_fallback_list(locale_str)
31 | for path in paths:
32 | self.__load_bundle(path)
33 |
34 | @classmethod
35 | def get_bundle(cls, locale_str=None):
36 | if locale_str is None:
37 | try:
38 | locale_str = locale.getlocale()[0] if locale.getlocale() and len(
39 | locale.getlocale()) > 0 else os.getenv('LANG')
40 | except:
41 | print('Invalid locale')
42 | locale_str = 'en'
43 |
44 | return StringBundle(cls.__create_key, locale_str)
45 |
46 | def get_string(self, string_id):
47 | assert(string_id in self.id_to_message), "Missing string id : " + string_id
48 | return self.id_to_message[string_id]
49 |
50 | def __create_lookup_fallback_list(self, locale_str):
51 | result_paths = []
52 | base_path = ":/strings"
53 | # base_path = ":/strings-zh-CN"
54 | result_paths.append(base_path)
55 | if locale_str is not None:
56 | # Don't follow standard BCP47. Simple fallback
57 | tags = re.split('[^a-zA-Z]', locale_str)
58 | for tag in tags:
59 | last_path = result_paths[-1]
60 | result_paths.append(last_path + '-' + tag)
61 |
62 | return result_paths
63 |
64 | def __load_bundle(self, path):
65 | PROP_SEPERATOR = '='
66 | f = QFile(path)
67 | if f.exists():
68 | if f.open(QIODevice.ReadOnly | QFile.Text):
69 | text = QTextStream(f)
70 | text.setCodec("UTF-8")
71 |
72 | while not text.atEnd():
73 | line = ustr(text.readLine())
74 | key_value = line.split(PROP_SEPERATOR)
75 | key = key_value[0].strip()
76 | value = PROP_SEPERATOR.join(key_value[1:]).strip().strip('"')
77 | self.id_to_message[key] = value
78 |
79 | f.close()
80 |
--------------------------------------------------------------------------------
/libs/toolBar.py:
--------------------------------------------------------------------------------
1 | try:
2 | from PyQt5.QtGui import *
3 | from PyQt5.QtCore import *
4 | from PyQt5.QtWidgets import *
5 | except ImportError:
6 | from PyQt4.QtGui import *
7 | from PyQt4.QtCore import *
8 |
9 |
10 | class ToolBar(QToolBar):
11 |
12 | def __init__(self, title):
13 | super(ToolBar, self).__init__(title)
14 | layout = self.layout()
15 | m = (0, 0, 0, 0)
16 | layout.setSpacing(0)
17 | layout.setContentsMargins(*m)
18 | self.setContentsMargins(*m)
19 | self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
20 |
21 | def addAction(self, action):
22 | if isinstance(action, QWidgetAction):
23 | return super(ToolBar, self).addAction(action)
24 | btn = ToolButton()
25 | btn.setDefaultAction(action)
26 | btn.setToolButtonStyle(self.toolButtonStyle())
27 | self.addWidget(btn)
28 |
29 |
30 | class ToolButton(QToolButton):
31 | """ToolBar companion class which ensures all buttons have the same size."""
32 | minSize = (60, 60)
33 |
34 | def minimumSizeHint(self):
35 | ms = super(ToolButton, self).minimumSizeHint()
36 | w1, h1 = ms.width(), ms.height()
37 | w2, h2 = self.minSize
38 | ToolButton.minSize = max(w1, w2), max(h1, h2)
39 | return QSize(*ToolButton.minSize)
40 |
--------------------------------------------------------------------------------
/libs/ustr.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from libs.constants import DEFAULT_ENCODING
3 |
4 | def ustr(x):
5 | """py2/py3 unicode helper"""
6 |
7 | if sys.version_info < (3, 0, 0):
8 | from PyQt4.QtCore import QString
9 | if type(x) == str:
10 | return x.decode(DEFAULT_ENCODING)
11 | if type(x) == QString:
12 | # https://blog.csdn.net/friendan/article/details/51088476
13 | # https://blog.csdn.net/xxm524/article/details/74937308
14 | return unicode(x.toUtf8(), DEFAULT_ENCODING, 'ignore')
15 | return x
16 | else:
17 | return x
18 |
--------------------------------------------------------------------------------
/libs/utils.py:
--------------------------------------------------------------------------------
1 | from math import sqrt
2 | from libs.ustr import ustr
3 | import hashlib
4 | import re
5 | import sys
6 |
7 | try:
8 | from PyQt5.QtGui import *
9 | from PyQt5.QtCore import *
10 | from PyQt5.QtWidgets import *
11 | except ImportError:
12 | from PyQt4.QtGui import *
13 | from PyQt4.QtCore import *
14 |
15 |
16 | def new_icon(icon):
17 | return QIcon(':/' + icon)
18 |
19 |
20 | def new_button(text, icon=None, slot=None):
21 | b = QPushButton(text)
22 | if icon is not None:
23 | b.setIcon(new_icon(icon))
24 | if slot is not None:
25 | b.clicked.connect(slot)
26 | return b
27 |
28 |
29 | def new_action(parent, text, slot=None, shortcut=None, icon=None,
30 | tip=None, checkable=False, enabled=True):
31 | """Create a new action and assign callbacks, shortcuts, etc."""
32 | a = QAction(text, parent)
33 | if icon is not None:
34 | a.setIcon(new_icon(icon))
35 | if shortcut is not None:
36 | if isinstance(shortcut, (list, tuple)):
37 | a.setShortcuts(shortcut)
38 | else:
39 | a.setShortcut(shortcut)
40 | if tip is not None:
41 | a.setToolTip(tip)
42 | a.setStatusTip(tip)
43 | if slot is not None:
44 | a.triggered.connect(slot)
45 | if checkable:
46 | a.setCheckable(True)
47 | a.setEnabled(enabled)
48 | return a
49 |
50 |
51 | def add_actions(widget, actions):
52 | for action in actions:
53 | if action is None:
54 | widget.addSeparator()
55 | elif isinstance(action, QMenu):
56 | widget.addMenu(action)
57 | else:
58 | widget.addAction(action)
59 |
60 |
61 | def label_validator():
62 | return QRegExpValidator(QRegExp(r'^[^ \t].+'), None)
63 |
64 |
65 | class Struct(object):
66 |
67 | def __init__(self, **kwargs):
68 | self.__dict__.update(kwargs)
69 |
70 |
71 | def distance(p):
72 | return sqrt(p.x() * p.x() + p.y() * p.y())
73 |
74 |
75 | def format_shortcut(text):
76 | mod, key = text.split('+', 1)
77 | return '%s+%s' % (mod, key)
78 |
79 |
80 | def generate_color_by_text(text):
81 | s = ustr(text)
82 | hash_code = int(hashlib.sha256(s.encode('utf-8')).hexdigest(), 16)
83 | r = int((hash_code / 255) % 255)
84 | g = int((hash_code / 65025) % 255)
85 | b = int((hash_code / 16581375) % 255)
86 | return QColor(r, g, b, 100)
87 |
88 | def have_qstring():
89 | """p3/qt5 get rid of QString wrapper as py3 has native unicode str type"""
90 | return not (sys.version_info.major >= 3 or QT_VERSION_STR.startswith('5.'))
91 |
92 | def util_qt_strlistclass():
93 | return QStringList if have_qstring() else list
94 |
95 | def natural_sort(list, key=lambda s:s):
96 | """
97 | Sort the list into natural alphanumeric order.
98 | """
99 | def get_alphanum_key_func(key):
100 | convert = lambda text: int(text) if text.isdigit() else text
101 | return lambda s: [convert(c) for c in re.split('([0-9]+)', key(s))]
102 | sort_key = get_alphanum_key_func(key)
103 | list.sort(key=sort_key)
104 |
--------------------------------------------------------------------------------
/libs/zoomWidget.py:
--------------------------------------------------------------------------------
1 | try:
2 | from PyQt5.QtGui import *
3 | from PyQt5.QtCore import *
4 | from PyQt5.QtWidgets import *
5 | except ImportError:
6 | from PyQt4.QtGui import *
7 | from PyQt4.QtCore import *
8 |
9 |
10 | class ZoomWidget(QSpinBox):
11 |
12 | def __init__(self, value=100):
13 | super(ZoomWidget, self).__init__()
14 | self.setButtonSymbols(QAbstractSpinBox.NoButtons)
15 | self.setRange(1, 500)
16 | self.setSuffix(' %')
17 | self.setValue(value)
18 | self.setToolTip(u'Zoom Level')
19 | self.setStatusTip(self.toolTip())
20 | self.setAlignment(Qt.AlignCenter)
21 |
22 | def minimumSizeHint(self):
23 | height = super(ZoomWidget, self).minimumSizeHint().height()
24 | fm = QFontMetrics(self.font())
25 | width = fm.width(str(self.maximum()))
26 | return QSize(width, height)
27 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # Usage: pip install -r requirements.txt
2 |
3 | requests
4 | opencv-python
5 | psutil
6 | tqdm
7 | matplotlib
8 | pyyaml
9 | pandas
10 |
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | resources/icons/help.png
5 | resources/icons/app.png
6 | resources/icons/expert2.png
7 | resources/icons/done.png
8 | resources/icons/file.png
9 | resources/icons/labels.png
10 | resources/icons/objects.png
11 | resources/icons/close.png
12 | resources/icons/fit-width.png
13 | resources/icons/fit-window.png
14 | resources/icons/undo.png
15 | resources/icons/eye.png
16 | resources/icons/quit.png
17 | resources/icons/copy.png
18 | resources/icons/edit.png
19 | resources/icons/open.png
20 | resources/icons/save.png
21 | resources/icons/format_voc.png
22 | resources/icons/format_yolo.png
23 | resources/icons/format_createml.png
24 | resources/icons/save-as.png
25 | resources/icons/color.png
26 | resources/icons/color_line.png
27 | resources/icons/zoom.png
28 | resources/icons/zoom-in.png
29 | resources/icons/zoom-out.png
30 | resources/icons/cancel.png
31 | resources/icons/next.png
32 | resources/icons/prev.png
33 | resources/icons/resetall.png
34 | resources/icons/verify.png
35 | resources/strings/strings.properties
36 | resources/strings/strings-zh-TW.properties
37 | resources/strings/strings-zh-CN.properties
38 | resources/strings/strings-ja-JP.properties
39 |
40 |
41 |
--------------------------------------------------------------------------------
/resources/icons/app.icns:
--------------------------------------------------------------------------------
1 | icns
--------------------------------------------------------------------------------
/resources/icons/app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/app.png
--------------------------------------------------------------------------------
/resources/icons/app.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
31 |
--------------------------------------------------------------------------------
/resources/icons/autolabel-all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/autolabel-all.png
--------------------------------------------------------------------------------
/resources/icons/autolabel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/autolabel.png
--------------------------------------------------------------------------------
/resources/icons/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/cancel.png
--------------------------------------------------------------------------------
/resources/icons/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/close.png
--------------------------------------------------------------------------------
/resources/icons/color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/color.png
--------------------------------------------------------------------------------
/resources/icons/color_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/color_line.png
--------------------------------------------------------------------------------
/resources/icons/copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/copy.png
--------------------------------------------------------------------------------
/resources/icons/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/delete.png
--------------------------------------------------------------------------------
/resources/icons/done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/done.png
--------------------------------------------------------------------------------
/resources/icons/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/edit.png
--------------------------------------------------------------------------------
/resources/icons/expert1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/expert1.png
--------------------------------------------------------------------------------
/resources/icons/expert2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/expert2.png
--------------------------------------------------------------------------------
/resources/icons/eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/eye.png
--------------------------------------------------------------------------------
/resources/icons/feBlend-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/feBlend-icon.png
--------------------------------------------------------------------------------
/resources/icons/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/file.png
--------------------------------------------------------------------------------
/resources/icons/fit-width.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/fit-width.png
--------------------------------------------------------------------------------
/resources/icons/fit-window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/fit-window.png
--------------------------------------------------------------------------------
/resources/icons/fit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/fit.png
--------------------------------------------------------------------------------
/resources/icons/format_createml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/format_createml.png
--------------------------------------------------------------------------------
/resources/icons/format_voc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/format_voc.png
--------------------------------------------------------------------------------
/resources/icons/format_yolo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/format_yolo.png
--------------------------------------------------------------------------------
/resources/icons/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/help.png
--------------------------------------------------------------------------------
/resources/icons/labels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/labels.png
--------------------------------------------------------------------------------
/resources/icons/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/new.png
--------------------------------------------------------------------------------
/resources/icons/next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/next.png
--------------------------------------------------------------------------------
/resources/icons/objects.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/objects.png
--------------------------------------------------------------------------------
/resources/icons/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/open.png
--------------------------------------------------------------------------------
/resources/icons/prev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/prev.png
--------------------------------------------------------------------------------
/resources/icons/quit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/quit.png
--------------------------------------------------------------------------------
/resources/icons/resetall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/resetall.png
--------------------------------------------------------------------------------
/resources/icons/save-as.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/save-as.png
--------------------------------------------------------------------------------
/resources/icons/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/save.png
--------------------------------------------------------------------------------
/resources/icons/undo-cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/undo-cross.png
--------------------------------------------------------------------------------
/resources/icons/undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/undo.png
--------------------------------------------------------------------------------
/resources/icons/verify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/verify.png
--------------------------------------------------------------------------------
/resources/icons/zoom-in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/zoom-in.png
--------------------------------------------------------------------------------
/resources/icons/zoom-out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/zoom-out.png
--------------------------------------------------------------------------------
/resources/icons/zoom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/resources/icons/zoom.png
--------------------------------------------------------------------------------
/resources/strings/strings-ja-JP.properties:
--------------------------------------------------------------------------------
1 | openFile=ファイルを開く
2 | openFileDetail=画像かラベルファイルを開きます。
3 | quit=アプリを終了
4 | quitApp=このアプリを終了します。
5 | openDir=ディレクトリを開く
6 | openAnnotation=アノテーションを開く
7 | openAnnotationDetail=アノテーションファイルを開きます。
8 | changeSaveDir=保存先を変更する
9 | resetAll=すべてリセットする
10 | hideAll=すべての図形を非表示にする
11 | viewAll=すべての図形を表示する
12 | crtBox=矩形を作成する
13 | crtBoxDetail=矩形を描画します。
14 | dupBox=矩形を複製する
15 | delBox=矩形を削除する
16 | editBox=矩形を編集する(&E)
17 | hideAllBox=矩形を非表示にする(&H)
18 | showAllBox=矩形を表示する(&S)
19 | tutorialDefault=チュートリアル動画を見る
20 | tutorialChrome=Chromeでチュートリアル動画を見る
21 | tutorialDetail=LabelImgのデモ動画を見ます。
22 | info=LabelImgについて
23 | verifyImg=画像を検証する
24 | verifyImgDetail=画像を検証します。
25 | save=保存する
26 | saveDetail=現在の編集を保存します。
27 | saveAs=名前を付けて保存
28 | saveAsDetail=ファイルに名前を付けて現在の編集を保存します。
29 | closeCur=このファイルを閉じる
30 | deleteImg=この画像を削除する
31 | resetAll=すべて初期化する。
32 | resetAllDetail=データをすべて初期状態に戻します。
33 | boxLineColor=線の色の編集
34 | boxLineColorDetail=色の編集を行います。
35 | chooseLineColor=線の色の編集
36 | chooseFillColor=塗りつぶす色の編集
37 | shortcuts=ショートカット一覧を見る(英語)
38 | editLabel=ラベルを編集する
39 | editLabelDetail=選択した矩形のラベル名を変更します。
40 | changeSaveFormat=保存するデータのフォーマットを変更します。
41 | nextImg=次の画像
42 | nextImgDetail=次の画像を開きます。
43 | prevImg=前の画像
44 | prevImgDetail=前の画像を開きます。
45 | zoomin=拡大
46 | zoomout=縮小
47 | useDefaultLabel=指定されたラベル名を使う
48 | advancedMode=上級者向け機能
49 | advancedModeDetail=上級者向け機能を使います。
50 | boxLabelText=矩形ラベル一覧
51 | labels=ラベル一覧
52 | autoSaveMode=自動で保存する
53 | singleClsMode=単一のラベルだけをアノテーションする
54 | displayLabel=ラベルを表示する
55 | menu_file=ファイル(&F)
56 | menu_edit=編集(&E)
57 | menu_view=表示(&V)
58 | menu_help=ヘルプ(&H)
59 | menu_openRecent=最近開いたファイル(&R)
60 | drawSquares=四角形を書く
61 | fitWin=ウィンドウに合わせる
62 | fitWinDetail=ウィンドウサイズに合わせて拡大します。
63 | fitWidth=ウィンドウの幅に合わせる
64 | fitWidthDetail=ウインドウの幅に合わせて拡大します。
65 | originalsize=原寸に戻す
66 | displayLabel=ラベルを表示する
67 | fileList=ファイル一覧
68 | files=ファイル
69 | boxLabelText=矩形ラベル
70 |
--------------------------------------------------------------------------------
/resources/strings/strings-zh-CN.properties:
--------------------------------------------------------------------------------
1 | saveAsDetail=將标签保存到其他文件
2 | changeSaveDir=改变存放目录
3 | openFile=打开文件
4 | shapeLineColorDetail=更改线条颜色
5 | resetAll=全部重置
6 | crtBox=创建区块
7 | crtBoxDetail=创建一个新的区块
8 | dupBoxDetail=复制区块
9 | verifyImg=验证图像
10 | zoominDetail=放大
11 | verifyImgDetail=验证图像
12 | saveDetail=保存标签文件
13 | openFileDetail=打开图像文件
14 | fitWidthDetail=调整宽度适应到窗口宽度
15 | tutorialDefault=YouTube教学
16 | tutorialChrome=YouTube教学(Chrome)
17 | info=版本信息
18 | shortcut=快捷键
19 | editLabel=编辑标签
20 | openAnnotationDetail=打开标签文件
21 | quit=退出
22 | shapeFillColorDetail=更改填充颜色
23 | closeCurDetail=关闭当前文件
24 | closeCur=关闭文件
25 | deleteImg=删除图像
26 | deleteImgDetail=删除当前图像
27 | fitWin=调整到窗口大小
28 | delBox=删除选择的区块
29 | boxLineColorDetail=选择线框颜色
30 | originalsize=原始大小
31 | resetAllDetail=重置所有设定
32 | zoomoutDetail=放大画面
33 | save=保存
34 | saveAs=另存为
35 | fitWinDetail=缩放到当前窗口大小
36 | openDir=打开目录
37 | copyPrevBounding=复制当前图像中的上一个边界框
38 | showHide=显示/隐藏标签
39 | changeSaveFormat=更改存储格式
40 | shapeFillColor=填充颜色
41 | quitApp=退出程序
42 | dupBox=复制区块
43 | delBoxDetail=删除区块
44 | zoomin=放大画面
45 | info=信息
46 | openAnnotation=开启标签
47 | prevImgDetail=上一个图像
48 | fitWidth=缩放到跟当前画面一样宽
49 | zoomout=缩小画面
50 | changeSavedAnnotationDir=更改保存标签文件的预设目录
51 | nextImgDetail=下一个图像
52 | originalsizeDetail=放大到原始大小
53 | prevImg=上一个图像
54 | tutorialDetail=显示示范内容
55 | shapeLineColor=形状线条颜色
56 | boxLineColor=区块线条颜色
57 | editLabelDetail=修改当前所选的区块颜色
58 | nextImg=下一个图片
59 | useDefaultLabel=使用预设标签
60 | useDifficult=有难度的
61 | boxLabelText=区块的标签
62 | labels=标签
63 | autoSaveMode=自动保存模式
64 | singleClsMode=单一类别模式
65 | displayLabel=显示类别
66 | fileList=文件列表
67 | files=文件
68 | advancedMode=专家模式
69 | advancedModeDetail=切换到专家模式
70 | showAllBoxDetail=显示所有区块
71 | hideAllBoxDetail=隐藏所有区块
72 | menu_file=文件(&F)
73 | menu_edit=编辑(&E)
74 | menu_view=查看(&V)
75 | menu_additional=附加(&A)
76 | menu_help=帮助(&H)
77 | menu_openRecent=最近打开(&R)
78 | autoLabel=自动标注
79 | autoLabelDetail=自动标注
80 | autoLabelAll=全部自动标注
81 | autoLabelAllDetail=全部自动标注
82 |
--------------------------------------------------------------------------------
/resources/strings/strings-zh-TW.properties:
--------------------------------------------------------------------------------
1 | saveAsDetail=將標籤保存到其他文件
2 | changeSaveDir=改變存放目錄
3 | openFile=開啟檔案
4 | shapeLineColorDetail=更改線條顏色
5 | resetAll=重置
6 | crtBox=創建區塊
7 | crtBoxDetail=畫一個區塊
8 | dupBoxDetail=複製區塊
9 | verifyImg=驗證圖像
10 | zoominDetail=放大
11 | verifyImgDetail=驗證圖像
12 | saveDetail=將標籤存到
13 | openFileDetail=打開圖像
14 | fitWidthDetail=調整到窗口寬度
15 | tutorialDefault=YouTube教學
16 | tutorialChrome=YouTube教學(Chrome)
17 | info=版本信息
18 | shortcut=快捷鍵
19 | editLabel=編輯標籤
20 | openAnnotationDetail=打開標籤文件
21 | quit=結束
22 | shapeFillColorDetail=更改填充顏色
23 | closeCurDetail=關閉目前檔案
24 | closeCur=關閉
25 | deleteImg=刪除圖像
26 | deleteImgDetail=刪除目前圖像
27 | fitWin=調整到跟窗口一樣大小
28 | delBox=刪除選取區塊
29 | boxLineColorDetail=選擇框線顏色
30 | originalsize=原始大小
31 | resetAllDetail=重設所有設定
32 | zoomoutDetail=畫面放大
33 | save=儲存
34 | saveAs=另存為
35 | fitWinDetail=縮放到窗口一樣
36 | openDir=開啟目錄
37 | copyPrevBounding=複製當前圖像中的上一個邊界框
38 | showHide=顯示/隱藏標籤
39 | changeSaveFormat=更改儲存格式
40 | shapeFillColor=填充顏色
41 | quitApp=離開本程式
42 | dupBox=複製區塊
43 | delBoxDetail=刪除區塊
44 | zoomin=放大畫面
45 | info=資訊
46 | openAnnotation=開啟標籤
47 | prevImgDetail=上一個圖像
48 | fitWidth=縮放到跟畫面一樣寬
49 | zoomout=縮小畫面
50 | changeSavedAnnotationDir=更改預設標籤存的目錄
51 | nextImgDetail=下一個圖像
52 | originalsizeDetail=放大到原始大小
53 | prevImg=上一個圖像
54 | tutorialDetail=顯示示範內容
55 | shapeLineColor=形狀線條顏色
56 | boxLineColor=日期分隔線顏色
57 | editLabelDetail=修改所選區塊的標籤
58 | nextImg=下一張圖片
59 | useDefaultLabel=使用預設標籤
60 | useDifficult=有難度的
61 | boxLabelText=區塊的標籤
62 | labels=標籤
63 | autoSaveMode=自動儲存模式
64 | singleClsMode=單一類別模式
65 | displayLabel=顯示類別
66 | fileList=檔案清單
67 | files=檔案
68 | advancedMode=進階模式
69 | advancedModeDetail=切到進階模式
70 | showAllBoxDetail=顯示所有區塊
71 | hideAllBoxDetail=隱藏所有區塊
72 | menu_file=檔案(&F)
73 | menu_edit=編輯(&E)
74 | menu_view=檢視(&V)
75 | menu_help=說明(&H)
76 | menu_openRecent=最近開啟(&R)
77 |
--------------------------------------------------------------------------------
/resources/strings/strings.properties:
--------------------------------------------------------------------------------
1 | openFile=Open
2 | openFileDetail=Open image or label file
3 | quit=Quit
4 | quitApp=Quit application
5 | openDir=Open Dir
6 | copyPrevBounding=Copy previous Bounding Boxes in the current image
7 | changeSavedAnnotationDir=Change default saved Annotation dir
8 | openAnnotation=Open Annotation
9 | openAnnotationDetail=Open an annotation file
10 | changeSaveDir=Change Save Dir
11 | nextImg=Next Image
12 | nextImgDetail=Open the next Image
13 | prevImg=Prev Image
14 | prevImgDetail=Open the previous Image
15 | verifyImg=Verify Image
16 | verifyImgDetail=Verify Image
17 | save=Save
18 | saveDetail=Save the labels to a file
19 | changeSaveFormat=Change save format
20 | saveAs=Save As
21 | saveAsDetail=Save the labels to a different file
22 | closeCur=Close
23 | closeCurDetail=Close the current file
24 | deleteImg=Delete current image
25 | deleteImgDetail=Delete the current image
26 | resetAll=Reset All
27 | resetAllDetail=Reset All
28 | boxLineColor=Box Line Color
29 | boxLineColorDetail=Choose Box line color
30 | crtBox=Create RectBox
31 | crtBoxDetail=Draw a new box
32 | delBox=Delete RectBox
33 | delBoxDetail=Remove the box
34 | dupBox=Duplicate RectBox
35 | dupBoxDetail=Create a duplicate of the selected box
36 | editBox=&Edit RectBox
37 | editBoxDetail=Move and edit Boxs
38 | hideAllBox=&Hide RectBox
39 | showAllBox=&Show RectBox
40 | tutorialDefault=Tutorial
41 | tutorialChrome=Tutorial(Chrome)
42 | tutorialDetail=Show demo
43 | info=Information
44 | shortcut=Keyboard shortcuts
45 | zoomin=Zoom In
46 | zoominDetail=Increase zoom level
47 | zoomout=Zoom Out
48 | zoomoutDetail=Decrease zoom level
49 | originalsize=Original size
50 | originalsizeDetail=Zoom to original size
51 | fitWin=Fit Window
52 | fitWinDetail=Zoom follows window size
53 | fitWidth=Fit Width
54 | fitWidthDetail=Zoom follows window width
55 | editLabel=Edit Label
56 | editLabelDetail=Modify the label of the selected Box
57 | shapeLineColor=Shape Line Color
58 | shapeLineColorDetail=Change the line color for this specific shape
59 | shapeFillColor=Shape Fill Color
60 | shapeFillColorDetail=Change the fill color for this specific shape
61 | showHide=Show/Hide Label Panel
62 | useDefaultLabel=Use default label
63 | useDifficult=difficult
64 | boxLabelText=Box Labels
65 | labels=Labels
66 | autoSaveMode=Auto Save mode
67 | singleClsMode=Single Class Mode
68 | displayLabel=Display Labels
69 | fileList=File List
70 | files=Files
71 | advancedMode=Advanced Mode
72 | advancedModeDetail=Swtich to advanced mode
73 | showAllBoxDetail=Show all bounding boxes
74 | hideAllBoxDetail=Hide all bounding boxes
75 | menu_file=&File
76 | menu_edit=&Edit
77 | menu_view=&View
78 | menu_additional=&additional
79 | menu_help=&Help
80 | menu_openRecent=Open &Recent
81 | menu_repeatFilter=Label &Filter
82 | chooseLineColor=Choose Line Color
83 | chooseFillColor=Choose Fill Color
84 | drawSquares=Draw Squares
85 | autoLabel=Auto Label
86 | autoLabelDetail=Auto Label
87 | autoLabelAll=Auto Label ALL
88 | autoLabelAllDetail=Auto Label All
89 | prev=Prev
90 | next=Next
91 | filterate=filterate
--------------------------------------------------------------------------------
/tools/change_labels.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | def replace(line):
5 | if line.startswith('5') or line.startswith('7'):
6 | line = '2' + line[1:]
7 | return line
8 |
9 |
10 | def rework_classes(labelpath, default=True):
11 | if default:
12 |
13 | if type(labelpath) == list:
14 | for path in labelpath:
15 | if os.path.exists(path):
16 | data = ''
17 | with open(path, "r") as fr:
18 | lines = fr.readlines()
19 | for line in lines:
20 | line = replace(line)
21 | data = data + line
22 | with open(path, 'w') as fw:
23 | fw.write(data)
24 | return
25 |
26 | if os.path.isdir(labelpath):
27 | labels = os.listdir(labelpath)
28 | labels.remove('classes.txt') if 'classes.txt' in labels else None
29 | for name in labels:
30 | path = os.path.join(labelpath, name)
31 | if os.path.exists(path):
32 | data = ''
33 | with open(path, "r") as fr:
34 | lines = fr.readlines()
35 | for line in lines:
36 | line = replace(line)
37 | data = data + line
38 | with open(path, 'w') as fw:
39 | fw.write(data)
40 |
41 | elif os.path.isfile(labelpath):
42 | data = ''
43 | with open(labelpath, "r") as fr:
44 | lines = fr.readlines()
45 | for line in lines:
46 | line = replace(line)
47 | data = data + line
48 | with open(labelpath, 'w') as fw:
49 | fw.write(data)
50 |
51 |
52 |
--------------------------------------------------------------------------------
/tools/repeat_filter.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | import cv2
4 | from tqdm import tqdm
5 |
6 |
7 | def main(imgfol_path, labfol_path, conf, check_ls):
8 | labfol_ls = os.listdir(labfol_path)
9 | labfol_ls.remove("classes.txt")
10 | labfol_ls = tqdm(labfol_ls)
11 | check_file_ls = list()
12 | for file in labfol_ls:
13 | lab_path = os.path.join(labfol_path, file)
14 | prefix = os.path.splitext(file)[0]
15 | img_path = os.path.join(imgfol_path, f'{prefix}.jpg')
16 |
17 | with open(lab_path, 'r') as txt:
18 | lab = txt.readlines()
19 | lab_ls = list()
20 | for i in lab:
21 | sub_list = i.split()
22 | if check_ls:
23 | if sub_list[0] in check_ls:
24 | lab_ls.append(sub_list)
25 | else:
26 | lab_ls.append(sub_list)
27 |
28 | bool = calculate_iou_for_grouped_labels(lab_ls, img_path, conf)
29 | if bool:
30 | check_file_ls.append(img_path)
31 |
32 | labfol_ls.close()
33 | return check_file_ls
34 |
35 |
36 | def xywh2xyxy(box, img_path):
37 | x, y, w, h = box
38 | img = cv2.imread(img_path)
39 | height, wide = img.shape[:2]
40 | xmin = int(wide * (float(x) - (float(w) / 2)))
41 | ymin = int(height * (float(y) - (float(h) / 2)))
42 | xmax = int(wide * (float(x) + (float(w) / 2)))
43 | ymax = int(height * (float(y) + (float(h) / 2)))
44 |
45 | return [xmin, ymin, xmax, ymax]
46 |
47 |
48 | def compute_iou(box1, box2, wh=False):
49 | """
50 | compute the iou of two boxes.
51 | Args:
52 | box1, box2: [xmin, ymin, xmax, ymax] (wh=False) or [xcenter, ycenter, w, h] (wh=True)
53 | wh: the format of coordinate.
54 | Return:
55 | iou: iou of box1 and box2.
56 | """
57 | if wh:
58 | xmin1, ymin1, xmax1, ymax1 = box1
59 | xmin2, ymin2, xmax2, ymax2 = box2
60 | else:
61 | xmin1, ymin1 = int(box1[0] - box1[2] / 2.0), int(box1[1] - box1[3] / 2.0)
62 | xmax1, ymax1 = int(box1[0] + box1[2] / 2.0), int(box1[1] + box1[3] / 2.0)
63 | xmin2, ymin2 = int(box2[0] - box2[2] / 2.0), int(box2[1] - box2[3] / 2.0)
64 | xmax2, ymax2 = int(box2[0] + box2[2] / 2.0), int(box2[1] + box2[3] / 2.0)
65 |
66 | # 获取矩形框交集对应的左上角和右下角的坐标(intersection)
67 | xx1 = np.max([xmin1, xmin2])
68 | yy1 = np.max([ymin1, ymin2])
69 | xx2 = np.min([xmax1, xmax2])
70 | yy2 = np.min([ymax1, ymax2])
71 |
72 | # 计算两个矩形框面积
73 | area1 = (xmax1 - xmin1) * (ymax1 - ymin1)
74 | area2 = (xmax2 - xmin2) * (ymax2 - ymin2)
75 |
76 | inter_area = (np.max([0, xx2 - xx1])) * (np.max([0, yy2 - yy1])) # 计算交集面积
77 | iou = inter_area / (area1 + area2 - inter_area + 1e-6) # 计算交并比
78 |
79 | return iou
80 |
81 |
82 | def calculate_iou_for_grouped_labels(labels, img_path, conf):
83 | # iou_values = []
84 | for i in range(len(labels)):
85 | for j in range(i+1, len(labels)):
86 | if labels[i][0] == labels[j][0]:
87 | box_i, box_j = xywh2xyxy(labels[i][1:], img_path), xywh2xyxy(labels[j][1:], img_path)
88 | iou = compute_iou(box_i, box_j)
89 | # iou_values.append(iou)
90 | if iou >= conf:
91 | return True
92 |
93 |
94 | if __name__ == '__main__':
95 | imgfol_path = r"F:\data\labelimages\23.8.2\output_folder_20\images"
96 | labfol_path = r"F:\data\labelimages\23.8.2\output_folder_20\lables"
97 | conf = 0.9
98 | check_ls = ['2']
99 | file_ls = main(imgfol_path, labfol_path, conf, check_ls)
100 | print(file_ls)
101 |
--------------------------------------------------------------------------------
/ultralytics/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | __version__ = '8.0.148'
4 |
5 | from ultralytics.hub import start
6 | from ultralytics.models import RTDETR, SAM, YOLO
7 | from ultralytics.models.fastsam import FastSAM
8 | from ultralytics.models.nas import NAS
9 | from ultralytics.utils import SETTINGS as settings
10 | from ultralytics.utils.checks import check_yolo as checks
11 | from ultralytics.utils.downloads import download
12 |
13 | __all__ = '__version__', 'YOLO', 'NAS', 'SAM', 'FastSAM', 'RTDETR', 'checks', 'download', 'start', 'settings' # allow simpler import
14 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/Argoverse.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # Argoverse-HD dataset (ring-front-center camera) http://www.cs.cmu.edu/~mengtial/proj/streaming/ by Argo AI
3 | # Example usage: yolo train data=Argoverse.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── Argoverse ← downloads here (31.3 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/Argoverse # dataset root dir
12 | train: Argoverse-1.1/images/train/ # train images (relative to 'path') 39384 images
13 | val: Argoverse-1.1/images/val/ # val images (relative to 'path') 15062 images
14 | test: Argoverse-1.1/images/test/ # test images (optional) https://eval.ai/web/challenges/challenge-page/800/overview
15 |
16 | # Classes
17 | names:
18 | 0: person
19 | 1: bicycle
20 | 2: car
21 | 3: motorcycle
22 | 4: bus
23 | 5: truck
24 | 6: traffic_light
25 | 7: stop_sign
26 |
27 |
28 | # Download script/URL (optional) ---------------------------------------------------------------------------------------
29 | download: |
30 | import json
31 | from tqdm import tqdm
32 | from ultralytics.utils.downloads import download
33 | from pathlib import Path
34 |
35 | def argoverse2yolo(set):
36 | labels = {}
37 | a = json.load(open(set, "rb"))
38 | for annot in tqdm(a['annotations'], desc=f"Converting {set} to YOLOv5 format..."):
39 | img_id = annot['image_id']
40 | img_name = a['images'][img_id]['name']
41 | img_label_name = f'{img_name[:-3]}txt'
42 |
43 | cls = annot['category_id'] # instance class id
44 | x_center, y_center, width, height = annot['bbox']
45 | x_center = (x_center + width / 2) / 1920.0 # offset and scale
46 | y_center = (y_center + height / 2) / 1200.0 # offset and scale
47 | width /= 1920.0 # scale
48 | height /= 1200.0 # scale
49 |
50 | img_dir = set.parents[2] / 'Argoverse-1.1' / 'labels' / a['seq_dirs'][a['images'][annot['image_id']]['sid']]
51 | if not img_dir.exists():
52 | img_dir.mkdir(parents=True, exist_ok=True)
53 |
54 | k = str(img_dir / img_label_name)
55 | if k not in labels:
56 | labels[k] = []
57 | labels[k].append(f"{cls} {x_center} {y_center} {width} {height}\n")
58 |
59 | for k in labels:
60 | with open(k, "w") as f:
61 | f.writelines(labels[k])
62 |
63 |
64 | # Download
65 | dir = Path(yaml['path']) # dataset root dir
66 | urls = ['https://argoverse-hd.s3.us-east-2.amazonaws.com/Argoverse-HD-Full.zip']
67 | download(urls, dir=dir)
68 |
69 | # Convert
70 | annotations_dir = 'Argoverse-HD/annotations/'
71 | (dir / 'Argoverse-1.1' / 'tracking').rename(dir / 'Argoverse-1.1' / 'images') # rename 'tracking' to 'images'
72 | for d in "train.json", "val.json":
73 | argoverse2yolo(dir / annotations_dir / d) # convert VisDrone annotations to YOLO labels
74 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/GlobalWheat2020.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # Global Wheat 2020 dataset http://www.global-wheat.com/ by University of Saskatchewan
3 | # Example usage: yolo train data=GlobalWheat2020.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── GlobalWheat2020 ← downloads here (7.0 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/GlobalWheat2020 # dataset root dir
12 | train: # train images (relative to 'path') 3422 images
13 | - images/arvalis_1
14 | - images/arvalis_2
15 | - images/arvalis_3
16 | - images/ethz_1
17 | - images/rres_1
18 | - images/inrae_1
19 | - images/usask_1
20 | val: # val images (relative to 'path') 748 images (WARNING: train set contains ethz_1)
21 | - images/ethz_1
22 | test: # test images (optional) 1276 images
23 | - images/utokyo_1
24 | - images/utokyo_2
25 | - images/nau_1
26 | - images/uq_1
27 |
28 | # Classes
29 | names:
30 | 0: wheat_head
31 |
32 |
33 | # Download script/URL (optional) ---------------------------------------------------------------------------------------
34 | download: |
35 | from ultralytics.utils.downloads import download
36 | from pathlib import Path
37 |
38 | # Download
39 | dir = Path(yaml['path']) # dataset root dir
40 | urls = ['https://zenodo.org/record/4298502/files/global-wheat-codalab-official.zip',
41 | 'https://github.com/ultralytics/yolov5/releases/download/v1.0/GlobalWheat2020_labels.zip']
42 | download(urls, dir=dir)
43 |
44 | # Make Directories
45 | for p in 'annotations', 'images', 'labels':
46 | (dir / p).mkdir(parents=True, exist_ok=True)
47 |
48 | # Move
49 | for p in 'arvalis_1', 'arvalis_2', 'arvalis_3', 'ethz_1', 'rres_1', 'inrae_1', 'usask_1', \
50 | 'utokyo_1', 'utokyo_2', 'nau_1', 'uq_1':
51 | (dir / 'global-wheat-codalab-official' / p).rename(dir / 'images' / p) # move to /images
52 | f = (dir / 'global-wheat-codalab-official' / p).with_suffix('.json') # json file
53 | if f.exists():
54 | f.rename((dir / 'annotations' / p).with_suffix('.json')) # move to /annotations
55 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/SKU-110K.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # SKU-110K retail items dataset https://github.com/eg4000/SKU110K_CVPR19 by Trax Retail
3 | # Example usage: yolo train data=SKU-110K.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── SKU-110K ← downloads here (13.6 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/SKU-110K # dataset root dir
12 | train: train.txt # train images (relative to 'path') 8219 images
13 | val: val.txt # val images (relative to 'path') 588 images
14 | test: test.txt # test images (optional) 2936 images
15 |
16 | # Classes
17 | names:
18 | 0: object
19 |
20 |
21 | # Download script/URL (optional) ---------------------------------------------------------------------------------------
22 | download: |
23 | import shutil
24 | from pathlib import Path
25 |
26 | import numpy as np
27 | import pandas as pd
28 | from tqdm import tqdm
29 |
30 | from ultralytics.utils.downloads import download
31 | from ultralytics.utils.ops import xyxy2xywh
32 |
33 | # Download
34 | dir = Path(yaml['path']) # dataset root dir
35 | parent = Path(dir.parent) # download dir
36 | urls = ['http://trax-geometry.s3.amazonaws.com/cvpr_challenge/SKU110K_fixed.tar.gz']
37 | download(urls, dir=parent)
38 |
39 | # Rename directories
40 | if dir.exists():
41 | shutil.rmtree(dir)
42 | (parent / 'SKU110K_fixed').rename(dir) # rename dir
43 | (dir / 'labels').mkdir(parents=True, exist_ok=True) # create labels dir
44 |
45 | # Convert labels
46 | names = 'image', 'x1', 'y1', 'x2', 'y2', 'class', 'image_width', 'image_height' # column names
47 | for d in 'annotations_train.csv', 'annotations_val.csv', 'annotations_test.csv':
48 | x = pd.read_csv(dir / 'annotations' / d, names=names).values # annotations
49 | images, unique_images = x[:, 0], np.unique(x[:, 0])
50 | with open((dir / d).with_suffix('.txt').__str__().replace('annotations_', ''), 'w') as f:
51 | f.writelines(f'./images/{s}\n' for s in unique_images)
52 | for im in tqdm(unique_images, desc=f'Converting {dir / d}'):
53 | cls = 0 # single-class dataset
54 | with open((dir / 'labels' / im).with_suffix('.txt'), 'a') as f:
55 | for r in x[images == im]:
56 | w, h = r[6], r[7] # image width, height
57 | xywh = xyxy2xywh(np.array([[r[1] / w, r[2] / h, r[3] / w, r[4] / h]]))[0] # instance
58 | f.write(f"{cls} {xywh[0]:.5f} {xywh[1]:.5f} {xywh[2]:.5f} {xywh[3]:.5f}\n") # write label
59 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/VOC.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # PASCAL VOC dataset http://host.robots.ox.ac.uk/pascal/VOC by University of Oxford
3 | # Example usage: yolo train data=VOC.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── VOC ← downloads here (2.8 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/VOC
12 | train: # train images (relative to 'path') 16551 images
13 | - images/train2012
14 | - images/train2007
15 | - images/val2012
16 | - images/val2007
17 | val: # val images (relative to 'path') 4952 images
18 | - images/test2007
19 | test: # test images (optional)
20 | - images/test2007
21 |
22 | # Classes
23 | names:
24 | 0: aeroplane
25 | 1: bicycle
26 | 2: bird
27 | 3: boat
28 | 4: bottle
29 | 5: bus
30 | 6: car
31 | 7: cat
32 | 8: chair
33 | 9: cow
34 | 10: diningtable
35 | 11: dog
36 | 12: horse
37 | 13: motorbike
38 | 14: person
39 | 15: pottedplant
40 | 16: sheep
41 | 17: sofa
42 | 18: train
43 | 19: tvmonitor
44 |
45 |
46 | # Download script/URL (optional) ---------------------------------------------------------------------------------------
47 | download: |
48 | import xml.etree.ElementTree as ET
49 |
50 | from tqdm import tqdm
51 | from ultralytics.utils.downloads import download
52 | from pathlib import Path
53 |
54 | def convert_label(path, lb_path, year, image_id):
55 | def convert_box(size, box):
56 | dw, dh = 1. / size[0], 1. / size[1]
57 | x, y, w, h = (box[0] + box[1]) / 2.0 - 1, (box[2] + box[3]) / 2.0 - 1, box[1] - box[0], box[3] - box[2]
58 | return x * dw, y * dh, w * dw, h * dh
59 |
60 | in_file = open(path / f'VOC{year}/Annotations/{image_id}.xml')
61 | out_file = open(lb_path, 'w')
62 | tree = ET.parse(in_file)
63 | root = tree.getroot()
64 | size = root.find('size')
65 | w = int(size.find('width').text)
66 | h = int(size.find('height').text)
67 |
68 | names = list(yaml['names'].values()) # names list
69 | for obj in root.iter('object'):
70 | cls = obj.find('name').text
71 | if cls in names and int(obj.find('difficult').text) != 1:
72 | xmlbox = obj.find('bndbox')
73 | bb = convert_box((w, h), [float(xmlbox.find(x).text) for x in ('xmin', 'xmax', 'ymin', 'ymax')])
74 | cls_id = names.index(cls) # class id
75 | out_file.write(" ".join([str(a) for a in (cls_id, *bb)]) + '\n')
76 |
77 |
78 | # Download
79 | dir = Path(yaml['path']) # dataset root dir
80 | url = 'https://github.com/ultralytics/yolov5/releases/download/v1.0/'
81 | urls = [f'{url}VOCtrainval_06-Nov-2007.zip', # 446MB, 5012 images
82 | f'{url}VOCtest_06-Nov-2007.zip', # 438MB, 4953 images
83 | f'{url}VOCtrainval_11-May-2012.zip'] # 1.95GB, 17126 images
84 | download(urls, dir=dir / 'images', curl=True, threads=3)
85 |
86 | # Convert
87 | path = dir / 'images/VOCdevkit'
88 | for year, image_set in ('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test'):
89 | imgs_path = dir / 'images' / f'{image_set}{year}'
90 | lbs_path = dir / 'labels' / f'{image_set}{year}'
91 | imgs_path.mkdir(exist_ok=True, parents=True)
92 | lbs_path.mkdir(exist_ok=True, parents=True)
93 |
94 | with open(path / f'VOC{year}/ImageSets/Main/{image_set}.txt') as f:
95 | image_ids = f.read().strip().split()
96 | for id in tqdm(image_ids, desc=f'{image_set}{year}'):
97 | f = path / f'VOC{year}/JPEGImages/{id}.jpg' # old img path
98 | lb_path = (lbs_path / f.name).with_suffix('.txt') # new label path
99 | f.rename(imgs_path / f.name) # move image
100 | convert_label(path, lb_path, year, id) # convert labels to YOLO format
101 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/VisDrone.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # VisDrone2019-DET dataset https://github.com/VisDrone/VisDrone-Dataset by Tianjin University
3 | # Example usage: yolo train data=VisDrone.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── VisDrone ← downloads here (2.3 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/VisDrone # dataset root dir
12 | train: VisDrone2019-DET-train/images # train images (relative to 'path') 6471 images
13 | val: VisDrone2019-DET-val/images # val images (relative to 'path') 548 images
14 | test: VisDrone2019-DET-test-dev/images # test images (optional) 1610 images
15 |
16 | # Classes
17 | names:
18 | 0: pedestrian
19 | 1: people
20 | 2: bicycle
21 | 3: car
22 | 4: van
23 | 5: truck
24 | 6: tricycle
25 | 7: awning-tricycle
26 | 8: bus
27 | 9: motor
28 |
29 |
30 | # Download script/URL (optional) ---------------------------------------------------------------------------------------
31 | download: |
32 | import os
33 | from pathlib import Path
34 |
35 | from ultralytics.utils.downloads import download
36 |
37 | def visdrone2yolo(dir):
38 | from PIL import Image
39 | from tqdm import tqdm
40 |
41 | def convert_box(size, box):
42 | # Convert VisDrone box to YOLO xywh box
43 | dw = 1. / size[0]
44 | dh = 1. / size[1]
45 | return (box[0] + box[2] / 2) * dw, (box[1] + box[3] / 2) * dh, box[2] * dw, box[3] * dh
46 |
47 | (dir / 'labels').mkdir(parents=True, exist_ok=True) # make labels directory
48 | pbar = tqdm((dir / 'annotations').glob('*.txt'), desc=f'Converting {dir}')
49 | for f in pbar:
50 | img_size = Image.open((dir / 'images' / f.name).with_suffix('.jpg')).size
51 | lines = []
52 | with open(f, 'r') as file: # read annotation.txt
53 | for row in [x.split(',') for x in file.read().strip().splitlines()]:
54 | if row[4] == '0': # VisDrone 'ignored regions' class 0
55 | continue
56 | cls = int(row[5]) - 1
57 | box = convert_box(img_size, tuple(map(int, row[:4])))
58 | lines.append(f"{cls} {' '.join(f'{x:.6f}' for x in box)}\n")
59 | with open(str(f).replace(f'{os.sep}annotations{os.sep}', f'{os.sep}labels{os.sep}'), 'w') as fl:
60 | fl.writelines(lines) # write label.txt
61 |
62 |
63 | # Download
64 | dir = Path(yaml['path']) # dataset root dir
65 | urls = ['https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-train.zip',
66 | 'https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-val.zip',
67 | 'https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-test-dev.zip',
68 | 'https://github.com/ultralytics/yolov5/releases/download/v1.0/VisDrone2019-DET-test-challenge.zip']
69 | download(urls, dir=dir, curl=True, threads=4)
70 |
71 | # Convert
72 | for d in 'VisDrone2019-DET-train', 'VisDrone2019-DET-val', 'VisDrone2019-DET-test-dev':
73 | visdrone2yolo(dir / d) # convert VisDrone annotations to YOLO labels
74 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco-pose.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO 2017 dataset http://cocodataset.org by Microsoft
3 | # Example usage: yolo train data=coco-pose.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco-pose ← downloads here (20.1 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco-pose # dataset root dir
12 | train: train2017.txt # train images (relative to 'path') 118287 images
13 | val: val2017.txt # val images (relative to 'path') 5000 images
14 | test: test-dev2017.txt # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794
15 |
16 | # Keypoints
17 | kpt_shape: [17, 3] # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
18 | flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]
19 |
20 | # Classes
21 | names:
22 | 0: person
23 |
24 | # Download script/URL (optional)
25 | download: |
26 | from ultralytics.utils.downloads import download
27 | from pathlib import Path
28 |
29 | # Download labels
30 | dir = Path(yaml['path']) # dataset root dir
31 | url = 'https://github.com/ultralytics/yolov5/releases/download/v1.0/'
32 | urls = [url + 'coco2017labels-pose.zip'] # labels
33 | download(urls, dir=dir.parent)
34 | # Download data
35 | urls = ['http://images.cocodataset.org/zips/train2017.zip', # 19G, 118k images
36 | 'http://images.cocodataset.org/zips/val2017.zip', # 1G, 5k images
37 | 'http://images.cocodataset.org/zips/test2017.zip'] # 7G, 41k images (optional)
38 | download(urls, dir=dir / 'images', threads=3)
39 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO 2017 dataset http://cocodataset.org by Microsoft
3 | # Example usage: yolo train data=coco.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco ← downloads here (20.1 GB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco # dataset root dir
12 | train: train2017.txt # train images (relative to 'path') 118287 images
13 | val: val2017.txt # val images (relative to 'path') 5000 images
14 | test: test-dev2017.txt # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794
15 |
16 | # Classes
17 | names:
18 | 0: person
19 | 1: bicycle
20 | 2: car
21 | 3: motorcycle
22 | 4: airplane
23 | 5: bus
24 | 6: train
25 | 7: truck
26 | 8: boat
27 | 9: traffic light
28 | 10: fire hydrant
29 | 11: stop sign
30 | 12: parking meter
31 | 13: bench
32 | 14: bird
33 | 15: cat
34 | 16: dog
35 | 17: horse
36 | 18: sheep
37 | 19: cow
38 | 20: elephant
39 | 21: bear
40 | 22: zebra
41 | 23: giraffe
42 | 24: backpack
43 | 25: umbrella
44 | 26: handbag
45 | 27: tie
46 | 28: suitcase
47 | 29: frisbee
48 | 30: skis
49 | 31: snowboard
50 | 32: sports ball
51 | 33: kite
52 | 34: baseball bat
53 | 35: baseball glove
54 | 36: skateboard
55 | 37: surfboard
56 | 38: tennis racket
57 | 39: bottle
58 | 40: wine glass
59 | 41: cup
60 | 42: fork
61 | 43: knife
62 | 44: spoon
63 | 45: bowl
64 | 46: banana
65 | 47: apple
66 | 48: sandwich
67 | 49: orange
68 | 50: broccoli
69 | 51: carrot
70 | 52: hot dog
71 | 53: pizza
72 | 54: donut
73 | 55: cake
74 | 56: chair
75 | 57: couch
76 | 58: potted plant
77 | 59: bed
78 | 60: dining table
79 | 61: toilet
80 | 62: tv
81 | 63: laptop
82 | 64: mouse
83 | 65: remote
84 | 66: keyboard
85 | 67: cell phone
86 | 68: microwave
87 | 69: oven
88 | 70: toaster
89 | 71: sink
90 | 72: refrigerator
91 | 73: book
92 | 74: clock
93 | 75: vase
94 | 76: scissors
95 | 77: teddy bear
96 | 78: hair drier
97 | 79: toothbrush
98 |
99 |
100 | # Download script/URL (optional)
101 | download: |
102 | from ultralytics.utils.downloads import download
103 | from pathlib import Path
104 |
105 | # Download labels
106 | segments = True # segment or box labels
107 | dir = Path(yaml['path']) # dataset root dir
108 | url = 'https://github.com/ultralytics/yolov5/releases/download/v1.0/'
109 | urls = [url + ('coco2017labels-segments.zip' if segments else 'coco2017labels.zip')] # labels
110 | download(urls, dir=dir.parent)
111 | # Download data
112 | urls = ['http://images.cocodataset.org/zips/train2017.zip', # 19G, 118k images
113 | 'http://images.cocodataset.org/zips/val2017.zip', # 1G, 5k images
114 | 'http://images.cocodataset.org/zips/test2017.zip'] # 7G, 41k images (optional)
115 | download(urls, dir=dir / 'images', threads=3)
116 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco128-seg.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO128-seg dataset https://www.kaggle.com/ultralytics/coco128 (first 128 images from COCO train2017) by Ultralytics
3 | # Example usage: yolo train data=coco128.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco128-seg ← downloads here (7 MB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco128-seg # dataset root dir
12 | train: images/train2017 # train images (relative to 'path') 128 images
13 | val: images/train2017 # val images (relative to 'path') 128 images
14 | test: # test images (optional)
15 |
16 | # Classes
17 | names:
18 | 0: person
19 | 1: bicycle
20 | 2: car
21 | 3: motorcycle
22 | 4: airplane
23 | 5: bus
24 | 6: train
25 | 7: truck
26 | 8: boat
27 | 9: traffic light
28 | 10: fire hydrant
29 | 11: stop sign
30 | 12: parking meter
31 | 13: bench
32 | 14: bird
33 | 15: cat
34 | 16: dog
35 | 17: horse
36 | 18: sheep
37 | 19: cow
38 | 20: elephant
39 | 21: bear
40 | 22: zebra
41 | 23: giraffe
42 | 24: backpack
43 | 25: umbrella
44 | 26: handbag
45 | 27: tie
46 | 28: suitcase
47 | 29: frisbee
48 | 30: skis
49 | 31: snowboard
50 | 32: sports ball
51 | 33: kite
52 | 34: baseball bat
53 | 35: baseball glove
54 | 36: skateboard
55 | 37: surfboard
56 | 38: tennis racket
57 | 39: bottle
58 | 40: wine glass
59 | 41: cup
60 | 42: fork
61 | 43: knife
62 | 44: spoon
63 | 45: bowl
64 | 46: banana
65 | 47: apple
66 | 48: sandwich
67 | 49: orange
68 | 50: broccoli
69 | 51: carrot
70 | 52: hot dog
71 | 53: pizza
72 | 54: donut
73 | 55: cake
74 | 56: chair
75 | 57: couch
76 | 58: potted plant
77 | 59: bed
78 | 60: dining table
79 | 61: toilet
80 | 62: tv
81 | 63: laptop
82 | 64: mouse
83 | 65: remote
84 | 66: keyboard
85 | 67: cell phone
86 | 68: microwave
87 | 69: oven
88 | 70: toaster
89 | 71: sink
90 | 72: refrigerator
91 | 73: book
92 | 74: clock
93 | 75: vase
94 | 76: scissors
95 | 77: teddy bear
96 | 78: hair drier
97 | 79: toothbrush
98 |
99 |
100 | # Download script/URL (optional)
101 | download: https://ultralytics.com/assets/coco128-seg.zip
102 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco128.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO128 dataset https://www.kaggle.com/ultralytics/coco128 (first 128 images from COCO train2017) by Ultralytics
3 | # Example usage: yolo train data=coco128.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco128 ← downloads here (7 MB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco128 # dataset root dir
12 | train: images/train2017 # train images (relative to 'path') 128 images
13 | val: images/train2017 # val images (relative to 'path') 128 images
14 | test: # test images (optional)
15 |
16 | # Classes
17 | names:
18 | 0: person
19 | 1: bicycle
20 | 2: car
21 | 3: motorcycle
22 | 4: airplane
23 | 5: bus
24 | 6: train
25 | 7: truck
26 | 8: boat
27 | 9: traffic light
28 | 10: fire hydrant
29 | 11: stop sign
30 | 12: parking meter
31 | 13: bench
32 | 14: bird
33 | 15: cat
34 | 16: dog
35 | 17: horse
36 | 18: sheep
37 | 19: cow
38 | 20: elephant
39 | 21: bear
40 | 22: zebra
41 | 23: giraffe
42 | 24: backpack
43 | 25: umbrella
44 | 26: handbag
45 | 27: tie
46 | 28: suitcase
47 | 29: frisbee
48 | 30: skis
49 | 31: snowboard
50 | 32: sports ball
51 | 33: kite
52 | 34: baseball bat
53 | 35: baseball glove
54 | 36: skateboard
55 | 37: surfboard
56 | 38: tennis racket
57 | 39: bottle
58 | 40: wine glass
59 | 41: cup
60 | 42: fork
61 | 43: knife
62 | 44: spoon
63 | 45: bowl
64 | 46: banana
65 | 47: apple
66 | 48: sandwich
67 | 49: orange
68 | 50: broccoli
69 | 51: carrot
70 | 52: hot dog
71 | 53: pizza
72 | 54: donut
73 | 55: cake
74 | 56: chair
75 | 57: couch
76 | 58: potted plant
77 | 59: bed
78 | 60: dining table
79 | 61: toilet
80 | 62: tv
81 | 63: laptop
82 | 64: mouse
83 | 65: remote
84 | 66: keyboard
85 | 67: cell phone
86 | 68: microwave
87 | 69: oven
88 | 70: toaster
89 | 71: sink
90 | 72: refrigerator
91 | 73: book
92 | 74: clock
93 | 75: vase
94 | 76: scissors
95 | 77: teddy bear
96 | 78: hair drier
97 | 79: toothbrush
98 |
99 |
100 | # Download script/URL (optional)
101 | download: https://ultralytics.com/assets/coco128.zip
102 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco8-pose.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO8-pose dataset (first 8 images from COCO train2017) by Ultralytics
3 | # Example usage: yolo train data=coco8-pose.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco8-pose ← downloads here (1 MB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco8-pose # dataset root dir
12 | train: images/train # train images (relative to 'path') 4 images
13 | val: images/val # val images (relative to 'path') 4 images
14 | test: # test images (optional)
15 |
16 | # Keypoints
17 | kpt_shape: [17, 3] # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
18 | flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]
19 |
20 | # Classes
21 | names:
22 | 0: person
23 |
24 | # Download script/URL (optional)
25 | download: https://ultralytics.com/assets/coco8-pose.zip
26 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco8-seg.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO8-seg dataset (first 8 images from COCO train2017) by Ultralytics
3 | # Example usage: yolo train data=coco8-seg.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco8-seg ← downloads here (1 MB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco8-seg # dataset root dir
12 | train: images/train # train images (relative to 'path') 4 images
13 | val: images/val # val images (relative to 'path') 4 images
14 | test: # test images (optional)
15 |
16 | # Classes
17 | names:
18 | 0: person
19 | 1: bicycle
20 | 2: car
21 | 3: motorcycle
22 | 4: airplane
23 | 5: bus
24 | 6: train
25 | 7: truck
26 | 8: boat
27 | 9: traffic light
28 | 10: fire hydrant
29 | 11: stop sign
30 | 12: parking meter
31 | 13: bench
32 | 14: bird
33 | 15: cat
34 | 16: dog
35 | 17: horse
36 | 18: sheep
37 | 19: cow
38 | 20: elephant
39 | 21: bear
40 | 22: zebra
41 | 23: giraffe
42 | 24: backpack
43 | 25: umbrella
44 | 26: handbag
45 | 27: tie
46 | 28: suitcase
47 | 29: frisbee
48 | 30: skis
49 | 31: snowboard
50 | 32: sports ball
51 | 33: kite
52 | 34: baseball bat
53 | 35: baseball glove
54 | 36: skateboard
55 | 37: surfboard
56 | 38: tennis racket
57 | 39: bottle
58 | 40: wine glass
59 | 41: cup
60 | 42: fork
61 | 43: knife
62 | 44: spoon
63 | 45: bowl
64 | 46: banana
65 | 47: apple
66 | 48: sandwich
67 | 49: orange
68 | 50: broccoli
69 | 51: carrot
70 | 52: hot dog
71 | 53: pizza
72 | 54: donut
73 | 55: cake
74 | 56: chair
75 | 57: couch
76 | 58: potted plant
77 | 59: bed
78 | 60: dining table
79 | 61: toilet
80 | 62: tv
81 | 63: laptop
82 | 64: mouse
83 | 65: remote
84 | 66: keyboard
85 | 67: cell phone
86 | 68: microwave
87 | 69: oven
88 | 70: toaster
89 | 71: sink
90 | 72: refrigerator
91 | 73: book
92 | 74: clock
93 | 75: vase
94 | 76: scissors
95 | 77: teddy bear
96 | 78: hair drier
97 | 79: toothbrush
98 |
99 |
100 | # Download script/URL (optional)
101 | download: https://ultralytics.com/assets/coco8-seg.zip
102 |
--------------------------------------------------------------------------------
/ultralytics/cfg/datasets/coco8.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # COCO8 dataset (first 8 images from COCO train2017) by Ultralytics
3 | # Example usage: yolo train data=coco8.yaml
4 | # parent
5 | # ├── ultralytics
6 | # └── datasets
7 | # └── coco8 ← downloads here (1 MB)
8 |
9 |
10 | # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
11 | path: ../datasets/coco8 # dataset root dir
12 | train: images/train # train images (relative to 'path') 4 images
13 | val: images/val # val images (relative to 'path') 4 images
14 | test: # test images (optional)
15 |
16 | # Classes
17 | names:
18 | 0: person
19 | 1: bicycle
20 | 2: car
21 | 3: motorcycle
22 | 4: airplane
23 | 5: bus
24 | 6: train
25 | 7: truck
26 | 8: boat
27 | 9: traffic light
28 | 10: fire hydrant
29 | 11: stop sign
30 | 12: parking meter
31 | 13: bench
32 | 14: bird
33 | 15: cat
34 | 16: dog
35 | 17: horse
36 | 18: sheep
37 | 19: cow
38 | 20: elephant
39 | 21: bear
40 | 22: zebra
41 | 23: giraffe
42 | 24: backpack
43 | 25: umbrella
44 | 26: handbag
45 | 27: tie
46 | 28: suitcase
47 | 29: frisbee
48 | 30: skis
49 | 31: snowboard
50 | 32: sports ball
51 | 33: kite
52 | 34: baseball bat
53 | 35: baseball glove
54 | 36: skateboard
55 | 37: surfboard
56 | 38: tennis racket
57 | 39: bottle
58 | 40: wine glass
59 | 41: cup
60 | 42: fork
61 | 43: knife
62 | 44: spoon
63 | 45: bowl
64 | 46: banana
65 | 47: apple
66 | 48: sandwich
67 | 49: orange
68 | 50: broccoli
69 | 51: carrot
70 | 52: hot dog
71 | 53: pizza
72 | 54: donut
73 | 55: cake
74 | 56: chair
75 | 57: couch
76 | 58: potted plant
77 | 59: bed
78 | 60: dining table
79 | 61: toilet
80 | 62: tv
81 | 63: laptop
82 | 64: mouse
83 | 65: remote
84 | 66: keyboard
85 | 67: cell phone
86 | 68: microwave
87 | 69: oven
88 | 70: toaster
89 | 71: sink
90 | 72: refrigerator
91 | 73: book
92 | 74: clock
93 | 75: vase
94 | 76: scissors
95 | 77: teddy bear
96 | 78: hair drier
97 | 79: toothbrush
98 |
99 |
100 | # Download script/URL (optional)
101 | download: https://ultralytics.com/assets/coco8.zip
102 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/rt-detr/rtdetr-l.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # RT-DETR-l object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | l: [1.00, 1.00, 1024]
9 |
10 | backbone:
11 | # [from, repeats, module, args]
12 | - [-1, 1, HGStem, [32, 48]] # 0-P2/4
13 | - [-1, 6, HGBlock, [48, 128, 3]] # stage 1
14 |
15 | - [-1, 1, DWConv, [128, 3, 2, 1, False]] # 2-P3/8
16 | - [-1, 6, HGBlock, [96, 512, 3]] # stage 2
17 |
18 | - [-1, 1, DWConv, [512, 3, 2, 1, False]] # 4-P3/16
19 | - [-1, 6, HGBlock, [192, 1024, 5, True, False]] # cm, c2, k, light, shortcut
20 | - [-1, 6, HGBlock, [192, 1024, 5, True, True]]
21 | - [-1, 6, HGBlock, [192, 1024, 5, True, True]] # stage 3
22 |
23 | - [-1, 1, DWConv, [1024, 3, 2, 1, False]] # 8-P4/32
24 | - [-1, 6, HGBlock, [384, 2048, 5, True, False]] # stage 4
25 |
26 | head:
27 | - [-1, 1, Conv, [256, 1, 1, None, 1, 1, False]] # 10 input_proj.2
28 | - [-1, 1, AIFI, [1024, 8]]
29 | - [-1, 1, Conv, [256, 1, 1]] # 12, Y5, lateral_convs.0
30 |
31 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
32 | - [7, 1, Conv, [256, 1, 1, None, 1, 1, False]] # 14 input_proj.1
33 | - [[-2, -1], 1, Concat, [1]]
34 | - [-1, 3, RepC3, [256]] # 16, fpn_blocks.0
35 | - [-1, 1, Conv, [256, 1, 1]] # 17, Y4, lateral_convs.1
36 |
37 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
38 | - [3, 1, Conv, [256, 1, 1, None, 1, 1, False]] # 19 input_proj.0
39 | - [[-2, -1], 1, Concat, [1]] # cat backbone P4
40 | - [-1, 3, RepC3, [256]] # X3 (21), fpn_blocks.1
41 |
42 | - [-1, 1, Conv, [256, 3, 2]] # 22, downsample_convs.0
43 | - [[-1, 17], 1, Concat, [1]] # cat Y4
44 | - [-1, 3, RepC3, [256]] # F4 (24), pan_blocks.0
45 |
46 | - [-1, 1, Conv, [256, 3, 2]] # 25, downsample_convs.1
47 | - [[-1, 12], 1, Concat, [1]] # cat Y5
48 | - [-1, 3, RepC3, [256]] # F5 (27), pan_blocks.1
49 |
50 | - [[21, 24, 27], 1, RTDETRDecoder, [nc]] # Detect(P3, P4, P5)
51 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/rt-detr/rtdetr-x.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # RT-DETR-x object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | x: [1.00, 1.00, 2048]
9 |
10 | backbone:
11 | # [from, repeats, module, args]
12 | - [-1, 1, HGStem, [32, 64]] # 0-P2/4
13 | - [-1, 6, HGBlock, [64, 128, 3]] # stage 1
14 |
15 | - [-1, 1, DWConv, [128, 3, 2, 1, False]] # 2-P3/8
16 | - [-1, 6, HGBlock, [128, 512, 3]]
17 | - [-1, 6, HGBlock, [128, 512, 3, False, True]] # 4-stage 2
18 |
19 | - [-1, 1, DWConv, [512, 3, 2, 1, False]] # 5-P3/16
20 | - [-1, 6, HGBlock, [256, 1024, 5, True, False]] # cm, c2, k, light, shortcut
21 | - [-1, 6, HGBlock, [256, 1024, 5, True, True]]
22 | - [-1, 6, HGBlock, [256, 1024, 5, True, True]]
23 | - [-1, 6, HGBlock, [256, 1024, 5, True, True]]
24 | - [-1, 6, HGBlock, [256, 1024, 5, True, True]] # 10-stage 3
25 |
26 | - [-1, 1, DWConv, [1024, 3, 2, 1, False]] # 11-P4/32
27 | - [-1, 6, HGBlock, [512, 2048, 5, True, False]]
28 | - [-1, 6, HGBlock, [512, 2048, 5, True, True]] # 13-stage 4
29 |
30 | head:
31 | - [-1, 1, Conv, [384, 1, 1, None, 1, 1, False]] # 14 input_proj.2
32 | - [-1, 1, AIFI, [2048, 8]]
33 | - [-1, 1, Conv, [384, 1, 1]] # 16, Y5, lateral_convs.0
34 |
35 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
36 | - [10, 1, Conv, [384, 1, 1, None, 1, 1, False]] # 18 input_proj.1
37 | - [[-2, -1], 1, Concat, [1]]
38 | - [-1, 3, RepC3, [384]] # 20, fpn_blocks.0
39 | - [-1, 1, Conv, [384, 1, 1]] # 21, Y4, lateral_convs.1
40 |
41 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
42 | - [4, 1, Conv, [384, 1, 1, None, 1, 1, False]] # 23 input_proj.0
43 | - [[-2, -1], 1, Concat, [1]] # cat backbone P4
44 | - [-1, 3, RepC3, [384]] # X3 (25), fpn_blocks.1
45 |
46 | - [-1, 1, Conv, [384, 3, 2]] # 26, downsample_convs.0
47 | - [[-1, 21], 1, Concat, [1]] # cat Y4
48 | - [-1, 3, RepC3, [384]] # F4 (28), pan_blocks.0
49 |
50 | - [-1, 1, Conv, [384, 3, 2]] # 29, downsample_convs.1
51 | - [[-1, 16], 1, Concat, [1]] # cat Y5
52 | - [-1, 3, RepC3, [384]] # F5 (31), pan_blocks.1
53 |
54 | - [[25, 28, 31], 1, RTDETRDecoder, [nc]] # Detect(P3, P4, P5)
55 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v3/yolov3-spp.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv3-SPP object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/yolov3
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | depth_multiple: 1.0 # model depth multiple
7 | width_multiple: 1.0 # layer channel multiple
8 |
9 | # darknet53 backbone
10 | backbone:
11 | # [from, number, module, args]
12 | [[-1, 1, Conv, [32, 3, 1]], # 0
13 | [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
14 | [-1, 1, Bottleneck, [64]],
15 | [-1, 1, Conv, [128, 3, 2]], # 3-P2/4
16 | [-1, 2, Bottleneck, [128]],
17 | [-1, 1, Conv, [256, 3, 2]], # 5-P3/8
18 | [-1, 8, Bottleneck, [256]],
19 | [-1, 1, Conv, [512, 3, 2]], # 7-P4/16
20 | [-1, 8, Bottleneck, [512]],
21 | [-1, 1, Conv, [1024, 3, 2]], # 9-P5/32
22 | [-1, 4, Bottleneck, [1024]], # 10
23 | ]
24 |
25 | # YOLOv3-SPP head
26 | head:
27 | [[-1, 1, Bottleneck, [1024, False]],
28 | [-1, 1, SPP, [512, [5, 9, 13]]],
29 | [-1, 1, Conv, [1024, 3, 1]],
30 | [-1, 1, Conv, [512, 1, 1]],
31 | [-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large)
32 |
33 | [-2, 1, Conv, [256, 1, 1]],
34 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
35 | [[-1, 8], 1, Concat, [1]], # cat backbone P4
36 | [-1, 1, Bottleneck, [512, False]],
37 | [-1, 1, Bottleneck, [512, False]],
38 | [-1, 1, Conv, [256, 1, 1]],
39 | [-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium)
40 |
41 | [-2, 1, Conv, [128, 1, 1]],
42 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
43 | [[-1, 6], 1, Concat, [1]], # cat backbone P3
44 | [-1, 1, Bottleneck, [256, False]],
45 | [-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small)
46 |
47 | [[27, 22, 15], 1, Detect, [nc]], # Detect(P3, P4, P5)
48 | ]
49 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v3/yolov3-tiny.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv3-tiny object detection model with P4-P5 outputs. For details see https://docs.ultralytics.com/models/yolov3
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | depth_multiple: 1.0 # model depth multiple
7 | width_multiple: 1.0 # layer channel multiple
8 |
9 | # YOLOv3-tiny backbone
10 | backbone:
11 | # [from, number, module, args]
12 | [[-1, 1, Conv, [16, 3, 1]], # 0
13 | [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 1-P1/2
14 | [-1, 1, Conv, [32, 3, 1]],
15 | [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 3-P2/4
16 | [-1, 1, Conv, [64, 3, 1]],
17 | [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 5-P3/8
18 | [-1, 1, Conv, [128, 3, 1]],
19 | [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 7-P4/16
20 | [-1, 1, Conv, [256, 3, 1]],
21 | [-1, 1, nn.MaxPool2d, [2, 2, 0]], # 9-P5/32
22 | [-1, 1, Conv, [512, 3, 1]],
23 | [-1, 1, nn.ZeroPad2d, [[0, 1, 0, 1]]], # 11
24 | [-1, 1, nn.MaxPool2d, [2, 1, 0]], # 12
25 | ]
26 |
27 | # YOLOv3-tiny head
28 | head:
29 | [[-1, 1, Conv, [1024, 3, 1]],
30 | [-1, 1, Conv, [256, 1, 1]],
31 | [-1, 1, Conv, [512, 3, 1]], # 15 (P5/32-large)
32 |
33 | [-2, 1, Conv, [128, 1, 1]],
34 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
35 | [[-1, 8], 1, Concat, [1]], # cat backbone P4
36 | [-1, 1, Conv, [256, 3, 1]], # 19 (P4/16-medium)
37 |
38 | [[19, 15], 1, Detect, [nc]], # Detect(P4, P5)
39 | ]
40 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v3/yolov3.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv3 object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/yolov3
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | depth_multiple: 1.0 # model depth multiple
7 | width_multiple: 1.0 # layer channel multiple
8 |
9 | # darknet53 backbone
10 | backbone:
11 | # [from, number, module, args]
12 | [[-1, 1, Conv, [32, 3, 1]], # 0
13 | [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
14 | [-1, 1, Bottleneck, [64]],
15 | [-1, 1, Conv, [128, 3, 2]], # 3-P2/4
16 | [-1, 2, Bottleneck, [128]],
17 | [-1, 1, Conv, [256, 3, 2]], # 5-P3/8
18 | [-1, 8, Bottleneck, [256]],
19 | [-1, 1, Conv, [512, 3, 2]], # 7-P4/16
20 | [-1, 8, Bottleneck, [512]],
21 | [-1, 1, Conv, [1024, 3, 2]], # 9-P5/32
22 | [-1, 4, Bottleneck, [1024]], # 10
23 | ]
24 |
25 | # YOLOv3 head
26 | head:
27 | [[-1, 1, Bottleneck, [1024, False]],
28 | [-1, 1, Conv, [512, 1, 1]],
29 | [-1, 1, Conv, [1024, 3, 1]],
30 | [-1, 1, Conv, [512, 1, 1]],
31 | [-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large)
32 |
33 | [-2, 1, Conv, [256, 1, 1]],
34 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
35 | [[-1, 8], 1, Concat, [1]], # cat backbone P4
36 | [-1, 1, Bottleneck, [512, False]],
37 | [-1, 1, Bottleneck, [512, False]],
38 | [-1, 1, Conv, [256, 1, 1]],
39 | [-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium)
40 |
41 | [-2, 1, Conv, [128, 1, 1]],
42 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
43 | [[-1, 6], 1, Concat, [1]], # cat backbone P3
44 | [-1, 1, Bottleneck, [256, False]],
45 | [-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small)
46 |
47 | [[27, 22, 15], 1, Detect, [nc]], # Detect(P3, P4, P5)
48 | ]
49 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v5/yolov5-p6.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv5 object detection model with P3-P6 outputs. For details see https://docs.ultralytics.com/models/yolov5
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov5n-p6.yaml' will call yolov5-p6.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024]
9 | s: [0.33, 0.50, 1024]
10 | m: [0.67, 0.75, 1024]
11 | l: [1.00, 1.00, 1024]
12 | x: [1.33, 1.25, 1024]
13 |
14 | # YOLOv5 v6.0 backbone
15 | backbone:
16 | # [from, number, module, args]
17 | [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
18 | [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
19 | [-1, 3, C3, [128]],
20 | [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
21 | [-1, 6, C3, [256]],
22 | [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
23 | [-1, 9, C3, [512]],
24 | [-1, 1, Conv, [768, 3, 2]], # 7-P5/32
25 | [-1, 3, C3, [768]],
26 | [-1, 1, Conv, [1024, 3, 2]], # 9-P6/64
27 | [-1, 3, C3, [1024]],
28 | [-1, 1, SPPF, [1024, 5]], # 11
29 | ]
30 |
31 | # YOLOv5 v6.0 head
32 | head:
33 | [[-1, 1, Conv, [768, 1, 1]],
34 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
35 | [[-1, 8], 1, Concat, [1]], # cat backbone P5
36 | [-1, 3, C3, [768, False]], # 15
37 |
38 | [-1, 1, Conv, [512, 1, 1]],
39 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
40 | [[-1, 6], 1, Concat, [1]], # cat backbone P4
41 | [-1, 3, C3, [512, False]], # 19
42 |
43 | [-1, 1, Conv, [256, 1, 1]],
44 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
45 | [[-1, 4], 1, Concat, [1]], # cat backbone P3
46 | [-1, 3, C3, [256, False]], # 23 (P3/8-small)
47 |
48 | [-1, 1, Conv, [256, 3, 2]],
49 | [[-1, 20], 1, Concat, [1]], # cat head P4
50 | [-1, 3, C3, [512, False]], # 26 (P4/16-medium)
51 |
52 | [-1, 1, Conv, [512, 3, 2]],
53 | [[-1, 16], 1, Concat, [1]], # cat head P5
54 | [-1, 3, C3, [768, False]], # 29 (P5/32-large)
55 |
56 | [-1, 1, Conv, [768, 3, 2]],
57 | [[-1, 12], 1, Concat, [1]], # cat head P6
58 | [-1, 3, C3, [1024, False]], # 32 (P6/64-xlarge)
59 |
60 | [[23, 26, 29, 32], 1, Detect, [nc]], # Detect(P3, P4, P5, P6)
61 | ]
62 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v5/yolov5.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv5 object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/yolov5
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov5n.yaml' will call yolov5.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024]
9 | s: [0.33, 0.50, 1024]
10 | m: [0.67, 0.75, 1024]
11 | l: [1.00, 1.00, 1024]
12 | x: [1.33, 1.25, 1024]
13 |
14 | # YOLOv5 v6.0 backbone
15 | backbone:
16 | # [from, number, module, args]
17 | [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
18 | [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
19 | [-1, 3, C3, [128]],
20 | [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
21 | [-1, 6, C3, [256]],
22 | [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
23 | [-1, 9, C3, [512]],
24 | [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
25 | [-1, 3, C3, [1024]],
26 | [-1, 1, SPPF, [1024, 5]], # 9
27 | ]
28 |
29 | # YOLOv5 v6.0 head
30 | head:
31 | [[-1, 1, Conv, [512, 1, 1]],
32 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
33 | [[-1, 6], 1, Concat, [1]], # cat backbone P4
34 | [-1, 3, C3, [512, False]], # 13
35 |
36 | [-1, 1, Conv, [256, 1, 1]],
37 | [-1, 1, nn.Upsample, [None, 2, 'nearest']],
38 | [[-1, 4], 1, Concat, [1]], # cat backbone P3
39 | [-1, 3, C3, [256, False]], # 17 (P3/8-small)
40 |
41 | [-1, 1, Conv, [256, 3, 2]],
42 | [[-1, 14], 1, Concat, [1]], # cat head P4
43 | [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
44 |
45 | [-1, 1, Conv, [512, 3, 2]],
46 | [[-1, 10], 1, Concat, [1]], # cat head P5
47 | [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
48 |
49 | [[17, 20, 23], 1, Detect, [nc]], # Detect(P3, P4, P5)
50 | ]
51 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v6/yolov6.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv6 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/models/yolov6
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | activation: nn.ReLU() # (optional) model default activation function
7 | scales: # model compound scaling constants, i.e. 'model=yolov6n.yaml' will call yolov8.yaml with scale 'n'
8 | # [depth, width, max_channels]
9 | n: [0.33, 0.25, 1024]
10 | s: [0.33, 0.50, 1024]
11 | m: [0.67, 0.75, 768]
12 | l: [1.00, 1.00, 512]
13 | x: [1.00, 1.25, 512]
14 |
15 | # YOLOv6-3.0s backbone
16 | backbone:
17 | # [from, repeats, module, args]
18 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
19 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
20 | - [-1, 6, Conv, [128, 3, 1]]
21 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
22 | - [-1, 12, Conv, [256, 3, 1]]
23 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
24 | - [-1, 18, Conv, [512, 3, 1]]
25 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
26 | - [-1, 6, Conv, [1024, 3, 1]]
27 | - [-1, 1, SPPF, [1024, 5]] # 9
28 |
29 | # YOLOv6-3.0s head
30 | head:
31 | - [-1, 1, Conv, [256, 1, 1]]
32 | - [-1, 1, nn.ConvTranspose2d, [256, 2, 2, 0]]
33 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
34 | - [-1, 1, Conv, [256, 3, 1]]
35 | - [-1, 9, Conv, [256, 3, 1]] # 14
36 |
37 | - [-1, 1, Conv, [128, 1, 1]]
38 | - [-1, 1, nn.ConvTranspose2d, [128, 2, 2, 0]]
39 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
40 | - [-1, 1, Conv, [128, 3, 1]]
41 | - [-1, 9, Conv, [128, 3, 1]] # 19
42 |
43 | - [-1, 1, Conv, [128, 3, 2]]
44 | - [[-1, 15], 1, Concat, [1]] # cat head P4
45 | - [-1, 1, Conv, [256, 3, 1]]
46 | - [-1, 9, Conv, [256, 3, 1]] # 23
47 |
48 | - [-1, 1, Conv, [256, 3, 2]]
49 | - [[-1, 10], 1, Concat, [1]] # cat head P5
50 | - [-1, 1, Conv, [512, 3, 1]]
51 | - [-1, 9, Conv, [512, 3, 1]] # 27
52 |
53 | - [[19, 23, 27], 1, Detect, [nc]] # Detect(P3, P4, P5)
54 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-cls.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8-cls image classification model. For Usage examples see https://docs.ultralytics.com/tasks/classify
3 |
4 | # Parameters
5 | nc: 1000 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024]
9 | s: [0.33, 0.50, 1024]
10 | m: [0.67, 0.75, 1024]
11 | l: [1.00, 1.00, 1024]
12 | x: [1.00, 1.25, 1024]
13 |
14 | # YOLOv8.0n backbone
15 | backbone:
16 | # [from, repeats, module, args]
17 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
18 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
19 | - [-1, 3, C2f, [128, True]]
20 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21 | - [-1, 6, C2f, [256, True]]
22 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23 | - [-1, 6, C2f, [512, True]]
24 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
25 | - [-1, 3, C2f, [1024, True]]
26 |
27 | # YOLOv8.0n head
28 | head:
29 | - [-1, 1, Classify, [nc]] # Classify
30 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-p2.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8 object detection model with P2-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024]
9 | s: [0.33, 0.50, 1024]
10 | m: [0.67, 0.75, 768]
11 | l: [1.00, 1.00, 512]
12 | x: [1.00, 1.25, 512]
13 |
14 | # YOLOv8.0 backbone
15 | backbone:
16 | # [from, repeats, module, args]
17 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
18 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
19 | - [-1, 3, C2f, [128, True]]
20 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21 | - [-1, 6, C2f, [256, True]]
22 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23 | - [-1, 6, C2f, [512, True]]
24 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
25 | - [-1, 3, C2f, [1024, True]]
26 | - [-1, 1, SPPF, [1024, 5]] # 9
27 |
28 | # YOLOv8.0-p2 head
29 | head:
30 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
31 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
32 | - [-1, 3, C2f, [512]] # 12
33 |
34 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
35 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
36 | - [-1, 3, C2f, [256]] # 15 (P3/8-small)
37 |
38 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
39 | - [[-1, 2], 1, Concat, [1]] # cat backbone P2
40 | - [-1, 3, C2f, [128]] # 18 (P2/4-xsmall)
41 |
42 | - [-1, 1, Conv, [128, 3, 2]]
43 | - [[-1, 15], 1, Concat, [1]] # cat head P3
44 | - [-1, 3, C2f, [256]] # 21 (P3/8-small)
45 |
46 | - [-1, 1, Conv, [256, 3, 2]]
47 | - [[-1, 12], 1, Concat, [1]] # cat head P4
48 | - [-1, 3, C2f, [512]] # 24 (P4/16-medium)
49 |
50 | - [-1, 1, Conv, [512, 3, 2]]
51 | - [[-1, 9], 1, Concat, [1]] # cat head P5
52 | - [-1, 3, C2f, [1024]] # 27 (P5/32-large)
53 |
54 | - [[18, 21, 24, 27], 1, Detect, [nc]] # Detect(P2, P3, P4, P5)
55 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-p6.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8 object detection model with P3-P6 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n-p6.yaml' will call yolov8-p6.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024]
9 | s: [0.33, 0.50, 1024]
10 | m: [0.67, 0.75, 768]
11 | l: [1.00, 1.00, 512]
12 | x: [1.00, 1.25, 512]
13 |
14 | # YOLOv8.0x6 backbone
15 | backbone:
16 | # [from, repeats, module, args]
17 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
18 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
19 | - [-1, 3, C2f, [128, True]]
20 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21 | - [-1, 6, C2f, [256, True]]
22 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23 | - [-1, 6, C2f, [512, True]]
24 | - [-1, 1, Conv, [768, 3, 2]] # 7-P5/32
25 | - [-1, 3, C2f, [768, True]]
26 | - [-1, 1, Conv, [1024, 3, 2]] # 9-P6/64
27 | - [-1, 3, C2f, [1024, True]]
28 | - [-1, 1, SPPF, [1024, 5]] # 11
29 |
30 | # YOLOv8.0x6 head
31 | head:
32 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
33 | - [[-1, 8], 1, Concat, [1]] # cat backbone P5
34 | - [-1, 3, C2, [768, False]] # 14
35 |
36 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
37 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
38 | - [-1, 3, C2, [512, False]] # 17
39 |
40 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
41 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
42 | - [-1, 3, C2, [256, False]] # 20 (P3/8-small)
43 |
44 | - [-1, 1, Conv, [256, 3, 2]]
45 | - [[-1, 17], 1, Concat, [1]] # cat head P4
46 | - [-1, 3, C2, [512, False]] # 23 (P4/16-medium)
47 |
48 | - [-1, 1, Conv, [512, 3, 2]]
49 | - [[-1, 14], 1, Concat, [1]] # cat head P5
50 | - [-1, 3, C2, [768, False]] # 26 (P5/32-large)
51 |
52 | - [-1, 1, Conv, [768, 3, 2]]
53 | - [[-1, 11], 1, Concat, [1]] # cat head P6
54 | - [-1, 3, C2, [1024, False]] # 29 (P6/64-xlarge)
55 |
56 | - [[20, 23, 26, 29], 1, Detect, [nc]] # Detect(P3, P4, P5, P6)
57 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-pose-p6.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8-pose keypoints/pose estimation model. For Usage examples see https://docs.ultralytics.com/tasks/pose
3 |
4 | # Parameters
5 | nc: 1 # number of classes
6 | kpt_shape: [17, 3] # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
7 | scales: # model compound scaling constants, i.e. 'model=yolov8n-p6.yaml' will call yolov8-p6.yaml with scale 'n'
8 | # [depth, width, max_channels]
9 | n: [0.33, 0.25, 1024]
10 | s: [0.33, 0.50, 1024]
11 | m: [0.67, 0.75, 768]
12 | l: [1.00, 1.00, 512]
13 | x: [1.00, 1.25, 512]
14 |
15 | # YOLOv8.0x6 backbone
16 | backbone:
17 | # [from, repeats, module, args]
18 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
19 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
20 | - [-1, 3, C2f, [128, True]]
21 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
22 | - [-1, 6, C2f, [256, True]]
23 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
24 | - [-1, 6, C2f, [512, True]]
25 | - [-1, 1, Conv, [768, 3, 2]] # 7-P5/32
26 | - [-1, 3, C2f, [768, True]]
27 | - [-1, 1, Conv, [1024, 3, 2]] # 9-P6/64
28 | - [-1, 3, C2f, [1024, True]]
29 | - [-1, 1, SPPF, [1024, 5]] # 11
30 |
31 | # YOLOv8.0x6 head
32 | head:
33 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
34 | - [[-1, 8], 1, Concat, [1]] # cat backbone P5
35 | - [-1, 3, C2, [768, False]] # 14
36 |
37 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
38 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
39 | - [-1, 3, C2, [512, False]] # 17
40 |
41 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
42 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
43 | - [-1, 3, C2, [256, False]] # 20 (P3/8-small)
44 |
45 | - [-1, 1, Conv, [256, 3, 2]]
46 | - [[-1, 17], 1, Concat, [1]] # cat head P4
47 | - [-1, 3, C2, [512, False]] # 23 (P4/16-medium)
48 |
49 | - [-1, 1, Conv, [512, 3, 2]]
50 | - [[-1, 14], 1, Concat, [1]] # cat head P5
51 | - [-1, 3, C2, [768, False]] # 26 (P5/32-large)
52 |
53 | - [-1, 1, Conv, [768, 3, 2]]
54 | - [[-1, 11], 1, Concat, [1]] # cat head P6
55 | - [-1, 3, C2, [1024, False]] # 29 (P6/64-xlarge)
56 |
57 | - [[20, 23, 26, 29], 1, Pose, [nc, kpt_shape]] # Pose(P3, P4, P5, P6)
58 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-pose.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8-pose keypoints/pose estimation model. For Usage examples see https://docs.ultralytics.com/tasks/pose
3 |
4 | # Parameters
5 | nc: 1 # number of classes
6 | kpt_shape: [17, 3] # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
7 | scales: # model compound scaling constants, i.e. 'model=yolov8n-pose.yaml' will call yolov8-pose.yaml with scale 'n'
8 | # [depth, width, max_channels]
9 | n: [0.33, 0.25, 1024]
10 | s: [0.33, 0.50, 1024]
11 | m: [0.67, 0.75, 768]
12 | l: [1.00, 1.00, 512]
13 | x: [1.00, 1.25, 512]
14 |
15 | # YOLOv8.0n backbone
16 | backbone:
17 | # [from, repeats, module, args]
18 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
19 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
20 | - [-1, 3, C2f, [128, True]]
21 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
22 | - [-1, 6, C2f, [256, True]]
23 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
24 | - [-1, 6, C2f, [512, True]]
25 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
26 | - [-1, 3, C2f, [1024, True]]
27 | - [-1, 1, SPPF, [1024, 5]] # 9
28 |
29 | # YOLOv8.0n head
30 | head:
31 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
32 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
33 | - [-1, 3, C2f, [512]] # 12
34 |
35 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
36 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
37 | - [-1, 3, C2f, [256]] # 15 (P3/8-small)
38 |
39 | - [-1, 1, Conv, [256, 3, 2]]
40 | - [[-1, 12], 1, Concat, [1]] # cat head P4
41 | - [-1, 3, C2f, [512]] # 18 (P4/16-medium)
42 |
43 | - [-1, 1, Conv, [512, 3, 2]]
44 | - [[-1, 9], 1, Concat, [1]] # cat head P5
45 | - [-1, 3, C2f, [1024]] # 21 (P5/32-large)
46 |
47 | - [[15, 18, 21], 1, Pose, [nc, kpt_shape]] # Pose(P3, P4, P5)
48 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-rtdetr.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
9 | s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
10 | m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
11 | l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
12 | x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
13 |
14 | # YOLOv8.0n backbone
15 | backbone:
16 | # [from, repeats, module, args]
17 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
18 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
19 | - [-1, 3, C2f, [128, True]]
20 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21 | - [-1, 6, C2f, [256, True]]
22 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23 | - [-1, 6, C2f, [512, True]]
24 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
25 | - [-1, 3, C2f, [1024, True]]
26 | - [-1, 1, SPPF, [1024, 5]] # 9
27 |
28 | # YOLOv8.0n head
29 | head:
30 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
31 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
32 | - [-1, 3, C2f, [512]] # 12
33 |
34 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
35 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
36 | - [-1, 3, C2f, [256]] # 15 (P3/8-small)
37 |
38 | - [-1, 1, Conv, [256, 3, 2]]
39 | - [[-1, 12], 1, Concat, [1]] # cat head P4
40 | - [-1, 3, C2f, [512]] # 18 (P4/16-medium)
41 |
42 | - [-1, 1, Conv, [512, 3, 2]]
43 | - [[-1, 9], 1, Concat, [1]] # cat head P5
44 | - [-1, 3, C2f, [1024]] # 21 (P5/32-large)
45 |
46 | - [[15, 18, 21], 1, RTDETRDecoder, [nc]] # Detect(P3, P4, P5)
47 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8-seg.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8-seg instance segmentation model. For Usage examples see https://docs.ultralytics.com/tasks/segment
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n-seg.yaml' will call yolov8-seg.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024]
9 | s: [0.33, 0.50, 1024]
10 | m: [0.67, 0.75, 768]
11 | l: [1.00, 1.00, 512]
12 | x: [1.00, 1.25, 512]
13 |
14 | # YOLOv8.0n backbone
15 | backbone:
16 | # [from, repeats, module, args]
17 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
18 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
19 | - [-1, 3, C2f, [128, True]]
20 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21 | - [-1, 6, C2f, [256, True]]
22 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23 | - [-1, 6, C2f, [512, True]]
24 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
25 | - [-1, 3, C2f, [1024, True]]
26 | - [-1, 1, SPPF, [1024, 5]] # 9
27 |
28 | # YOLOv8.0n head
29 | head:
30 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
31 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
32 | - [-1, 3, C2f, [512]] # 12
33 |
34 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
35 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
36 | - [-1, 3, C2f, [256]] # 15 (P3/8-small)
37 |
38 | - [-1, 1, Conv, [256, 3, 2]]
39 | - [[-1, 12], 1, Concat, [1]] # cat head P4
40 | - [-1, 3, C2f, [512]] # 18 (P4/16-medium)
41 |
42 | - [-1, 1, Conv, [512, 3, 2]]
43 | - [[-1, 9], 1, Concat, [1]] # cat head P5
44 | - [-1, 3, C2f, [1024]] # 21 (P5/32-large)
45 |
46 | - [[15, 18, 21], 1, Segment, [nc, 32, 256]] # Segment(P3, P4, P5)
47 |
--------------------------------------------------------------------------------
/ultralytics/cfg/models/v8/yolov8.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
3 |
4 | # Parameters
5 | nc: 80 # number of classes
6 | scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
7 | # [depth, width, max_channels]
8 | n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
9 | s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
10 | m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
11 | l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
12 | x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
13 |
14 | # YOLOv8.0n backbone
15 | backbone:
16 | # [from, repeats, module, args]
17 | - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
18 | - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
19 | - [-1, 3, C2f, [128, True]]
20 | - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
21 | - [-1, 6, C2f, [256, True]]
22 | - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
23 | - [-1, 6, C2f, [512, True]]
24 | - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
25 | - [-1, 3, C2f, [1024, True]]
26 | - [-1, 1, SPPF, [1024, 5]] # 9
27 |
28 | # YOLOv8.0n head
29 | head:
30 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
31 | - [[-1, 6], 1, Concat, [1]] # cat backbone P4
32 | - [-1, 3, C2f, [512]] # 12
33 |
34 | - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
35 | - [[-1, 4], 1, Concat, [1]] # cat backbone P3
36 | - [-1, 3, C2f, [256]] # 15 (P3/8-small)
37 |
38 | - [-1, 1, Conv, [256, 3, 2]]
39 | - [[-1, 12], 1, Concat, [1]] # cat head P4
40 | - [-1, 3, C2f, [512]] # 18 (P4/16-medium)
41 |
42 | - [-1, 1, Conv, [512, 3, 2]]
43 | - [[-1, 9], 1, Concat, [1]] # cat head P5
44 | - [-1, 3, C2f, [1024]] # 21 (P5/32-large)
45 |
46 | - [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
47 |
--------------------------------------------------------------------------------
/ultralytics/cfg/trackers/botsort.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # Default YOLO tracker settings for BoT-SORT tracker https://github.com/NirAharon/BoT-SORT
3 |
4 | tracker_type: botsort # tracker type, ['botsort', 'bytetrack']
5 | track_high_thresh: 0.5 # threshold for the first association
6 | track_low_thresh: 0.1 # threshold for the second association
7 | new_track_thresh: 0.6 # threshold for init new track if the detection does not match any tracks
8 | track_buffer: 30 # buffer to calculate the time when to remove tracks
9 | match_thresh: 0.8 # threshold for matching tracks
10 | # min_box_area: 10 # threshold for min box areas(for tracker evaluation, not used for now)
11 | # mot20: False # for tracker evaluation(not used for now)
12 |
13 | # BoT-SORT settings
14 | cmc_method: sparseOptFlow # method of global motion compensation
15 | # ReID model related thresh (not supported yet)
16 | proximity_thresh: 0.5
17 | appearance_thresh: 0.25
18 | with_reid: False
19 |
--------------------------------------------------------------------------------
/ultralytics/cfg/trackers/bytetrack.yaml:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | # Default YOLO tracker settings for ByteTrack tracker https://github.com/ifzhang/ByteTrack
3 |
4 | tracker_type: bytetrack # tracker type, ['botsort', 'bytetrack']
5 | track_high_thresh: 0.5 # threshold for the first association
6 | track_low_thresh: 0.1 # threshold for the second association
7 | new_track_thresh: 0.6 # threshold for init new track if the detection does not match any tracks
8 | track_buffer: 30 # buffer to calculate the time when to remove tracks
9 | match_thresh: 0.8 # threshold for matching tracks
10 | # min_box_area: 10 # threshold for min box areas(for tracker evaluation, not used for now)
11 | # mot20: False # for tracker evaluation(not used for now)
12 |
--------------------------------------------------------------------------------
/ultralytics/data/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .base import BaseDataset
4 | from .build import build_dataloader, build_yolo_dataset, load_inference_source
5 | from .dataset import ClassificationDataset, SemanticDataset, YOLODataset
6 |
7 | __all__ = ('BaseDataset', 'ClassificationDataset', 'SemanticDataset', 'YOLODataset', 'build_yolo_dataset',
8 | 'build_dataloader', 'load_inference_source')
9 |
--------------------------------------------------------------------------------
/ultralytics/data/annotator.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | from ultralytics import SAM, YOLO
4 |
5 |
6 | def auto_annotate(data, det_model='yolov8x.pt', sam_model='sam_b.pt', device='', output_dir=None):
7 | """
8 | Automatically annotates images using a YOLO object detection model and a SAM segmentation model.
9 | Args:
10 | data (str): Path to a folder containing images to be annotated.
11 | det_model (str, optional): Pre-trained YOLO detection model. Defaults to 'yolov8x.pt'.
12 | sam_model (str, optional): Pre-trained SAM segmentation model. Defaults to 'sam_b.pt'.
13 | device (str, optional): Device to run the models on. Defaults to an empty string (CPU or GPU, if available).
14 | output_dir (str | None | optional): Directory to save the annotated results.
15 | Defaults to a 'labels' folder in the same directory as 'data'.
16 | """
17 | det_model = YOLO(det_model)
18 | sam_model = SAM(sam_model)
19 |
20 | if not output_dir:
21 | output_dir = Path(str(data)).parent / 'labels'
22 | Path(output_dir).mkdir(exist_ok=True, parents=True)
23 |
24 | det_results = det_model(data, stream=True, device=device)
25 |
26 | for result in det_results:
27 | class_ids = result.boxes.cls.int().tolist() # noqa
28 | if len(class_ids):
29 | boxes = result.boxes.xyxy # Boxes object for bbox outputs
30 | sam_results = sam_model(result.orig_img, bboxes=boxes, verbose=False, save=False, device=device)
31 | segments = sam_results[0].masks.xyn # noqa
32 |
33 | with open(f'{str(Path(output_dir) / Path(result.path).stem)}.txt', 'w') as f:
34 | for i in range(len(segments)):
35 | s = segments[i]
36 | if len(s) == 0:
37 | continue
38 | segment = map(str, segments[i].reshape(-1).tolist())
39 | f.write(f'{class_ids[i]} ' + ' '.join(segment) + '\n')
40 |
--------------------------------------------------------------------------------
/ultralytics/data/dataloaders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/T-SW/AutoLabelImg/2197d60c2baadfd9fec47b017b589126529897ab/ultralytics/data/dataloaders/__init__.py
--------------------------------------------------------------------------------
/ultralytics/data/scripts/download_weights.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Ultralytics YOLO 🚀, AGPL-3.0 license
3 | # Download latest models from https://github.com/ultralytics/assets/releases
4 | # Example usage: bash ultralytics/data/scripts/download_weights.sh
5 | # parent
6 | # └── weights
7 | # ├── yolov8n.pt ← downloads here
8 | # ├── yolov8s.pt
9 | # └── ...
10 |
11 | python - < w - threshold, 2] = w # x2
26 | boxes[boxes[:, 3] > h - threshold, 3] = h # y2
27 | return boxes
28 |
29 |
30 | def bbox_iou(box1, boxes, iou_thres=0.9, image_shape=(640, 640), raw_output=False):
31 | """
32 | Compute the Intersection-Over-Union of a bounding box with respect to an array of other bounding boxes.
33 |
34 | Args:
35 | box1 (torch.Tensor): (4, )
36 | boxes (torch.Tensor): (n, 4)
37 |
38 | Returns:
39 | high_iou_indices (torch.Tensor): Indices of boxes with IoU > thres
40 | """
41 | boxes = adjust_bboxes_to_image_border(boxes, image_shape)
42 | # obtain coordinates for intersections
43 | x1 = torch.max(box1[0], boxes[:, 0])
44 | y1 = torch.max(box1[1], boxes[:, 1])
45 | x2 = torch.min(box1[2], boxes[:, 2])
46 | y2 = torch.min(box1[3], boxes[:, 3])
47 |
48 | # compute the area of intersection
49 | intersection = (x2 - x1).clamp(0) * (y2 - y1).clamp(0)
50 |
51 | # compute the area of both individual boxes
52 | box1_area = (box1[2] - box1[0]) * (box1[3] - box1[1])
53 | box2_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
54 |
55 | # compute the area of union
56 | union = box1_area + box2_area - intersection
57 |
58 | # compute the IoU
59 | iou = intersection / union # Should be shape (n, )
60 | if raw_output:
61 | return 0 if iou.numel() == 0 else iou
62 |
63 | # return indices of boxes with IoU > thres
64 | return torch.nonzero(iou > iou_thres).flatten()
65 |
--------------------------------------------------------------------------------
/ultralytics/models/nas/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .model import NAS
4 | from .predict import NASPredictor
5 | from .val import NASValidator
6 |
7 | __all__ = 'NASPredictor', 'NASValidator', 'NAS'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/nas/model.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | YOLO-NAS model interface.
4 |
5 | Usage - Predict:
6 | from ultralytics import NAS
7 |
8 | model = NAS('yolo_nas_s')
9 | results = model.predict('ultralytics/assets/bus.jpg')
10 | """
11 |
12 | from pathlib import Path
13 |
14 | import torch
15 |
16 | from ultralytics.engine.model import Model
17 | from ultralytics.utils.torch_utils import model_info, smart_inference_mode
18 |
19 | from .predict import NASPredictor
20 | from .val import NASValidator
21 |
22 |
23 | class NAS(Model):
24 |
25 | def __init__(self, model='yolo_nas_s.pt') -> None:
26 | assert Path(model).suffix not in ('.yaml', '.yml'), 'YOLO-NAS models only support pre-trained models.'
27 | super().__init__(model, task='detect')
28 |
29 | @smart_inference_mode()
30 | def _load(self, weights: str, task: str):
31 | # Load or create new NAS model
32 | import super_gradients
33 | suffix = Path(weights).suffix
34 | if suffix == '.pt':
35 | self.model = torch.load(weights)
36 | elif suffix == '':
37 | self.model = super_gradients.training.models.get(weights, pretrained_weights='coco')
38 | # Standardize model
39 | self.model.fuse = lambda verbose=True: self.model
40 | self.model.stride = torch.tensor([32])
41 | self.model.names = dict(enumerate(self.model._class_names))
42 | self.model.is_fused = lambda: False # for info()
43 | self.model.yaml = {} # for info()
44 | self.model.pt_path = weights # for export()
45 | self.model.task = 'detect' # for export()
46 |
47 | def info(self, detailed=False, verbose=True):
48 | """
49 | Logs model info.
50 |
51 | Args:
52 | detailed (bool): Show detailed information about model.
53 | verbose (bool): Controls verbosity.
54 | """
55 | return model_info(self.model, detailed=detailed, verbose=verbose, imgsz=640)
56 |
57 | @property
58 | def task_map(self):
59 | return {'detect': {'predictor': NASPredictor, 'validator': NASValidator}}
60 |
--------------------------------------------------------------------------------
/ultralytics/models/nas/predict.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import torch
4 |
5 | from ultralytics.engine.predictor import BasePredictor
6 | from ultralytics.engine.results import Results
7 | from ultralytics.utils import ops
8 | from ultralytics.utils.ops import xyxy2xywh
9 |
10 |
11 | class NASPredictor(BasePredictor):
12 |
13 | def postprocess(self, preds_in, img, orig_imgs):
14 | """Postprocesses predictions and returns a list of Results objects."""
15 |
16 | # Cat boxes and class scores
17 | boxes = xyxy2xywh(preds_in[0][0])
18 | preds = torch.cat((boxes, preds_in[0][1]), -1).permute(0, 2, 1)
19 |
20 | preds = ops.non_max_suppression(preds,
21 | self.args.conf,
22 | self.args.iou,
23 | agnostic=self.args.agnostic_nms,
24 | max_det=self.args.max_det,
25 | classes=self.args.classes)
26 |
27 | results = []
28 | for i, pred in enumerate(preds):
29 | orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
30 | if not isinstance(orig_imgs, torch.Tensor):
31 | pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
32 | path = self.batch[0]
33 | img_path = path[i] if isinstance(path, list) else path
34 | results.append(Results(orig_img=orig_img, path=img_path, names=self.model.names, boxes=pred))
35 | return results
36 |
--------------------------------------------------------------------------------
/ultralytics/models/nas/val.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import torch
4 |
5 | from ultralytics.models.yolo.detect import DetectionValidator
6 | from ultralytics.utils import ops
7 | from ultralytics.utils.ops import xyxy2xywh
8 |
9 | __all__ = ['NASValidator']
10 |
11 |
12 | class NASValidator(DetectionValidator):
13 |
14 | def postprocess(self, preds_in):
15 | """Apply Non-maximum suppression to prediction outputs."""
16 | boxes = xyxy2xywh(preds_in[0][0])
17 | preds = torch.cat((boxes, preds_in[0][1]), -1).permute(0, 2, 1)
18 | return ops.non_max_suppression(preds,
19 | self.args.conf,
20 | self.args.iou,
21 | labels=self.lb,
22 | multi_label=False,
23 | agnostic=self.args.single_cls,
24 | max_det=self.args.max_det,
25 | max_time_img=0.5)
26 |
--------------------------------------------------------------------------------
/ultralytics/models/rtdetr/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .model import RTDETR
4 | from .predict import RTDETRPredictor
5 | from .val import RTDETRValidator
6 |
7 | __all__ = 'RTDETRPredictor', 'RTDETRValidator', 'RTDETR'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/rtdetr/model.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | RT-DETR model interface
4 | """
5 | from ultralytics.engine.model import Model
6 | from ultralytics.nn.tasks import RTDETRDetectionModel
7 |
8 | from .predict import RTDETRPredictor
9 | from .train import RTDETRTrainer
10 | from .val import RTDETRValidator
11 |
12 |
13 | class RTDETR(Model):
14 | """
15 | RTDETR model interface.
16 | """
17 |
18 | def __init__(self, model='rtdetr-l.pt') -> None:
19 | if model and not model.split('.')[-1] in ('pt', 'yaml', 'yml'):
20 | raise NotImplementedError('RT-DETR only supports creating from *.pt file or *.yaml file.')
21 | super().__init__(model=model, task='detect')
22 |
23 | @property
24 | def task_map(self):
25 | return {
26 | 'detect': {
27 | 'predictor': RTDETRPredictor,
28 | 'validator': RTDETRValidator,
29 | 'trainer': RTDETRTrainer,
30 | 'model': RTDETRDetectionModel}}
31 |
--------------------------------------------------------------------------------
/ultralytics/models/rtdetr/predict.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import torch
4 |
5 | from ultralytics.data.augment import LetterBox
6 | from ultralytics.engine.predictor import BasePredictor
7 | from ultralytics.engine.results import Results
8 | from ultralytics.utils import ops
9 |
10 |
11 | class RTDETRPredictor(BasePredictor):
12 |
13 | def postprocess(self, preds, img, orig_imgs):
14 | """Postprocess predictions and returns a list of Results objects."""
15 | nd = preds[0].shape[-1]
16 | bboxes, scores = preds[0].split((4, nd - 4), dim=-1)
17 | results = []
18 | for i, bbox in enumerate(bboxes): # (300, 4)
19 | bbox = ops.xywh2xyxy(bbox)
20 | score, cls = scores[i].max(-1, keepdim=True) # (300, 1)
21 | idx = score.squeeze(-1) > self.args.conf # (300, )
22 | if self.args.classes is not None:
23 | idx = (cls == torch.tensor(self.args.classes, device=cls.device)).any(1) & idx
24 | pred = torch.cat([bbox, score, cls], dim=-1)[idx] # filter
25 | orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
26 | oh, ow = orig_img.shape[:2]
27 | if not isinstance(orig_imgs, torch.Tensor):
28 | pred[..., [0, 2]] *= ow
29 | pred[..., [1, 3]] *= oh
30 | path = self.batch[0]
31 | img_path = path[i] if isinstance(path, list) else path
32 | results.append(Results(orig_img=orig_img, path=img_path, names=self.model.names, boxes=pred))
33 | return results
34 |
35 | def pre_transform(self, im):
36 | """Pre-transform input image before inference.
37 |
38 | Args:
39 | im (List(np.ndarray)): (N, 3, h, w) for tensor, [(h, w, 3) x N] for list.
40 |
41 | Return: A list of transformed imgs.
42 | """
43 | # The size must be square(640) and scaleFilled.
44 | return [LetterBox(self.imgsz, auto=False, scaleFill=True)(image=x) for x in im]
45 |
--------------------------------------------------------------------------------
/ultralytics/models/rtdetr/train.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from copy import copy
4 |
5 | import torch
6 |
7 | from ultralytics.models.yolo.detect import DetectionTrainer
8 | from ultralytics.nn.tasks import RTDETRDetectionModel
9 | from ultralytics.utils import DEFAULT_CFG, RANK, colorstr
10 |
11 | from .val import RTDETRDataset, RTDETRValidator
12 |
13 |
14 | class RTDETRTrainer(DetectionTrainer):
15 |
16 | def get_model(self, cfg=None, weights=None, verbose=True):
17 | """Return a YOLO detection model."""
18 | model = RTDETRDetectionModel(cfg, nc=self.data['nc'], verbose=verbose and RANK == -1)
19 | if weights:
20 | model.load(weights)
21 | return model
22 |
23 | def build_dataset(self, img_path, mode='val', batch=None):
24 | """Build RTDETR Dataset
25 |
26 | Args:
27 | img_path (str): Path to the folder containing images.
28 | mode (str): `train` mode or `val` mode, users are able to customize different augmentations for each mode.
29 | batch (int, optional): Size of batches, this is for `rect`. Defaults to None.
30 | """
31 | return RTDETRDataset(
32 | img_path=img_path,
33 | imgsz=self.args.imgsz,
34 | batch_size=batch,
35 | augment=mode == 'train', # no augmentation
36 | hyp=self.args,
37 | rect=False, # no rect
38 | cache=self.args.cache or None,
39 | prefix=colorstr(f'{mode}: '),
40 | data=self.data)
41 |
42 | def get_validator(self):
43 | """Returns a DetectionValidator for RTDETR model validation."""
44 | self.loss_names = 'giou_loss', 'cls_loss', 'l1_loss'
45 | return RTDETRValidator(self.test_loader, save_dir=self.save_dir, args=copy(self.args))
46 |
47 | def preprocess_batch(self, batch):
48 | """Preprocesses a batch of images by scaling and converting to float."""
49 | batch = super().preprocess_batch(batch)
50 | bs = len(batch['img'])
51 | batch_idx = batch['batch_idx']
52 | gt_bbox, gt_class = [], []
53 | for i in range(bs):
54 | gt_bbox.append(batch['bboxes'][batch_idx == i].to(batch_idx.device))
55 | gt_class.append(batch['cls'][batch_idx == i].to(device=batch_idx.device, dtype=torch.long))
56 | return batch
57 |
58 |
59 | def train(cfg=DEFAULT_CFG, use_python=False):
60 | """Train and optimize RTDETR model given training data and device."""
61 | model = 'rtdetr-l.yaml'
62 | data = cfg.data or 'coco128.yaml' # or yolo.ClassificationDataset("mnist")
63 | device = cfg.device if cfg.device is not None else ''
64 |
65 | # NOTE: F.grid_sample which is in rt-detr does not support deterministic=True
66 | # NOTE: amp training causes nan outputs and end with error while doing bipartite graph matching
67 | args = dict(model=model,
68 | data=data,
69 | device=device,
70 | imgsz=640,
71 | exist_ok=True,
72 | batch=4,
73 | deterministic=False,
74 | amp=False)
75 | trainer = RTDETRTrainer(overrides=args)
76 | trainer.train()
77 |
78 |
79 | if __name__ == '__main__':
80 | train()
81 |
--------------------------------------------------------------------------------
/ultralytics/models/sam/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .model import SAM
4 | from .predict import Predictor
5 |
6 | # from .build import build_sam
7 |
8 | __all__ = 'SAM', 'Predictor' # tuple or list
9 |
--------------------------------------------------------------------------------
/ultralytics/models/sam/model.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | SAM model interface
4 | """
5 |
6 | from ultralytics.engine.model import Model
7 | from ultralytics.utils.torch_utils import model_info
8 |
9 | from .build import build_sam
10 | from .predict import Predictor
11 |
12 |
13 | class SAM(Model):
14 | """
15 | SAM model interface.
16 | """
17 |
18 | def __init__(self, model='sam_b.pt') -> None:
19 | if model and not model.endswith('.pt') and not model.endswith('.pth'):
20 | # Should raise AssertionError instead?
21 | raise NotImplementedError('Segment anything prediction requires pre-trained checkpoint')
22 | super().__init__(model=model, task='segment')
23 |
24 | def _load(self, weights: str, task=None):
25 | self.model = build_sam(weights)
26 |
27 | def predict(self, source, stream=False, bboxes=None, points=None, labels=None, **kwargs):
28 | """Predicts and returns segmentation masks for given image or video source."""
29 | overrides = dict(conf=0.25, task='segment', mode='predict', imgsz=1024)
30 | kwargs.update(overrides)
31 | prompts = dict(bboxes=bboxes, points=points, labels=labels)
32 | return super().predict(source, stream, prompts=prompts, **kwargs)
33 |
34 | def __call__(self, source=None, stream=False, bboxes=None, points=None, labels=None, **kwargs):
35 | """Calls the 'predict' function with given arguments to perform object detection."""
36 | return self.predict(source, stream, bboxes, points, labels, **kwargs)
37 |
38 | def info(self, detailed=False, verbose=True):
39 | """
40 | Logs model info.
41 |
42 | Args:
43 | detailed (bool): Show detailed information about model.
44 | verbose (bool): Controls verbosity.
45 | """
46 | return model_info(self.model, detailed=detailed, verbose=verbose)
47 |
48 | @property
49 | def task_map(self):
50 | return {'segment': {'predictor': Predictor}}
51 |
--------------------------------------------------------------------------------
/ultralytics/models/sam/modules/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
--------------------------------------------------------------------------------
/ultralytics/models/utils/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.models.yolo import classify, detect, pose, segment
4 |
5 | from .model import YOLO
6 |
7 | __all__ = 'classify', 'segment', 'detect', 'pose', 'YOLO'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/classify/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.models.yolo.classify.predict import ClassificationPredictor, predict
4 | from ultralytics.models.yolo.classify.train import ClassificationTrainer, train
5 | from ultralytics.models.yolo.classify.val import ClassificationValidator, val
6 |
7 | __all__ = 'ClassificationPredictor', 'predict', 'ClassificationTrainer', 'train', 'ClassificationValidator', 'val'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/classify/predict.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import torch
4 |
5 | from ultralytics.engine.predictor import BasePredictor
6 | from ultralytics.engine.results import Results
7 | from ultralytics.utils import DEFAULT_CFG, ROOT
8 |
9 |
10 | class ClassificationPredictor(BasePredictor):
11 |
12 | def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
13 | super().__init__(cfg, overrides, _callbacks)
14 | self.args.task = 'classify'
15 |
16 | def preprocess(self, img):
17 | """Converts input image to model-compatible data type."""
18 | if not isinstance(img, torch.Tensor):
19 | img = torch.stack([self.transforms(im) for im in img], dim=0)
20 | img = (img if isinstance(img, torch.Tensor) else torch.from_numpy(img)).to(self.model.device)
21 | return img.half() if self.model.fp16 else img.float() # uint8 to fp16/32
22 |
23 | def postprocess(self, preds, img, orig_imgs):
24 | """Postprocesses predictions to return Results objects."""
25 | results = []
26 | for i, pred in enumerate(preds):
27 | orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
28 | path = self.batch[0]
29 | img_path = path[i] if isinstance(path, list) else path
30 | results.append(Results(orig_img=orig_img, path=img_path, names=self.model.names, probs=pred))
31 |
32 | return results
33 |
34 |
35 | def predict(cfg=DEFAULT_CFG, use_python=False):
36 | """Run YOLO model predictions on input images/videos."""
37 | model = cfg.model or 'yolov8n-cls.pt' # or "resnet18"
38 | source = cfg.source if cfg.source is not None else ROOT / 'assets' if (ROOT / 'assets').exists() \
39 | else 'https://ultralytics.com/images/bus.jpg'
40 |
41 | args = dict(model=model, source=source)
42 | if use_python:
43 | from ultralytics import YOLO
44 | YOLO(model)(**args)
45 | else:
46 | predictor = ClassificationPredictor(overrides=args)
47 | predictor.predict_cli()
48 |
49 |
50 | if __name__ == '__main__':
51 | predict()
52 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/detect/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .predict import DetectionPredictor, predict
4 | from .train import DetectionTrainer, train
5 | from .val import DetectionValidator, val
6 |
7 | __all__ = 'DetectionPredictor', 'predict', 'DetectionTrainer', 'train', 'DetectionValidator', 'val'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/detect/predict.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import torch
4 |
5 | from ultralytics.engine.predictor import BasePredictor
6 | from ultralytics.engine.results import Results
7 | from ultralytics.utils import DEFAULT_CFG, ROOT, ops
8 |
9 |
10 | class DetectionPredictor(BasePredictor):
11 |
12 | def postprocess(self, preds, img, orig_imgs):
13 | """Postprocesses predictions and returns a list of Results objects."""
14 | preds = ops.non_max_suppression(preds,
15 | self.args.conf,
16 | self.args.iou,
17 | agnostic=self.args.agnostic_nms,
18 | max_det=self.args.max_det,
19 | classes=self.args.classes)
20 |
21 | results = []
22 | for i, pred in enumerate(preds):
23 | orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
24 | if not isinstance(orig_imgs, torch.Tensor):
25 | pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
26 | path = self.batch[0]
27 | img_path = path[i] if isinstance(path, list) else path
28 | results.append(Results(orig_img=orig_img, path=img_path, names=self.model.names, boxes=pred))
29 | return results
30 |
31 |
32 | def predict(cfg=DEFAULT_CFG, use_python=False):
33 | """Runs YOLO model inference on input image(s)."""
34 | model = cfg.model or 'yolov8n.pt'
35 | source = cfg.source if cfg.source is not None else ROOT / 'assets' if (ROOT / 'assets').exists() \
36 | else 'https://ultralytics.com/images/bus.jpg'
37 |
38 | args = dict(model=model, source=source)
39 | if use_python:
40 | from ultralytics import YOLO
41 | YOLO(model)(**args)
42 | else:
43 | predictor = DetectionPredictor(overrides=args)
44 | predictor.predict_cli()
45 |
46 |
47 | if __name__ == '__main__':
48 | predict()
49 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/model.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.engine.model import Model
4 | from ultralytics.models import yolo # noqa
5 | from ultralytics.nn.tasks import ClassificationModel, DetectionModel, PoseModel, SegmentationModel
6 |
7 |
8 | class YOLO(Model):
9 | """
10 | YOLO (You Only Look Once) object detection model.
11 | """
12 |
13 | @property
14 | def task_map(self):
15 | """Map head to model, trainer, validator, and predictor classes"""
16 | return {
17 | 'classify': {
18 | 'model': ClassificationModel,
19 | 'trainer': yolo.classify.ClassificationTrainer,
20 | 'validator': yolo.classify.ClassificationValidator,
21 | 'predictor': yolo.classify.ClassificationPredictor, },
22 | 'detect': {
23 | 'model': DetectionModel,
24 | 'trainer': yolo.detect.DetectionTrainer,
25 | 'validator': yolo.detect.DetectionValidator,
26 | 'predictor': yolo.detect.DetectionPredictor, },
27 | 'segment': {
28 | 'model': SegmentationModel,
29 | 'trainer': yolo.segment.SegmentationTrainer,
30 | 'validator': yolo.segment.SegmentationValidator,
31 | 'predictor': yolo.segment.SegmentationPredictor, },
32 | 'pose': {
33 | 'model': PoseModel,
34 | 'trainer': yolo.pose.PoseTrainer,
35 | 'validator': yolo.pose.PoseValidator,
36 | 'predictor': yolo.pose.PosePredictor, }, }
37 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/pose/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .predict import PosePredictor, predict
4 | from .train import PoseTrainer, train
5 | from .val import PoseValidator, val
6 |
7 | __all__ = 'PoseTrainer', 'train', 'PoseValidator', 'val', 'PosePredictor', 'predict'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/pose/predict.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.engine.results import Results
4 | from ultralytics.models.yolo.detect.predict import DetectionPredictor
5 | from ultralytics.utils import DEFAULT_CFG, LOGGER, ROOT, ops
6 |
7 |
8 | class PosePredictor(DetectionPredictor):
9 |
10 | def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
11 | super().__init__(cfg, overrides, _callbacks)
12 | self.args.task = 'pose'
13 | if isinstance(self.args.device, str) and self.args.device.lower() == 'mps':
14 | LOGGER.warning("WARNING ⚠️ Apple MPS known Pose bug. Recommend 'device=cpu' for Pose models. "
15 | 'See https://github.com/ultralytics/ultralytics/issues/4031.')
16 |
17 | def postprocess(self, preds, img, orig_imgs):
18 | """Return detection results for a given input image or list of images."""
19 | preds = ops.non_max_suppression(preds,
20 | self.args.conf,
21 | self.args.iou,
22 | agnostic=self.args.agnostic_nms,
23 | max_det=self.args.max_det,
24 | classes=self.args.classes,
25 | nc=len(self.model.names))
26 |
27 | results = []
28 | for i, pred in enumerate(preds):
29 | orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
30 | shape = orig_img.shape
31 | pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], shape).round()
32 | pred_kpts = pred[:, 6:].view(len(pred), *self.model.kpt_shape) if len(pred) else pred[:, 6:]
33 | pred_kpts = ops.scale_coords(img.shape[2:], pred_kpts, shape)
34 | path = self.batch[0]
35 | img_path = path[i] if isinstance(path, list) else path
36 | results.append(
37 | Results(orig_img=orig_img,
38 | path=img_path,
39 | names=self.model.names,
40 | boxes=pred[:, :6],
41 | keypoints=pred_kpts))
42 | return results
43 |
44 |
45 | def predict(cfg=DEFAULT_CFG, use_python=False):
46 | """Runs YOLO to predict objects in an image or video."""
47 | model = cfg.model or 'yolov8n-pose.pt'
48 | source = cfg.source if cfg.source is not None else ROOT / 'assets' if (ROOT / 'assets').exists() \
49 | else 'https://ultralytics.com/images/bus.jpg'
50 |
51 | args = dict(model=model, source=source)
52 | if use_python:
53 | from ultralytics import YOLO
54 | YOLO(model)(**args)
55 | else:
56 | predictor = PosePredictor(overrides=args)
57 | predictor.predict_cli()
58 |
59 |
60 | if __name__ == '__main__':
61 | predict()
62 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/pose/train.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from copy import copy
4 |
5 | from ultralytics.models import yolo
6 | from ultralytics.nn.tasks import PoseModel
7 | from ultralytics.utils import DEFAULT_CFG, LOGGER
8 | from ultralytics.utils.plotting import plot_images, plot_results
9 |
10 |
11 | # BaseTrainer python usage
12 | class PoseTrainer(yolo.detect.DetectionTrainer):
13 |
14 | def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
15 | """Initialize a PoseTrainer object with specified configurations and overrides."""
16 | if overrides is None:
17 | overrides = {}
18 | overrides['task'] = 'pose'
19 | super().__init__(cfg, overrides, _callbacks)
20 |
21 | if isinstance(self.args.device, str) and self.args.device.lower() == 'mps':
22 | LOGGER.warning("WARNING ⚠️ Apple MPS known Pose bug. Recommend 'device=cpu' for Pose models. "
23 | 'See https://github.com/ultralytics/ultralytics/issues/4031.')
24 |
25 | def get_model(self, cfg=None, weights=None, verbose=True):
26 | """Get pose estimation model with specified configuration and weights."""
27 | model = PoseModel(cfg, ch=3, nc=self.data['nc'], data_kpt_shape=self.data['kpt_shape'], verbose=verbose)
28 | if weights:
29 | model.load(weights)
30 |
31 | return model
32 |
33 | def set_model_attributes(self):
34 | """Sets keypoints shape attribute of PoseModel."""
35 | super().set_model_attributes()
36 | self.model.kpt_shape = self.data['kpt_shape']
37 |
38 | def get_validator(self):
39 | """Returns an instance of the PoseValidator class for validation."""
40 | self.loss_names = 'box_loss', 'pose_loss', 'kobj_loss', 'cls_loss', 'dfl_loss'
41 | return yolo.pose.PoseValidator(self.test_loader, save_dir=self.save_dir, args=copy(self.args))
42 |
43 | def plot_training_samples(self, batch, ni):
44 | """Plot a batch of training samples with annotated class labels, bounding boxes, and keypoints."""
45 | images = batch['img']
46 | kpts = batch['keypoints']
47 | cls = batch['cls'].squeeze(-1)
48 | bboxes = batch['bboxes']
49 | paths = batch['im_file']
50 | batch_idx = batch['batch_idx']
51 | plot_images(images,
52 | batch_idx,
53 | cls,
54 | bboxes,
55 | kpts=kpts,
56 | paths=paths,
57 | fname=self.save_dir / f'train_batch{ni}.jpg',
58 | on_plot=self.on_plot)
59 |
60 | def plot_metrics(self):
61 | """Plots training/val metrics."""
62 | plot_results(file=self.csv, pose=True, on_plot=self.on_plot) # save results.png
63 |
64 |
65 | def train(cfg=DEFAULT_CFG, use_python=False):
66 | """Train the YOLO model on the given data and device."""
67 | model = cfg.model or 'yolov8n-pose.yaml'
68 | data = cfg.data or 'coco8-pose.yaml'
69 | device = cfg.device if cfg.device is not None else ''
70 |
71 | args = dict(model=model, data=data, device=device)
72 | if use_python:
73 | from ultralytics import YOLO
74 | YOLO(model).train(**args)
75 | else:
76 | trainer = PoseTrainer(overrides=args)
77 | trainer.train()
78 |
79 |
80 | if __name__ == '__main__':
81 | train()
82 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/segment/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .predict import SegmentationPredictor, predict
4 | from .train import SegmentationTrainer, train
5 | from .val import SegmentationValidator, val
6 |
7 | __all__ = 'SegmentationPredictor', 'predict', 'SegmentationTrainer', 'train', 'SegmentationValidator', 'val'
8 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/segment/predict.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import torch
4 |
5 | from ultralytics.engine.results import Results
6 | from ultralytics.models.yolo.detect.predict import DetectionPredictor
7 | from ultralytics.utils import DEFAULT_CFG, ROOT, ops
8 |
9 |
10 | class SegmentationPredictor(DetectionPredictor):
11 |
12 | def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
13 | super().__init__(cfg, overrides, _callbacks)
14 | self.args.task = 'segment'
15 |
16 | def postprocess(self, preds, img, orig_imgs):
17 | """TODO: filter by classes."""
18 | p = ops.non_max_suppression(preds[0],
19 | self.args.conf,
20 | self.args.iou,
21 | agnostic=self.args.agnostic_nms,
22 | max_det=self.args.max_det,
23 | nc=len(self.model.names),
24 | classes=self.args.classes)
25 | results = []
26 | proto = preds[1][-1] if len(preds[1]) == 3 else preds[1] # second output is len 3 if pt, but only 1 if exported
27 | for i, pred in enumerate(p):
28 | orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
29 | path = self.batch[0]
30 | img_path = path[i] if isinstance(path, list) else path
31 | if not len(pred): # save empty boxes
32 | results.append(Results(orig_img=orig_img, path=img_path, names=self.model.names, boxes=pred[:, :6]))
33 | continue
34 | if self.args.retina_masks:
35 | if not isinstance(orig_imgs, torch.Tensor):
36 | pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
37 | masks = ops.process_mask_native(proto[i], pred[:, 6:], pred[:, :4], orig_img.shape[:2]) # HWC
38 | else:
39 | masks = ops.process_mask(proto[i], pred[:, 6:], pred[:, :4], img.shape[2:], upsample=True) # HWC
40 | if not isinstance(orig_imgs, torch.Tensor):
41 | pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
42 | results.append(
43 | Results(orig_img=orig_img, path=img_path, names=self.model.names, boxes=pred[:, :6], masks=masks))
44 | return results
45 |
46 |
47 | def predict(cfg=DEFAULT_CFG, use_python=False):
48 | """Runs YOLO object detection on an image or video source."""
49 | model = cfg.model or 'yolov8n-seg.pt'
50 | source = cfg.source if cfg.source is not None else ROOT / 'assets' if (ROOT / 'assets').exists() \
51 | else 'https://ultralytics.com/images/bus.jpg'
52 |
53 | args = dict(model=model, source=source)
54 | if use_python:
55 | from ultralytics import YOLO
56 | YOLO(model)(**args)
57 | else:
58 | predictor = SegmentationPredictor(overrides=args)
59 | predictor.predict_cli()
60 |
61 |
62 | if __name__ == '__main__':
63 | predict()
64 |
--------------------------------------------------------------------------------
/ultralytics/models/yolo/segment/train.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from copy import copy
4 |
5 | from ultralytics.models import yolo
6 | from ultralytics.nn.tasks import SegmentationModel
7 | from ultralytics.utils import DEFAULT_CFG, RANK
8 | from ultralytics.utils.plotting import plot_images, plot_results
9 |
10 |
11 | # BaseTrainer python usage
12 | class SegmentationTrainer(yolo.detect.DetectionTrainer):
13 |
14 | def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
15 | """Initialize a SegmentationTrainer object with given arguments."""
16 | if overrides is None:
17 | overrides = {}
18 | overrides['task'] = 'segment'
19 | super().__init__(cfg, overrides, _callbacks)
20 |
21 | def get_model(self, cfg=None, weights=None, verbose=True):
22 | """Return SegmentationModel initialized with specified config and weights."""
23 | model = SegmentationModel(cfg, ch=3, nc=self.data['nc'], verbose=verbose and RANK == -1)
24 | if weights:
25 | model.load(weights)
26 |
27 | return model
28 |
29 | def get_validator(self):
30 | """Return an instance of SegmentationValidator for validation of YOLO model."""
31 | self.loss_names = 'box_loss', 'seg_loss', 'cls_loss', 'dfl_loss'
32 | return yolo.segment.SegmentationValidator(self.test_loader, save_dir=self.save_dir, args=copy(self.args))
33 |
34 | def plot_training_samples(self, batch, ni):
35 | """Creates a plot of training sample images with labels and box coordinates."""
36 | plot_images(batch['img'],
37 | batch['batch_idx'],
38 | batch['cls'].squeeze(-1),
39 | batch['bboxes'],
40 | batch['masks'],
41 | paths=batch['im_file'],
42 | fname=self.save_dir / f'train_batch{ni}.jpg',
43 | on_plot=self.on_plot)
44 |
45 | def plot_metrics(self):
46 | """Plots training/val metrics."""
47 | plot_results(file=self.csv, segment=True, on_plot=self.on_plot) # save results.png
48 |
49 |
50 | def train(cfg=DEFAULT_CFG, use_python=False):
51 | """Train a YOLO segmentation model based on passed arguments."""
52 | model = cfg.model or 'yolov8n-seg.pt'
53 | data = cfg.data or 'coco128-seg.yaml' # or yolo.ClassificationDataset("mnist")
54 | device = cfg.device if cfg.device is not None else ''
55 |
56 | args = dict(model=model, data=data, device=device)
57 | if use_python:
58 | from ultralytics import YOLO
59 | YOLO(model).train(**args)
60 | else:
61 | trainer = SegmentationTrainer(overrides=args)
62 | trainer.train()
63 |
64 |
65 | if __name__ == '__main__':
66 | train()
67 |
--------------------------------------------------------------------------------
/ultralytics/nn/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .tasks import (BaseModel, ClassificationModel, DetectionModel, SegmentationModel, attempt_load_one_weight,
4 | attempt_load_weights, guess_model_scale, guess_model_task, parse_model, torch_safe_load,
5 | yaml_model_load)
6 |
7 | __all__ = ('attempt_load_one_weight', 'attempt_load_weights', 'parse_model', 'yaml_model_load', 'guess_model_task',
8 | 'guess_model_scale', 'torch_safe_load', 'DetectionModel', 'SegmentationModel', 'ClassificationModel',
9 | 'BaseModel')
10 |
--------------------------------------------------------------------------------
/ultralytics/nn/modules/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | Ultralytics modules. Visualize with:
4 |
5 | from ultralytics.nn.modules import *
6 | import torch
7 | import os
8 |
9 | x = torch.ones(1, 128, 40, 40)
10 | m = Conv(128, 128)
11 | f = f'{m._get_name()}.onnx'
12 | torch.onnx.export(m, x, f)
13 | os.system(f'onnxsim {f} {f} && open {f}')
14 | """
15 |
16 | from .block import (C1, C2, C3, C3TR, DFL, SPP, SPPF, Bottleneck, BottleneckCSP, C2f, C3Ghost, C3x, GhostBottleneck,
17 | HGBlock, HGStem, Proto, RepC3)
18 | from .conv import (CBAM, ChannelAttention, Concat, Conv, Conv2, ConvTranspose, DWConv, DWConvTranspose2d, Focus,
19 | GhostConv, LightConv, RepConv, SpatialAttention)
20 | from .head import Classify, Detect, Pose, RTDETRDecoder, Segment
21 | from .transformer import (AIFI, MLP, DeformableTransformerDecoder, DeformableTransformerDecoderLayer, LayerNorm2d,
22 | MLPBlock, MSDeformAttn, TransformerBlock, TransformerEncoderLayer, TransformerLayer)
23 |
24 | __all__ = ('Conv', 'Conv2', 'LightConv', 'RepConv', 'DWConv', 'DWConvTranspose2d', 'ConvTranspose', 'Focus',
25 | 'GhostConv', 'ChannelAttention', 'SpatialAttention', 'CBAM', 'Concat', 'TransformerLayer',
26 | 'TransformerBlock', 'MLPBlock', 'LayerNorm2d', 'DFL', 'HGBlock', 'HGStem', 'SPP', 'SPPF', 'C1', 'C2', 'C3',
27 | 'C2f', 'C3x', 'C3TR', 'C3Ghost', 'GhostBottleneck', 'Bottleneck', 'BottleneckCSP', 'Proto', 'Detect',
28 | 'Segment', 'Pose', 'Classify', 'TransformerEncoderLayer', 'RepC3', 'RTDETRDecoder', 'AIFI',
29 | 'DeformableTransformerDecoder', 'DeformableTransformerDecoderLayer', 'MSDeformAttn', 'MLP')
30 |
--------------------------------------------------------------------------------
/ultralytics/nn/modules/utils.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | Module utils
4 | """
5 |
6 | import copy
7 | import math
8 |
9 | import numpy as np
10 | import torch
11 | import torch.nn as nn
12 | import torch.nn.functional as F
13 | from torch.nn.init import uniform_
14 |
15 | __all__ = 'multi_scale_deformable_attn_pytorch', 'inverse_sigmoid'
16 |
17 |
18 | def _get_clones(module, n):
19 | return nn.ModuleList([copy.deepcopy(module) for _ in range(n)])
20 |
21 |
22 | def bias_init_with_prob(prior_prob=0.01):
23 | """initialize conv/fc bias value according to a given probability value."""
24 | return float(-np.log((1 - prior_prob) / prior_prob)) # return bias_init
25 |
26 |
27 | def linear_init_(module):
28 | bound = 1 / math.sqrt(module.weight.shape[0])
29 | uniform_(module.weight, -bound, bound)
30 | if hasattr(module, 'bias') and module.bias is not None:
31 | uniform_(module.bias, -bound, bound)
32 |
33 |
34 | def inverse_sigmoid(x, eps=1e-5):
35 | x = x.clamp(min=0, max=1)
36 | x1 = x.clamp(min=eps)
37 | x2 = (1 - x).clamp(min=eps)
38 | return torch.log(x1 / x2)
39 |
40 |
41 | def multi_scale_deformable_attn_pytorch(value: torch.Tensor, value_spatial_shapes: torch.Tensor,
42 | sampling_locations: torch.Tensor,
43 | attention_weights: torch.Tensor) -> torch.Tensor:
44 | """
45 | Multi-scale deformable attention.
46 | https://github.com/IDEA-Research/detrex/blob/main/detrex/layers/multi_scale_deform_attn.py
47 | """
48 |
49 | bs, _, num_heads, embed_dims = value.shape
50 | _, num_queries, num_heads, num_levels, num_points, _ = sampling_locations.shape
51 | value_list = value.split([H_ * W_ for H_, W_ in value_spatial_shapes], dim=1)
52 | sampling_grids = 2 * sampling_locations - 1
53 | sampling_value_list = []
54 | for level, (H_, W_) in enumerate(value_spatial_shapes):
55 | # bs, H_*W_, num_heads, embed_dims ->
56 | # bs, H_*W_, num_heads*embed_dims ->
57 | # bs, num_heads*embed_dims, H_*W_ ->
58 | # bs*num_heads, embed_dims, H_, W_
59 | value_l_ = (value_list[level].flatten(2).transpose(1, 2).reshape(bs * num_heads, embed_dims, H_, W_))
60 | # bs, num_queries, num_heads, num_points, 2 ->
61 | # bs, num_heads, num_queries, num_points, 2 ->
62 | # bs*num_heads, num_queries, num_points, 2
63 | sampling_grid_l_ = sampling_grids[:, :, :, level].transpose(1, 2).flatten(0, 1)
64 | # bs*num_heads, embed_dims, num_queries, num_points
65 | sampling_value_l_ = F.grid_sample(value_l_,
66 | sampling_grid_l_,
67 | mode='bilinear',
68 | padding_mode='zeros',
69 | align_corners=False)
70 | sampling_value_list.append(sampling_value_l_)
71 | # (bs, num_queries, num_heads, num_levels, num_points) ->
72 | # (bs, num_heads, num_queries, num_levels, num_points) ->
73 | # (bs, num_heads, 1, num_queries, num_levels*num_points)
74 | attention_weights = attention_weights.transpose(1, 2).reshape(bs * num_heads, 1, num_queries,
75 | num_levels * num_points)
76 | output = ((torch.stack(sampling_value_list, dim=-2).flatten(-2) * attention_weights).sum(-1).view(
77 | bs, num_heads * embed_dims, num_queries))
78 | return output.transpose(1, 2).contiguous()
79 |
--------------------------------------------------------------------------------
/ultralytics/trackers/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .bot_sort import BOTSORT
4 | from .byte_tracker import BYTETracker
5 | from .track import register_tracker
6 |
7 | __all__ = 'register_tracker', 'BOTSORT', 'BYTETracker' # allow simpler import
8 |
--------------------------------------------------------------------------------
/ultralytics/trackers/basetrack.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from collections import OrderedDict
4 |
5 | import numpy as np
6 |
7 |
8 | class TrackState:
9 | """Enumeration of possible object tracking states."""
10 |
11 | New = 0
12 | Tracked = 1
13 | Lost = 2
14 | Removed = 3
15 |
16 |
17 | class BaseTrack:
18 | """Base class for object tracking, handling basic track attributes and operations."""
19 |
20 | _count = 0
21 |
22 | track_id = 0
23 | is_activated = False
24 | state = TrackState.New
25 |
26 | history = OrderedDict()
27 | features = []
28 | curr_feature = None
29 | score = 0
30 | start_frame = 0
31 | frame_id = 0
32 | time_since_update = 0
33 |
34 | # Multi-camera
35 | location = (np.inf, np.inf)
36 |
37 | @property
38 | def end_frame(self):
39 | """Return the last frame ID of the track."""
40 | return self.frame_id
41 |
42 | @staticmethod
43 | def next_id():
44 | """Increment and return the global track ID counter."""
45 | BaseTrack._count += 1
46 | return BaseTrack._count
47 |
48 | def activate(self, *args):
49 | """Activate the track with the provided arguments."""
50 | raise NotImplementedError
51 |
52 | def predict(self):
53 | """Predict the next state of the track."""
54 | raise NotImplementedError
55 |
56 | def update(self, *args, **kwargs):
57 | """Update the track with new observations."""
58 | raise NotImplementedError
59 |
60 | def mark_lost(self):
61 | """Mark the track as lost."""
62 | self.state = TrackState.Lost
63 |
64 | def mark_removed(self):
65 | """Mark the track as removed."""
66 | self.state = TrackState.Removed
67 |
68 | @staticmethod
69 | def reset_id():
70 | """Reset the global track ID counter."""
71 | BaseTrack._count = 0
72 |
--------------------------------------------------------------------------------
/ultralytics/trackers/track.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from functools import partial
4 |
5 | import torch
6 |
7 | from ultralytics.utils import IterableSimpleNamespace, yaml_load
8 | from ultralytics.utils.checks import check_yaml
9 |
10 | from .bot_sort import BOTSORT
11 | from .byte_tracker import BYTETracker
12 |
13 | TRACKER_MAP = {'bytetrack': BYTETracker, 'botsort': BOTSORT}
14 |
15 |
16 | def on_predict_start(predictor, persist=False):
17 | """
18 | Initialize trackers for object tracking during prediction.
19 |
20 | Args:
21 | predictor (object): The predictor object to initialize trackers for.
22 | persist (bool, optional): Whether to persist the trackers if they already exist. Defaults to False.
23 |
24 | Raises:
25 | AssertionError: If the tracker_type is not 'bytetrack' or 'botsort'.
26 | """
27 | if hasattr(predictor, 'trackers') and persist:
28 | return
29 | tracker = check_yaml(predictor.args.tracker)
30 | cfg = IterableSimpleNamespace(**yaml_load(tracker))
31 | assert cfg.tracker_type in ['bytetrack', 'botsort'], \
32 | f"Only support 'bytetrack' and 'botsort' for now, but got '{cfg.tracker_type}'"
33 | trackers = []
34 | for _ in range(predictor.dataset.bs):
35 | tracker = TRACKER_MAP[cfg.tracker_type](args=cfg, frame_rate=30)
36 | trackers.append(tracker)
37 | predictor.trackers = trackers
38 |
39 |
40 | def on_predict_postprocess_end(predictor):
41 | """Postprocess detected boxes and update with object tracking."""
42 | bs = predictor.dataset.bs
43 | im0s = predictor.batch[1]
44 | for i in range(bs):
45 | det = predictor.results[i].boxes.cpu().numpy()
46 | if len(det) == 0:
47 | continue
48 | tracks = predictor.trackers[i].update(det, im0s[i])
49 | if len(tracks) == 0:
50 | continue
51 | idx = tracks[:, -1].astype(int)
52 | predictor.results[i] = predictor.results[i][idx]
53 | predictor.results[i].update(boxes=torch.as_tensor(tracks[:, :-1]))
54 |
55 |
56 | def register_tracker(model, persist):
57 | """
58 | Register tracking callbacks to the model for object tracking during prediction.
59 |
60 | Args:
61 | model (object): The model object to register tracking callbacks for.
62 | persist (bool): Whether to persist the trackers if they already exist.
63 |
64 | """
65 | model.add_callback('on_predict_start', partial(on_predict_start, persist=persist))
66 | model.add_callback('on_predict_postprocess_end', on_predict_postprocess_end)
67 |
--------------------------------------------------------------------------------
/ultralytics/utils/autobatch.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | Functions for estimating the best YOLO batch size to use a fraction of the available CUDA memory in PyTorch.
4 | """
5 |
6 | from copy import deepcopy
7 |
8 | import numpy as np
9 | import torch
10 |
11 | from ultralytics.utils import DEFAULT_CFG, LOGGER, colorstr
12 | from ultralytics.utils.torch_utils import profile
13 |
14 |
15 | def check_train_batch_size(model, imgsz=640, amp=True):
16 | """
17 | Check YOLO training batch size using the autobatch() function.
18 |
19 | Args:
20 | model (torch.nn.Module): YOLO model to check batch size for.
21 | imgsz (int): Image size used for training.
22 | amp (bool): If True, use automatic mixed precision (AMP) for training.
23 |
24 | Returns:
25 | (int): Optimal batch size computed using the autobatch() function.
26 | """
27 |
28 | with torch.cuda.amp.autocast(amp):
29 | return autobatch(deepcopy(model).train(), imgsz) # compute optimal batch size
30 |
31 |
32 | def autobatch(model, imgsz=640, fraction=0.67, batch_size=DEFAULT_CFG.batch):
33 | """
34 | Automatically estimate the best YOLO batch size to use a fraction of the available CUDA memory.
35 |
36 | Args:
37 | model (torch.nn.module): YOLO model to compute batch size for.
38 | imgsz (int, optional): The image size used as input for the YOLO model. Defaults to 640.
39 | fraction (float, optional): The fraction of available CUDA memory to use. Defaults to 0.67.
40 | batch_size (int, optional): The default batch size to use if an error is detected. Defaults to 16.
41 |
42 | Returns:
43 | (int): The optimal batch size.
44 | """
45 |
46 | # Check device
47 | prefix = colorstr('AutoBatch: ')
48 | LOGGER.info(f'{prefix}Computing optimal batch size for imgsz={imgsz}')
49 | device = next(model.parameters()).device # get model device
50 | if device.type == 'cpu':
51 | LOGGER.info(f'{prefix}CUDA not detected, using default CPU batch-size {batch_size}')
52 | return batch_size
53 | if torch.backends.cudnn.benchmark:
54 | LOGGER.info(f'{prefix} ⚠️ Requires torch.backends.cudnn.benchmark=False, using default batch-size {batch_size}')
55 | return batch_size
56 |
57 | # Inspect CUDA memory
58 | gb = 1 << 30 # bytes to GiB (1024 ** 3)
59 | d = str(device).upper() # 'CUDA:0'
60 | properties = torch.cuda.get_device_properties(device) # device properties
61 | t = properties.total_memory / gb # GiB total
62 | r = torch.cuda.memory_reserved(device) / gb # GiB reserved
63 | a = torch.cuda.memory_allocated(device) / gb # GiB allocated
64 | f = t - (r + a) # GiB free
65 | LOGGER.info(f'{prefix}{d} ({properties.name}) {t:.2f}G total, {r:.2f}G reserved, {a:.2f}G allocated, {f:.2f}G free')
66 |
67 | # Profile batch sizes
68 | batch_sizes = [1, 2, 4, 8, 16]
69 | try:
70 | img = [torch.empty(b, 3, imgsz, imgsz) for b in batch_sizes]
71 | results = profile(img, model, n=3, device=device)
72 |
73 | # Fit a solution
74 | y = [x[2] for x in results if x] # memory [2]
75 | p = np.polyfit(batch_sizes[:len(y)], y, deg=1) # first degree polynomial fit
76 | b = int((f * fraction - p[1]) / p[0]) # y intercept (optimal batch size)
77 | if None in results: # some sizes failed
78 | i = results.index(None) # first fail index
79 | if b >= batch_sizes[i]: # y intercept above failure point
80 | b = batch_sizes[max(i - 1, 0)] # select prior safe point
81 | if b < 1 or b > 1024: # b outside of safe range
82 | b = batch_size
83 | LOGGER.info(f'{prefix}WARNING ⚠️ CUDA anomaly detected, using default batch-size {batch_size}.')
84 |
85 | fraction = (np.polyval(p, b) + r + a) / t # actual fraction predicted
86 | LOGGER.info(f'{prefix}Using batch-size {b} for {d} {t * fraction:.2f}G/{t:.2f}G ({fraction * 100:.0f}%) ✅')
87 | return b
88 | except Exception as e:
89 | LOGGER.warning(f'{prefix}WARNING ⚠️ error detected: {e}, using default batch-size {batch_size}.')
90 | return batch_size
91 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from .base import add_integration_callbacks, default_callbacks, get_default_callbacks
4 |
5 | __all__ = 'add_integration_callbacks', 'default_callbacks', 'get_default_callbacks'
6 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/dvc.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, GPL-3.0 license
2 | import os
3 |
4 | import pkg_resources as pkg
5 |
6 | from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
7 | from ultralytics.utils.torch_utils import model_info_for_loggers
8 |
9 | try:
10 | from importlib.metadata import version
11 |
12 | import dvclive
13 |
14 | assert not TESTS_RUNNING # do not log pytest
15 | assert SETTINGS['dvc'] is True # verify integration is enabled
16 |
17 | ver = version('dvclive')
18 | if pkg.parse_version(ver) < pkg.parse_version('2.11.0'):
19 | LOGGER.debug(f'DVCLive is detected but version {ver} is incompatible (>=2.11 required).')
20 | dvclive = None # noqa: F811
21 | except (ImportError, AssertionError, TypeError):
22 | dvclive = None
23 |
24 | # DVCLive logger instance
25 | live = None
26 | _processed_plots = {}
27 |
28 | # `on_fit_epoch_end` is called on final validation (probably need to be fixed)
29 | # for now this is the way we distinguish final evaluation of the best model vs
30 | # last epoch validation
31 | _training_epoch = False
32 |
33 |
34 | def _logger_disabled():
35 | return os.getenv('ULTRALYTICS_DVC_DISABLED', 'false').lower() == 'true'
36 |
37 |
38 | def _log_images(image_path, prefix=''):
39 | if live:
40 | live.log_image(os.path.join(prefix, image_path.name), image_path)
41 |
42 |
43 | def _log_plots(plots, prefix=''):
44 | for name, params in plots.items():
45 | timestamp = params['timestamp']
46 | if _processed_plots.get(name) != timestamp:
47 | _log_images(name, prefix)
48 | _processed_plots[name] = timestamp
49 |
50 |
51 | def _log_confusion_matrix(validator):
52 | targets = []
53 | preds = []
54 | matrix = validator.confusion_matrix.matrix
55 | names = list(validator.names.values())
56 | if validator.confusion_matrix.task == 'detect':
57 | names += ['background']
58 |
59 | for ti, pred in enumerate(matrix.T.astype(int)):
60 | for pi, num in enumerate(pred):
61 | targets.extend([names[ti]] * num)
62 | preds.extend([names[pi]] * num)
63 |
64 | live.log_sklearn_plot('confusion_matrix', targets, preds, name='cf.json', normalized=True)
65 |
66 |
67 | def on_pretrain_routine_start(trainer):
68 | try:
69 | global live
70 | if not _logger_disabled():
71 | live = dvclive.Live(save_dvc_exp=True, cache_images=True)
72 | LOGGER.info(
73 | 'DVCLive is detected and auto logging is enabled (can be disabled with `ULTRALYTICS_DVC_DISABLED=true`).'
74 | )
75 | else:
76 | LOGGER.debug('DVCLive is detected and auto logging is disabled via `ULTRALYTICS_DVC_DISABLED`.')
77 | live = None
78 | except Exception as e:
79 | LOGGER.warning(f'WARNING ⚠️ DVCLive installed but not initialized correctly, not logging this run. {e}')
80 |
81 |
82 | def on_pretrain_routine_end(trainer):
83 | _log_plots(trainer.plots, 'train')
84 |
85 |
86 | def on_train_start(trainer):
87 | if live:
88 | live.log_params(trainer.args)
89 |
90 |
91 | def on_train_epoch_start(trainer):
92 | global _training_epoch
93 | _training_epoch = True
94 |
95 |
96 | def on_fit_epoch_end(trainer):
97 | global _training_epoch
98 | if live and _training_epoch:
99 | all_metrics = {**trainer.label_loss_items(trainer.tloss, prefix='train'), **trainer.metrics, **trainer.lr}
100 | for metric, value in all_metrics.items():
101 | live.log_metric(metric, value)
102 |
103 | if trainer.epoch == 0:
104 | for metric, value in model_info_for_loggers(trainer).items():
105 | live.log_metric(metric, value, plot=False)
106 |
107 | _log_plots(trainer.plots, 'train')
108 | _log_plots(trainer.validator.plots, 'val')
109 |
110 | live.next_step()
111 | _training_epoch = False
112 |
113 |
114 | def on_train_end(trainer):
115 | if live:
116 | # At the end log the best metrics. It runs validator on the best model internally.
117 | all_metrics = {**trainer.label_loss_items(trainer.tloss, prefix='train'), **trainer.metrics, **trainer.lr}
118 | for metric, value in all_metrics.items():
119 | live.log_metric(metric, value, plot=False)
120 |
121 | _log_plots(trainer.plots, 'val')
122 | _log_plots(trainer.validator.plots, 'val')
123 | _log_confusion_matrix(trainer.validator)
124 |
125 | if trainer.best.exists():
126 | live.log_artifact(trainer.best, copy=True, type='model')
127 |
128 | live.end()
129 |
130 |
131 | callbacks = {
132 | 'on_pretrain_routine_start': on_pretrain_routine_start,
133 | 'on_pretrain_routine_end': on_pretrain_routine_end,
134 | 'on_train_start': on_train_start,
135 | 'on_train_epoch_start': on_train_epoch_start,
136 | 'on_fit_epoch_end': on_fit_epoch_end,
137 | 'on_train_end': on_train_end} if dvclive else {}
138 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/hub.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import json
4 | from time import time
5 |
6 | from ultralytics.hub.utils import HUB_WEB_ROOT, PREFIX, events
7 | from ultralytics.utils import LOGGER, SETTINGS
8 | from ultralytics.utils.torch_utils import model_info_for_loggers
9 |
10 |
11 | def on_pretrain_routine_end(trainer):
12 | """Logs info before starting timer for upload rate limit."""
13 | session = getattr(trainer, 'hub_session', None)
14 | if session:
15 | # Start timer for upload rate limit
16 | LOGGER.info(f'{PREFIX}View model at {HUB_WEB_ROOT}/models/{session.model_id} 🚀')
17 | session.timers = {'metrics': time(), 'ckpt': time()} # start timer on session.rate_limit
18 |
19 |
20 | def on_fit_epoch_end(trainer):
21 | """Uploads training progress metrics at the end of each epoch."""
22 | session = getattr(trainer, 'hub_session', None)
23 | if session:
24 | # Upload metrics after val end
25 | all_plots = {**trainer.label_loss_items(trainer.tloss, prefix='train'), **trainer.metrics}
26 | if trainer.epoch == 0:
27 | all_plots = {**all_plots, **model_info_for_loggers(trainer)}
28 | session.metrics_queue[trainer.epoch] = json.dumps(all_plots)
29 | if time() - session.timers['metrics'] > session.rate_limits['metrics']:
30 | session.upload_metrics()
31 | session.timers['metrics'] = time() # reset timer
32 | session.metrics_queue = {} # reset queue
33 |
34 |
35 | def on_model_save(trainer):
36 | """Saves checkpoints to Ultralytics HUB with rate limiting."""
37 | session = getattr(trainer, 'hub_session', None)
38 | if session:
39 | # Upload checkpoints with rate limiting
40 | is_best = trainer.best_fitness == trainer.fitness
41 | if time() - session.timers['ckpt'] > session.rate_limits['ckpt']:
42 | LOGGER.info(f'{PREFIX}Uploading checkpoint {HUB_WEB_ROOT}/models/{session.model_id}')
43 | session.upload_model(trainer.epoch, trainer.last, is_best)
44 | session.timers['ckpt'] = time() # reset timer
45 |
46 |
47 | def on_train_end(trainer):
48 | """Upload final model and metrics to Ultralytics HUB at the end of training."""
49 | session = getattr(trainer, 'hub_session', None)
50 | if session:
51 | # Upload final model and metrics with exponential standoff
52 | LOGGER.info(f'{PREFIX}Syncing final model...')
53 | session.upload_model(trainer.epoch, trainer.best, map=trainer.metrics.get('metrics/mAP50-95(B)', 0), final=True)
54 | session.alive = False # stop heartbeats
55 | LOGGER.info(f'{PREFIX}Done ✅\n'
56 | f'{PREFIX}View model at {HUB_WEB_ROOT}/models/{session.model_id} 🚀')
57 |
58 |
59 | def on_train_start(trainer):
60 | """Run events on train start."""
61 | events(trainer.args)
62 |
63 |
64 | def on_val_start(validator):
65 | """Runs events on validation start."""
66 | events(validator.args)
67 |
68 |
69 | def on_predict_start(predictor):
70 | """Run events on predict start."""
71 | events(predictor.args)
72 |
73 |
74 | def on_export_start(exporter):
75 | """Run events on export start."""
76 | events(exporter.args)
77 |
78 |
79 | callbacks = {
80 | 'on_pretrain_routine_end': on_pretrain_routine_end,
81 | 'on_fit_epoch_end': on_fit_epoch_end,
82 | 'on_model_save': on_model_save,
83 | 'on_train_end': on_train_end,
84 | 'on_train_start': on_train_start,
85 | 'on_val_start': on_val_start,
86 | 'on_predict_start': on_predict_start,
87 | 'on_export_start': on_export_start} if SETTINGS['hub'] is True else {} # verify enabled
88 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/mlflow.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import os
4 | import re
5 | from pathlib import Path
6 |
7 | from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
8 |
9 | try:
10 | import mlflow
11 |
12 | assert not TESTS_RUNNING # do not log pytest
13 | assert hasattr(mlflow, '__version__') # verify package is not directory
14 | assert SETTINGS['mlflow'] is True # verify integration is enabled
15 | except (ImportError, AssertionError):
16 | mlflow = None
17 |
18 |
19 | def on_pretrain_routine_end(trainer):
20 | """Logs training parameters to MLflow."""
21 | global mlflow, run, run_id, experiment_name
22 |
23 | if os.environ.get('MLFLOW_TRACKING_URI') is None:
24 | mlflow = None
25 |
26 | if mlflow:
27 | mlflow_location = os.environ['MLFLOW_TRACKING_URI'] # "http://192.168.xxx.xxx:5000"
28 | mlflow.set_tracking_uri(mlflow_location)
29 |
30 | experiment_name = os.environ.get('MLFLOW_EXPERIMENT_NAME') or trainer.args.project or '/Shared/YOLOv8'
31 | run_name = os.environ.get('MLFLOW_RUN') or trainer.args.name
32 | experiment = mlflow.get_experiment_by_name(experiment_name)
33 | if experiment is None:
34 | mlflow.create_experiment(experiment_name)
35 | mlflow.set_experiment(experiment_name)
36 |
37 | prefix = colorstr('MLFlow: ')
38 | try:
39 | run, active_run = mlflow, mlflow.active_run()
40 | if not active_run:
41 | active_run = mlflow.start_run(experiment_id=experiment.experiment_id, run_name=run_name)
42 | run_id = active_run.info.run_id
43 | LOGGER.info(f'{prefix}Using run_id({run_id}) at {mlflow_location}')
44 | run.log_params(vars(trainer.model.args))
45 | except Exception as err:
46 | LOGGER.error(f'{prefix}Failing init - {repr(err)}')
47 | LOGGER.warning(f'{prefix}Continuing without Mlflow')
48 |
49 |
50 | def on_fit_epoch_end(trainer):
51 | """Logs training metrics to Mlflow."""
52 | if mlflow:
53 | metrics_dict = {f"{re.sub('[()]', '', k)}": float(v) for k, v in trainer.metrics.items()}
54 | run.log_metrics(metrics=metrics_dict, step=trainer.epoch)
55 |
56 |
57 | def on_train_end(trainer):
58 | """Called at end of train loop to log model artifact info."""
59 | if mlflow:
60 | root_dir = Path(__file__).resolve().parents[3]
61 | run.log_artifact(trainer.last)
62 | run.log_artifact(trainer.best)
63 | run.pyfunc.log_model(artifact_path=experiment_name,
64 | code_path=[str(root_dir)],
65 | artifacts={'model_path': str(trainer.save_dir)},
66 | python_model=run.pyfunc.PythonModel())
67 |
68 |
69 | callbacks = {
70 | 'on_pretrain_routine_end': on_pretrain_routine_end,
71 | 'on_fit_epoch_end': on_fit_epoch_end,
72 | 'on_train_end': on_train_end} if mlflow else {}
73 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/neptune.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import matplotlib.image as mpimg
4 | import matplotlib.pyplot as plt
5 |
6 | from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
7 | from ultralytics.utils.torch_utils import model_info_for_loggers
8 |
9 | try:
10 | import neptune
11 | from neptune.types import File
12 |
13 | assert not TESTS_RUNNING # do not log pytest
14 | assert hasattr(neptune, '__version__')
15 | assert SETTINGS['neptune'] is True # verify integration is enabled
16 | except (ImportError, AssertionError):
17 | neptune = None
18 |
19 | run = None # NeptuneAI experiment logger instance
20 |
21 |
22 | def _log_scalars(scalars, step=0):
23 | """Log scalars to the NeptuneAI experiment logger."""
24 | if run:
25 | for k, v in scalars.items():
26 | run[k].append(value=v, step=step)
27 |
28 |
29 | def _log_images(imgs_dict, group=''):
30 | """Log scalars to the NeptuneAI experiment logger."""
31 | if run:
32 | for k, v in imgs_dict.items():
33 | run[f'{group}/{k}'].upload(File(v))
34 |
35 |
36 | def _log_plot(title, plot_path):
37 | """Log plots to the NeptuneAI experiment logger."""
38 | """
39 | Log image as plot in the plot section of NeptuneAI
40 |
41 | arguments:
42 | title (str) Title of the plot
43 | plot_path (PosixPath or str) Path to the saved image file
44 | """
45 | img = mpimg.imread(plot_path)
46 | fig = plt.figure()
47 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect='auto', xticks=[], yticks=[]) # no ticks
48 | ax.imshow(img)
49 | run[f'Plots/{title}'].upload(fig)
50 |
51 |
52 | def on_pretrain_routine_start(trainer):
53 | """Callback function called before the training routine starts."""
54 | try:
55 | global run
56 | run = neptune.init_run(project=trainer.args.project or 'YOLOv8', name=trainer.args.name, tags=['YOLOv8'])
57 | run['Configuration/Hyperparameters'] = {k: '' if v is None else v for k, v in vars(trainer.args).items()}
58 | except Exception as e:
59 | LOGGER.warning(f'WARNING ⚠️ NeptuneAI installed but not initialized correctly, not logging this run. {e}')
60 |
61 |
62 | def on_train_epoch_end(trainer):
63 | """Callback function called at end of each training epoch."""
64 | _log_scalars(trainer.label_loss_items(trainer.tloss, prefix='train'), trainer.epoch + 1)
65 | _log_scalars(trainer.lr, trainer.epoch + 1)
66 | if trainer.epoch == 1:
67 | _log_images({f.stem: str(f) for f in trainer.save_dir.glob('train_batch*.jpg')}, 'Mosaic')
68 |
69 |
70 | def on_fit_epoch_end(trainer):
71 | """Callback function called at end of each fit (train+val) epoch."""
72 | if run and trainer.epoch == 0:
73 | run['Configuration/Model'] = model_info_for_loggers(trainer)
74 | _log_scalars(trainer.metrics, trainer.epoch + 1)
75 |
76 |
77 | def on_val_end(validator):
78 | """Callback function called at end of each validation."""
79 | if run:
80 | # Log val_labels and val_pred
81 | _log_images({f.stem: str(f) for f in validator.save_dir.glob('val*.jpg')}, 'Validation')
82 |
83 |
84 | def on_train_end(trainer):
85 | """Callback function called at end of training."""
86 | if run:
87 | # Log final results, CM matrix + PR plots
88 | files = [
89 | 'results.png', 'confusion_matrix.png', 'confusion_matrix_normalized.png',
90 | *(f'{x}_curve.png' for x in ('F1', 'PR', 'P', 'R'))]
91 | files = [(trainer.save_dir / f) for f in files if (trainer.save_dir / f).exists()] # filter
92 | for f in files:
93 | _log_plot(title=f.stem, plot_path=f)
94 | # Log the final model
95 | run[f'weights/{trainer.args.name or trainer.args.task}/{str(trainer.best.name)}'].upload(File(str(
96 | trainer.best)))
97 |
98 |
99 | callbacks = {
100 | 'on_pretrain_routine_start': on_pretrain_routine_start,
101 | 'on_train_epoch_end': on_train_epoch_end,
102 | 'on_fit_epoch_end': on_fit_epoch_end,
103 | 'on_val_end': on_val_end,
104 | 'on_train_end': on_train_end} if neptune else {}
105 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/raytune.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.utils import SETTINGS
4 |
5 | try:
6 | import ray
7 | from ray import tune
8 | from ray.air import session
9 |
10 | assert SETTINGS['raytune'] is True # verify integration is enabled
11 | except (ImportError, AssertionError):
12 | tune = None
13 |
14 |
15 | def on_fit_epoch_end(trainer):
16 | """Sends training metrics to Ray Tune at end of each epoch."""
17 | if ray.tune.is_session_enabled():
18 | metrics = trainer.metrics
19 | metrics['epoch'] = trainer.epoch
20 | session.report(metrics)
21 |
22 |
23 | callbacks = {
24 | 'on_fit_epoch_end': on_fit_epoch_end, } if tune else {}
25 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/tensorboard.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
4 |
5 | try:
6 | from torch.utils.tensorboard import SummaryWriter
7 |
8 | assert not TESTS_RUNNING # do not log pytest
9 | assert SETTINGS['tensorboard'] is True # verify integration is enabled
10 |
11 | # TypeError for handling 'Descriptors cannot not be created directly.' protobuf errors in Windows
12 | except (ImportError, AssertionError, TypeError):
13 | SummaryWriter = None
14 |
15 | writer = None # TensorBoard SummaryWriter instance
16 |
17 |
18 | def _log_scalars(scalars, step=0):
19 | """Logs scalar values to TensorBoard."""
20 | if writer:
21 | for k, v in scalars.items():
22 | writer.add_scalar(k, v, step)
23 |
24 |
25 | def on_pretrain_routine_start(trainer):
26 | """Initialize TensorBoard logging with SummaryWriter."""
27 | if SummaryWriter:
28 | try:
29 | global writer
30 | writer = SummaryWriter(str(trainer.save_dir))
31 | prefix = colorstr('TensorBoard: ')
32 | LOGGER.info(f"{prefix}Start with 'tensorboard --logdir {trainer.save_dir}', view at http://localhost:6006/")
33 | except Exception as e:
34 | LOGGER.warning(f'WARNING ⚠️ TensorBoard not initialized correctly, not logging this run. {e}')
35 |
36 |
37 | def on_batch_end(trainer):
38 | """Logs scalar statistics at the end of a training batch."""
39 | _log_scalars(trainer.label_loss_items(trainer.tloss, prefix='train'), trainer.epoch + 1)
40 |
41 |
42 | def on_fit_epoch_end(trainer):
43 | """Logs epoch metrics at end of training epoch."""
44 | _log_scalars(trainer.metrics, trainer.epoch + 1)
45 |
46 |
47 | callbacks = {
48 | 'on_pretrain_routine_start': on_pretrain_routine_start,
49 | 'on_fit_epoch_end': on_fit_epoch_end,
50 | 'on_batch_end': on_batch_end}
51 |
--------------------------------------------------------------------------------
/ultralytics/utils/callbacks/wb.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | from ultralytics.utils import SETTINGS, TESTS_RUNNING
3 | from ultralytics.utils.torch_utils import model_info_for_loggers
4 |
5 | try:
6 | import wandb as wb
7 |
8 | assert hasattr(wb, '__version__')
9 | assert not TESTS_RUNNING # do not log pytest
10 | assert SETTINGS['wandb'] is True # verify integration is enabled
11 | except (ImportError, AssertionError):
12 | wb = None
13 |
14 | _processed_plots = {}
15 |
16 |
17 | def _log_plots(plots, step):
18 | for name, params in plots.items():
19 | timestamp = params['timestamp']
20 | if _processed_plots.get(name) != timestamp:
21 | wb.run.log({name.stem: wb.Image(str(name))}, step=step)
22 | _processed_plots[name] = timestamp
23 |
24 |
25 | def on_pretrain_routine_start(trainer):
26 | """Initiate and start project if module is present."""
27 | wb.run or wb.init(project=trainer.args.project or 'YOLOv8', name=trainer.args.name, config=vars(trainer.args))
28 |
29 |
30 | def on_fit_epoch_end(trainer):
31 | """Logs training metrics and model information at the end of an epoch."""
32 | wb.run.log(trainer.metrics, step=trainer.epoch + 1)
33 | _log_plots(trainer.plots, step=trainer.epoch + 1)
34 | _log_plots(trainer.validator.plots, step=trainer.epoch + 1)
35 | if trainer.epoch == 0:
36 | wb.run.log(model_info_for_loggers(trainer), step=trainer.epoch + 1)
37 |
38 |
39 | def on_train_epoch_end(trainer):
40 | """Log metrics and save images at the end of each training epoch."""
41 | wb.run.log(trainer.label_loss_items(trainer.tloss, prefix='train'), step=trainer.epoch + 1)
42 | wb.run.log(trainer.lr, step=trainer.epoch + 1)
43 | if trainer.epoch == 1:
44 | _log_plots(trainer.plots, step=trainer.epoch + 1)
45 |
46 |
47 | def on_train_end(trainer):
48 | """Save the best model as an artifact at end of training."""
49 | _log_plots(trainer.validator.plots, step=trainer.epoch + 1)
50 | _log_plots(trainer.plots, step=trainer.epoch + 1)
51 | art = wb.Artifact(type='model', name=f'run_{wb.run.id}_model')
52 | if trainer.best.exists():
53 | art.add_file(trainer.best)
54 | wb.run.log_artifact(art, aliases=['best'])
55 |
56 |
57 | callbacks = {
58 | 'on_pretrain_routine_start': on_pretrain_routine_start,
59 | 'on_train_epoch_end': on_train_epoch_end,
60 | 'on_fit_epoch_end': on_fit_epoch_end,
61 | 'on_train_end': on_train_end} if wb else {}
62 |
--------------------------------------------------------------------------------
/ultralytics/utils/dist.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | import os
4 | import re
5 | import shutil
6 | import socket
7 | import sys
8 | import tempfile
9 | from pathlib import Path
10 |
11 | from . import USER_CONFIG_DIR
12 | from .torch_utils import TORCH_1_9
13 |
14 |
15 | def find_free_network_port() -> int:
16 | """Finds a free port on localhost.
17 |
18 | It is useful in single-node training when we don't want to connect to a real main node but have to set the
19 | `MASTER_PORT` environment variable.
20 | """
21 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
22 | s.bind(('127.0.0.1', 0))
23 | return s.getsockname()[1] # port
24 |
25 |
26 | def generate_ddp_file(trainer):
27 | """Generates a DDP file and returns its file name."""
28 | module, name = f'{trainer.__class__.__module__}.{trainer.__class__.__name__}'.rsplit('.', 1)
29 |
30 | content = f'''overrides = {vars(trainer.args)} \nif __name__ == "__main__":
31 | from {module} import {name}
32 | from ultralytics.utils import DEFAULT_CFG_DICT
33 |
34 | cfg = DEFAULT_CFG_DICT.copy()
35 | cfg.update(save_dir='') # handle the extra key 'save_dir'
36 | trainer = {name}(cfg=cfg, overrides=overrides)
37 | trainer.train()'''
38 | (USER_CONFIG_DIR / 'DDP').mkdir(exist_ok=True)
39 | with tempfile.NamedTemporaryFile(prefix='_temp_',
40 | suffix=f'{id(trainer)}.py',
41 | mode='w+',
42 | encoding='utf-8',
43 | dir=USER_CONFIG_DIR / 'DDP',
44 | delete=False) as file:
45 | file.write(content)
46 | return file.name
47 |
48 |
49 | def generate_ddp_command(world_size, trainer):
50 | """Generates and returns command for distributed training."""
51 | import __main__ # noqa local import to avoid https://github.com/Lightning-AI/lightning/issues/15218
52 | if not trainer.resume:
53 | shutil.rmtree(trainer.save_dir) # remove the save_dir
54 | file = str(Path(sys.argv[0]).resolve())
55 | safe_pattern = re.compile(r'^[a-zA-Z0-9_. /\\-]{1,128}$') # allowed characters and maximum of 100 characters
56 | if not (safe_pattern.match(file) and Path(file).exists() and file.endswith('.py')): # using CLI
57 | file = generate_ddp_file(trainer)
58 | dist_cmd = 'torch.distributed.run' if TORCH_1_9 else 'torch.distributed.launch'
59 | port = find_free_network_port()
60 | cmd = [sys.executable, '-m', dist_cmd, '--nproc_per_node', f'{world_size}', '--master_port', f'{port}', file]
61 | return cmd, file
62 |
63 |
64 | def ddp_cleanup(trainer, file):
65 | """Delete temp file if created."""
66 | if f'{id(trainer)}.py' in file: # if temp_file suffix in file
67 | os.remove(file)
68 |
--------------------------------------------------------------------------------
/ultralytics/utils/errors.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from ultralytics.utils import emojis
4 |
5 |
6 | class HUBModelError(Exception):
7 |
8 | def __init__(self, message='Model not found. Please check model URL and try again.'):
9 | """Create an exception for when a model is not found."""
10 | super().__init__(emojis(message))
11 |
--------------------------------------------------------------------------------
/ultralytics/utils/patches.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 | """
3 | Monkey patches to update/extend functionality of existing functions
4 | """
5 |
6 | from pathlib import Path
7 |
8 | import cv2
9 | import numpy as np
10 | import torch
11 |
12 | # OpenCV Multilanguage-friendly functions ------------------------------------------------------------------------------
13 | _imshow = cv2.imshow # copy to avoid recursion errors
14 |
15 |
16 | def imread(filename, flags=cv2.IMREAD_COLOR):
17 | return cv2.imdecode(np.fromfile(filename, np.uint8), flags)
18 |
19 |
20 | def imwrite(filename, img):
21 | try:
22 | cv2.imencode(Path(filename).suffix, img)[1].tofile(filename)
23 | return True
24 | except Exception:
25 | return False
26 |
27 |
28 | def imshow(path, im):
29 | _imshow(path.encode('unicode_escape').decode(), im)
30 |
31 |
32 | # PyTorch functions ----------------------------------------------------------------------------------------------------
33 | _torch_save = torch.save # copy to avoid recursion errors
34 |
35 |
36 | def torch_save(*args, **kwargs):
37 | """Use dill (if exists) to serialize the lambda functions where pickle does not do this."""
38 | try:
39 | import dill as pickle
40 | except ImportError:
41 | import pickle
42 |
43 | if 'pickle_module' not in kwargs:
44 | kwargs['pickle_module'] = pickle
45 | return _torch_save(*args, **kwargs)
46 |
--------------------------------------------------------------------------------
/ultralytics/yolo/__init__.py:
--------------------------------------------------------------------------------
1 | # Ultralytics YOLO 🚀, AGPL-3.0 license
2 |
3 | from . import v8
4 |
5 | __all__ = 'v8', # tuple or list
6 |
--------------------------------------------------------------------------------
/ultralytics/yolo/cfg/__init__.py:
--------------------------------------------------------------------------------
1 | import importlib
2 | import sys
3 |
4 | from ultralytics.utils import LOGGER
5 |
6 | # Set modules in sys.modules under their old name
7 | sys.modules['ultralytics.yolo.cfg'] = importlib.import_module('ultralytics.cfg')
8 |
9 | LOGGER.warning("WARNING ⚠️ 'ultralytics.yolo.cfg' is deprecated since '8.0.136' and will be removed in '8.1.0'. "
10 | "Please use 'ultralytics.cfg' instead.")
11 |
--------------------------------------------------------------------------------
/ultralytics/yolo/data/__init__.py:
--------------------------------------------------------------------------------
1 | import importlib
2 | import sys
3 |
4 | from ultralytics.utils import LOGGER
5 |
6 | # Set modules in sys.modules under their old name
7 | sys.modules['ultralytics.yolo.data'] = importlib.import_module('ultralytics.data')
8 | # This is for updating old cls models, or the way in following warning won't work.
9 | sys.modules['ultralytics.yolo.data.augment'] = importlib.import_module('ultralytics.data.augment')
10 |
11 | DATA_WARNING = """WARNING ⚠️ 'ultralytics.yolo.data' is deprecated since '8.0.136' and will be removed in '8.1.0'. Please use 'ultralytics.data' instead.
12 | Note this warning may be related to loading older models. You can update your model to current structure with:
13 | import torch
14 | ckpt = torch.load("model.pt") # applies to both official and custom models
15 | torch.save(ckpt, "updated-model.pt")
16 | """
17 | LOGGER.warning(DATA_WARNING)
18 |
--------------------------------------------------------------------------------
/ultralytics/yolo/engine/__init__.py:
--------------------------------------------------------------------------------
1 | import importlib
2 | import sys
3 |
4 | from ultralytics.utils import LOGGER
5 |
6 | # Set modules in sys.modules under their old name
7 | sys.modules['ultralytics.yolo.engine'] = importlib.import_module('ultralytics.engine')
8 |
9 | LOGGER.warning("WARNING ⚠️ 'ultralytics.yolo.engine' is deprecated since '8.0.136' and will be removed in '8.1.0'. "
10 | "Please use 'ultralytics.engine' instead.")
11 |
--------------------------------------------------------------------------------
/ultralytics/yolo/utils/__init__.py:
--------------------------------------------------------------------------------
1 | import importlib
2 | import sys
3 |
4 | from ultralytics.utils import LOGGER
5 |
6 | # Set modules in sys.modules under their old name
7 | sys.modules['ultralytics.yolo.utils'] = importlib.import_module('ultralytics.utils')
8 |
9 | UTILS_WARNING = """WARNING ⚠️ 'ultralytics.yolo.utils' is deprecated since '8.0.136' and will be removed in '8.1.0'. Please use 'ultralytics.utils' instead.
10 | Note this warning may be related to loading older models. You can update your model to current structure with:
11 | import torch
12 | ckpt = torch.load("model.pt") # applies to both official and custom models
13 | torch.save(ckpt, "updated-model.pt")
14 | """
15 | LOGGER.warning(UTILS_WARNING)
16 |
--------------------------------------------------------------------------------
/ultralytics/yolo/v8/__init__.py:
--------------------------------------------------------------------------------
1 | import importlib
2 | import sys
3 |
4 | from ultralytics.utils import LOGGER
5 |
6 | # Set modules in sys.modules under their old name
7 | sys.modules['ultralytics.yolo.v8'] = importlib.import_module('ultralytics.models.yolo')
8 |
9 | LOGGER.warning("WARNING ⚠️ 'ultralytics.yolo.v8' is deprecated since '8.0.136' and will be removed in '8.1.0'. "
10 | "Please use 'ultralytics.models.yolo' instead.")
11 |
--------------------------------------------------------------------------------