├── 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 | ![CE057907-DEA1-4ce7-B567-CA9913DE8F0C](https://github.com/T-SW/AutoLabelImg/assets/69509115/f59cfe39-0ddf-4397-b567-803e2d67c217) 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 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 22 | 24 | 26 | 29 | 30 | 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 | --------------------------------------------------------------------------------