Как конвертировать COCO аннотации в формат YOLO
Обучение моделей Ultralytics YOLO требует аннотаций в формате YOLO, но многие популярные инструменты для аннотирования экспортируют данные в формате COCO JSON. Это руководство покажет тебе, как конвертировать твои COCO аннотации в формат YOLO и начать обучение обнаружения объектов, instance segmentation и , оценку позы моделей.
Зачем конвертировать из COCO в YOLO?
Формат COCO JSON хранит все аннотации в одном файле, в то время как YOLO использует один текстовый файл на каждое изображение с нормализованными координатами. Конвертация необходима, потому что:
- Модели YOLO требуют
.txtфайлов меток по одному файлу на изображение, содержащемуclass x_center y_center width heightв нормализованных координатах. - COCO JSON использует координаты в пикселях в
[x_min, y_min, width, height]и один JSON файл для всех изображений. - ID классов различаются — COCO использует произвольные
category_idзначения, в то время как YOLO требует ID классов с индексацией от нуля.
| Функция | 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 | Массивы полигонов в segmentation поле | Координаты полигона после ID класса |
| Keypoints | [x, y, visibility, ...] в пикселях | [x, y, visibility, ...] нормализованные |
Быстрый старт
Самый быстрый способ конвертировать COCO аннотации и начать обучение:
from ultralytics.data.converter import convert_coco
convert_coco(
labels_dir="path/to/annotations/", # directory containing your JSON files
save_dir="path/to/output/", # where to save converted labels
cls91to80=False, # IMPORTANT: set False for custom datasets
)После конвертации, организуй структуру своих директорий, создай dataset.yaml и начни обучение. Смотри полное пошаговое руководство ниже.
Метод cls91to80=True настройка по умолчанию разработана только для стандартного export mode с 80 классами объектов, которая сопоставляет 91 несмежный ID категории с 80 смежными ID классов. Для любого пользовательского датасета ты должен должен установить cls91to80=False — иначе твои ID классов будут автоматически сопоставлены неверно, и модель выучит неправильные классы.
Пошаговое руководство по конвертации
1. Подготовь свой 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 data format с тремя обязательными полями — 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" }
]
}2. Конвертируй аннотации
Используй команду 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,
)3. Организуй структуру директорий
После конвертации файлы меток должны быть размещены рядом с твоими изображениями. YOLO ожидает директорию labels/ , которая зеркально повторяет директорию images/ :
import shutil
from pathlib import Path
# Paths
converted_dir = Path("my_dataset/converted/labels")
dataset_dir = Path("my_dataset")
# Move labels next to images for each split
for split in ["train", "val"]:
src = converted_dir / split # convert_coco strips "instances_" prefix from JSON filename
dst = dataset_dir / "labels" / split
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.yaml4. Создай 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 датасета смотри руководство по конфигурации датасета.
5. Обучи свою модель 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)Для советов по обучению и лучших практик смотри руководство по обучению моделей.
6. Проверь свою конвертацию
Перед обучением выборочно проверь несколько файлов меток, чтобы подтвердить, что ID классов и координаты верны:
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}"Если ты видишь отрицательные ID классов, твой COCO JSON, скорее всего, использует category_id начиная с 0. Добавь 1 ко всем category_id значениям в твоем JSON перед запуском convert_coco(), так как он сопоставляет ID классов как category_id - 1.
Устранение распространенных проблем
Неверные ID классов после конвертации
Если твоя модель обучается, но детектирует неверные классы объектов, скорее всего, ты используешь cls91to80=True (по умолчанию) для пользовательского датасета. Это сопоставляет твои category_id значения через таблицу поиска COCO 91-to-80, что верно только для стандартного export mode.
Решение: Всегда используй cls91to80=False для пользовательских датасетов.
Метки не найдены во время обучения
Если обучение показывает WARNING: No labels found или 0 images, N backgrounds, твои файлы меток находятся не в той директории. convert_coco() сохраняет метки в отдельную выходную директорию (например, save_dir/labels/train/), но YOLO ожидает labels/ параллельно с images/ внутри директории твоего датасета.
Решение: Перемести файлы меток в соответствии с ожидаемой структурой директорий. Убедись, что labels/train/ является родственным для images/train/.
KeyError во время конвертации
Если ты получаешь KeyError: 'bbox' или похожие ошибки при запуске convert_coco(), твой labels_dir вероятно содержит JSON-файлы, не являющиеся экземплярами (например, captions_train2017.json), которые имеют другую структуру аннотаций.
Решение: Помещай в папку только JSON-файлы с аннотациями экземпляров (например, instances_train2017.json) в labels_dir.
Пустые файлы меток после конвертации
Если конвертация завершена, но .txt файлы пустые или отсутствуют, возможно, все аннотации имеют iscrowd: 1 (обычно для масок, созданных SAM-ом), или bounding boxes имеют нулевую ширину или высоту.
Решение: Проверь свои JSON-аннотации на наличие iscrowd значений. Если используешь маски SAM, предварительно обработай JSON, чтобы задать iscrowd: 0.
Пропуски в ID классов в сконвертированных метках
Если ID классов в файлах меток не являются непрерывными (например, 0, 4, 9 вместо 0, 1, 2), твой инструмент аннотирования использует неконтинуальные category_id значения.
Решение: Убедись, что ID классов в твоих .txt файлах соответствуют names словарю в dataset.yaml. При необходимости переназначь ID на непрерывные значения.
Для получения полной информации об API и описания параметров смотри convert_coco справку по API.
FAQ
Как мне конвертировать 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 файл. Смотри пошаговое руководство для ознакомления с полным рабочим процессом.
Почему при обучении YOLO после конвертации COCO появляется ошибка "No labels found"?
Это происходит, потому что convert_coco() сохраняет метки в подпапку внутри save_dir/labels/ (например, save_dir/labels/train/) вместо того, чтобы сохранять их напрямую в labels/train/ вместе с директориями images/train/. YOLO ожидает, что метки будут находиться параллельно изображениям — например, images/train/img.jpg требует labels/train/img.txt. Перемести сконвертированные метки, чтобы они соответствовали этой структуре. Смотри исправление структуры каталогов.
Что делает cls91to80 в convert_coco()?
Метод cls91to80 параметр управляет тем, как COCO category_id значения сопоставляются с ID классов YOLO. Когда True (по умолчанию), используется таблица поиска, разработанная для стандартного export mode, в котором 80 классов с неконтинуальными ID (1-90). Для пользовательских датасетах, всегда устанавливай cls91to80=False — это просто вычитает 1 из каждого category_id для создания ID классов с нулевым индексом.
Могу ли я обучать YOLO напрямую на COCO JSON без конвертации?
Нет, в текущем конвейере обучения YOLO — аннотации должны быть в формате YOLO .txt с одним файлом на изображение. Используй convert_coco() для предварительной конвертации твоего COCO JSON, а затем следуй этому руководстве для организации и обучения. Подробнее о поддерживаемых форматах смотри форматы наборов данных.
Могу ли я конвертировать сегментационные аннотации 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)Как мне конвертировать аннотации ключевых точек 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, в файлы меток будут записаны только ключевые точки — сегменты будут молча игнорироваться.