Link to this sectionКак конвертировать аннотации COCO в формат YOLO#
Для обучения моделей Ultralytics YOLO требуются аннотации в формате YOLO, однако многие популярные инструменты аннотирования экспортируют данные в формате COCO JSON. В этом руководстве показано, как конвертировать аннотации COCO в формат YOLO и приступить к обучению моделей обнаружения объектов, сегментации экземпляров и оценки поз.
Чтобы обучать YOLO прямо на COCO JSON без генерации файлов .txt, смотри Обучение YOLO на COCO JSON без конвертации.
Link to this sectionЗачем конвертировать из COCO в YOLO?#
Формат COCO JSON хранит все аннотации в одном файле, в то время как YOLO использует по одному текстовому файлу на каждое изображение с нормализованными координатами. Конвертация необходима, потому что:
- Модели YOLO требуют файлы меток
.txt, по одному на каждое изображение, содержащиеclass x_center y_center width heightв нормализованных координатах. - COCO JSON использует пиксельные координаты в формате
[x_min, y_min, width, height]и один JSON-файл для всех изображений. - Идентификаторы классов различаются — в COCO используются произвольные значения
category_id, тогда как YOLO требует идентификаторы классов с индексацией от нуля.
| Функция | COCO JSON | YOLO TXT |
|---|---|---|
| Структура | Один JSON-файл для всех изображений | Один .txt файл на изображение |
| Формат Bbox | [x_min, y_min, width, height] в пикселях | class x_center y_center width height нормализованные (0-1) |
| ID классов | category_id (может начинаться с любого числа) | С индексацией от нуля (начинается с 0) |
| Сегментация | Массивы полигонов в поле segmentation | Координаты полигона после ID класса |
| Ключевые точки | [x, y, visibility, ...] в пикселях | [x, y, visibility, ...] нормализованные |
Link to this sectionБыстрый старт#
Самый быстрый способ конвертировать аннотации COCO и начать обучение:
from ultralytics.data.converter import convert_coco
convert_coco(
labels_dir="my_dataset/annotations/", # directory containing your JSON files
save_dir="my_dataset/converted/", # where to save converted labels
cls91to80=False, # set False for custom datasets (see warning below)
)После конвертации организуй структуру своих директорий, создай файл dataset.yaml и начни обучение. Ознакомься с полным пошаговым руководством ниже.
Значение по умолчанию cls91to80=True предназначено только для стандартного набора данных COCO с 80 классами объектов, который преобразует 91 несмежный идентификатор категории в 80 последовательных идентификаторов классов. Для любого пользовательского набора данных ты обязан установить cls91to80=False — в противном случае идентификаторы классов будут неявно отображены некорректно, и твоя модель изучит неправильные классы.
Link to this sectionПошаговое руководство по конвертации#
Link to this section1. Подготовь свой набор данных COCO#
Типичный набор данных в формате COCO, экспортированный из инструментов аннотирования, имеет следующую структуру:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ ├── img_002.jpg
│ │ └── ...
│ └── val/
│ ├── img_100.jpg
│ └── ...
└── annotations/
├── instances_train.json
└── instances_val.jsonКаждый JSON-файл соответствует спецификации формата данных COCO с тремя обязательными полями — images, annotations и categories:
{
"images": [{ "id": 1, "file_name": "img_001.jpg", "width": 640, "height": 480 }],
"annotations": [
{
"id": 1,
"image_id": 1,
"category_id": 1,
"bbox": [100, 50, 200, 150],
"area": 30000,
"iscrowd": 0
}
],
"categories": [
{ "id": 1, "name": "helmet" },
{ "id": 2, "name": "vest" }
]
}Link to this section2. Конвертируй аннотации#
Используй функцию convert_coco(), чтобы конвертировать аннотации COCO JSON в формат YOLO .txt:
from ultralytics.data.converter import convert_coco
convert_coco(
labels_dir="my_dataset/annotations/",
save_dir="my_dataset/converted/",
cls91to80=False,
)convert_coco() записывает по одному файлу .txt для каждого изображения с разметкой в поддиректорию labels/, названную по имени каждого JSON-файла, с удалением префикса instances_ (так что instances_train.json создает labels/train/). Изображения без разметки пропускаются и не получают файла с метками, поэтому дерево labels/ может не в точности повторять структуру папок с изображениями:
my_dataset/converted/
└── labels/
├── train/ # from instances_train.json
│ ├── img_001.txt
│ └── ...
└── val/ # from instances_val.json
└── ...convert_coco() никогда не перезаписывает существующую save_dir: если my_dataset/converted/ уже существует, повторный запуск запишет данные в my_dataset/converted-2/. Удали предыдущий вывод (или измени save_dir) перед повторным запуском, иначе следующие шаги будут использовать устаревшие метки.
Link to this section3. Организуй структуру директорий#
После конвертации файлы меток должны быть размещены рядом с твоими изображениями. YOLO ожидает директорию labels/, которая дублирует структуру директории images/:
import shutil
from pathlib import Path
converted_dir = Path("my_dataset/converted/labels")
dataset_dir = Path("my_dataset")
# convert_coco names each subdirectory after its JSON file (minus the "instances_" prefix),
# so iterate the actual subdirectories instead of assuming "train"/"val".
for src in converted_dir.iterdir():
if not src.is_dir():
continue
dst = dataset_dir / "labels" / src.name
dst.mkdir(parents=True, exist_ok=True)
for f in src.glob("*.txt"):
shutil.move(str(f), str(dst / f.name))Твоя итоговая структура набора данных должна выглядеть так:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ └── ...
│ └── val/
│ └── ...
├── labels/
│ ├── train/
│ │ ├── img_001.txt
│ │ └── ...
│ └── val/
│ └── ...
└── dataset.yamlLink to this section4. Создай dataset.yaml#
Создай конфигурационный файл dataset.yaml, который сопоставляет твои категории COCO с именами классов YOLO. Этот файл сообщает YOLO, где находятся твои данные и какие классы необходимо обнаруживать:
import json
from pathlib import Path
import yaml
# Read categories from your COCO JSON
with open("my_dataset/annotations/instances_train.json") as f:
coco = json.load(f)
# Build class names matching convert_coco output (category_id - 1)
categories = sorted(coco["categories"], key=lambda x: x["id"])
names = {cat["id"] - 1: cat["name"] for cat in categories}
# NOTE: convert_coco maps class IDs as category_id - 1, so category_id must
# start from 1. If your categories start from 0, add 1 to each ID first.
# Create dataset.yaml
dataset = {
"path": str(Path("my_dataset").resolve()),
"train": "images/train",
"val": "images/val",
"names": names,
}
with open("my_dataset/dataset.yaml", "w") as f:
yaml.dump(dataset, f, default_flow_style=False)Полученный YAML-файл:
path: /absolute/path/to/my_dataset
train: images/train
val: images/val
names:
0: helmet
1: vestДля получения подробной информации о формате YAML набора данных ознакомься с руководством по конфигурации набора данных.
Link to this section5. Обучи свою модель YOLO#
Когда твой конвертированный набор данных готов, обучи модель YOLO:
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load a pretrained model
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)Для получения советов по обучению и лучших практик ознакомься с руководством по обучению моделей.
Link to this section6. Проверь свою конвертацию#
Перед обучением выборочно проверь несколько файлов меток, чтобы подтвердить правильность идентификаторов классов и координат:
from pathlib import Path
label_file = Path("my_dataset/labels/train/img_001.txt")
for line in label_file.read_text().strip().splitlines():
parts = line.split()
cls_id = int(parts[0])
coords = [float(v) for v in parts[1:5]]
assert cls_id >= 0, f"Negative class ID {cls_id} — category_id in your JSON may start from 0"
assert all(0 <= v <= 1 for v in coords), f"Coordinates out of [0, 1] range: {coords}"Если ты видишь отрицательные идентификаторы классов, вероятно, твой JSON COCO использует category_id, начинающийся с 0. Добавь 1 ко всем значениям category_id в своем JSON перед запуском convert_coco(), так как она сопоставляет ID классов как category_id - 1.
Link to this sectionУстранение распространенных проблем#
Link to this sectionНеправильные ID классов после конвертации#
Если модель обучается, но обнаруживает неправильные классы объектов, вероятно, ты используешь cls91to80=True (по умолчанию) для пользовательского набора данных. Это отображает твои значения category_id через таблицу поиска COCO 91-to-80, которая верна только для стандартного набора данных COCO.
Решение: Всегда используй cls91to80=False для пользовательских наборов данных.
Link to this sectionВо время обучения метки не найдены#
Если обучение показывает WARNING: No labels found или 0 images, N backgrounds, твои файлы меток находятся не в ожидаемой директории. convert_coco() сохраняет метки в отдельную выходную директорию (например, save_dir/labels/train/), но YOLO ожидает labels/ параллельно images/ внутри директории твоего набора данных.
Решение: Перемести файлы меток в соответствии с ожидаемой структурой директорий. Убедись, что labels/train/ является дочерней директорией, соседствующей с images/train/.
Link to this sectionОшибка KeyError во время конвертации#
Если ты получаешь KeyError: 'bbox' или подобные ошибки при запуске convert_coco(), вероятно, твой labels_dir содержит JSON-файлы, не относящиеся к экземплярам (например, captions_train2017.json), которые имеют другую структуру аннотаций.
Решение: Помещай только JSON-файлы с аннотациями экземпляров (например, instances_train2017.json) в папку labels_dir.
Link to this sectionПустые файлы меток после конвертации#
Если конвертация завершена, но файлы .txt пусты или отсутствуют, возможно, все аннотации имеют iscrowd: 1 (распространено для масок, созданных SAM), или ограничивающие рамки имеют нулевую ширину или высоту.
Решение: Проверь свои JSON-аннотации на наличие значений iscrowd. Если ты используешь маски SAM, выполни предварительную обработку JSON, установив iscrowd: 0.
Link to this sectionРазрывы в ID классов в конвертированных метках#
Если идентификаторы классов в файлах меток не являются непрерывными (например, 0, 4, 9 вместо 0, 1, 2), твой инструмент аннотирования использует несмежные значения category_id.
Решение: Проверь, что идентификаторы классов в твоих файлах .txt соответствуют словарю names в dataset.yaml. При необходимости переназначь идентификаторы на последовательные значения.
Для получения полной информации об API и описания параметров ознакомься со справочником API convert_coco.
Link to this sectionFAQ#
Link to this sectionКак конвертировать аннотации COCO JSON в формат YOLO?#
Используй функцию convert_coco() от Ultralytics для конвертации аннотаций COCO JSON в формат YOLO .txt. Установи cls91to80=False для пользовательских наборов данных:
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="path/to/annotations/", save_dir="output/", cls91to80=False)После конвертации реорганизуй свои файлы меток так, чтобы labels/ дублировала директорию images/, затем создай файл dataset.yaml. Смотри пошаговое руководство для полного рабочего процесса.
Link to this sectionПочему обучение YOLO показывает "No labels found" после конвертации COCO?#
Это происходит потому, что convert_coco() сохраняет метки в поддиректорию внутри save_dir/labels/ (например, save_dir/labels/train/), а не непосредственно в labels/train/ твоего набора данных рядом с images/train/. YOLO ожидает, что метки будут параллельны изображениям — например, images/train/img.jpg требует labels/train/img.txt. Перемести конвертированные метки, чтобы они соответствовали этой структуре. Смотри исправление структуры директорий.
Link to this sectionЧто делает cls91to80 в convert_coco()?#
Параметр cls91to80 управляет тем, как значения COCO category_id отображаются на ID классов YOLO. Когда установлено значение True (по умолчанию), применяется таблица поиска coco91_to_coco80_class(), разработанная для стандартного набора данных COCO, который содержит 80 классов с несмежными ID (1-90). Для пользовательских наборов данных всегда устанавливай cls91to80=False — это просто вычитает 1 из каждого category_id для создания ID классов с индексацией от нуля.
Link to this sectionМожно ли обучать YOLO непосредственно на COCO JSON без конвертации?#
Нет, с текущим конвейером обучения YOLO это невозможно — аннотации должны быть в формате YOLO .txt, по одному файлу на изображение. Сначала используй convert_coco() для конвертации твоего COCO JSON, затем следуй этому руководству для организации и обучения. Для получения дополнительной информации о поддерживаемых форматах ознакомься с форматами наборов данных.
Link to this sectionМожно ли конвертировать аннотации сегментации COCO в формат YOLO?#
Да, используй use_segments=True при вызове convert_coco(), чтобы включить полигональные маски сегментации в конвертированные метки YOLO. Это создает файлы меток, совместимые с моделями сегментации YOLO:
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="annotations/", save_dir="output/", use_segments=True, cls91to80=False)Link to this sectionКак конвертировать аннотации ключевых точек COCO в формат YOLO?#
Используй use_keypoints=True для конвертации аннотаций ключевых точек COCO для обучения оценке поз:
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="annotations/", save_dir="output/", use_keypoints=True, cls91to80=False)Обрати внимание, что если и use_segments, и use_keypoints установлены в True, в файлы меток будут записаны только ключевые точки — сегменты будут неявно проигнорированы.