Meet YOLO26: next-gen vision AI.

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 JSONYOLO 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=False`

Значение по умолчанию 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:

Конвертация COCO в формат YOLO
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.yaml

Link 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:

Обучение на конвертированных данных COCO
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, в файлы меток будут записаны только ключевые точки — сегменты будут неявно проигнорированы.

Комментарии