Сбор данных и схема классов
Уроки курсаСбор данных и схема классов
Форматы: YOLO/COCO, data.yaml, class-map и алиасы
Для обучения детектора нужны изображения и аннотации — координаты bbox и класс объекта. Два популярных формата: YOLO (текстовые файлы, простой) и COCO (JSON, подробный). data.yaml описывает датасет: пути к train/val/test, число классов, их имена. Class-map связывает индекс класса с названием (0 → car, 1 → person). Алиасы позволяют использовать синонимы (automobile → car).
Ключевые идеи
- YOLO: текстовые файлы, каждая строка — один объект. Координаты в относительных единицах (0-1).
- COCO: JSON с полной информацией (изображения, аннотации, категории). Используется для бенчмарков.
- data.yaml: конфиг датасета (пути, число классов, имена). Нужен для обучения.
- Class-map: индекс → имя класса. Предотвращает ошибки при разметке.
Формат YOLO
YOLO использует текстовые файлы `.txt` — один файл на изображение. Имя файла совпадает с изображением: `image001.jpg` → `image001.txt`.
Формат строки:
<class_id> <x_center> <y_center> <width> <height>
Координаты нормализованы (0-1): делим на ширину/высоту изображения.
Пример: изображение 640×480, объект класса 0 (car) с bbox [100, 150, 200, 100] (x, y, w, h в пикселях).
# Нормализация
x_center = (100 + 200/2) / 640 = 0.3125
y_center = (150 + 100/2) / 480 = 0.4167
width = 200 / 640 = 0.3125
height = 100 / 480 = 0.2083
# Результат в image001.txt
0 0.3125 0.4167 0.3125 0.2083
Если на изображении несколько объектов — несколько строк:
0 0.3125 0.4167 0.3125 0.2083 1 0.7500 0.2500 0.1500 0.2000
Структура папок:
dataset/
├── images/
│ ├── train/
│ │ ├── image001.jpg
│ │ └── image002.jpg
│ └── val/
│ └── image003.jpg
└── labels/
├── train/
│ ├── image001.txt
│ └── image002.txt
└── val/
└── image003.txt
Формат COCO
COCO использует один JSON-файл для всех аннотаций. Подробнее, чем YOLO, но сложнее редактировать вручную.
Структура:
{
"images": [
{
"id": 1,
"file_name": "image001.jpg",
"width": 640,
"height": 480
}
],
"annotations": [
{
"id": 1,
"image_id": 1,
"category_id": 1,
"bbox": [100, 150, 200, 100], # [x, y, width, height] в пикселях
"area": 20000,
"iscrowd": 0 # 0 — отдельный объект, 1 — группа
}
],
"categories": [
{
"id": 1,
"name": "car",
"supercategory": "vehicle"
},
{
"id": 2,
"name": "person",
"supercategory": "human"
}
]
}
bbox в COCO: `[x_top_left, y_top_left, width, height]` в пикселях (не нормализованы, в отличие от YOLO).
COCO используется для официальных бенчмарков, YOLO — для быстрого обучения и inference.
Файл data.yaml
data.yaml описывает датасет для обучения. Используется в YOLO, Ultralytics, многих фреймворках.
Пример:
# Пути к данным (относительно data.yaml или абсолютные)
train: data/images/train
val: data/images/val
test: data/images/test # опционально
# Число классов
nc: 3
# Имена классов (порядок важен: индекс 0 → первое имя)
names: ['car', 'person', 'dog']
Обучение с этим конфигом:
python train.py --data data.yaml --epochs 50
Если пути относительные, они разрешаются относительно расположения data.yaml. Лучше использовать относительные пути — проект переносимый.
Class-map и алиасы
Class-map — явное сопоставление индекс → имя класса. Предотвращает ошибки, когда индексы перепутаны.
Пример class_map.yaml:
0: car
1: person
2: dog
Используется при конвертации форматов или валидации аннотаций.
Алиасы — синонимы классов. Полезны, если разметчики использовали разные названия для одного объекта.
Пример с алиасами:
nc: 3
names: ['car', 'person', 'dog']
# Алиасы: разные названия → один класс
aliases:
automobile: car
vehicle: car
human: person
pedestrian: person
canine: dog
При загрузке данных алиасы автоматически заменяются основным именем: `automobile` → `car`.
Конвертация форматов
Часто нужно конвертировать COCO → YOLO или наоборот.
Пример COCO → YOLO:
import json
from pathlib import Path
def coco_to_yolo(coco_json_path, output_dir):
with open(coco_json_path) as f:
coco = json.load(f)
# Создаём mapping image_id → file_name, width, height
images = {img['id']: img for img in coco['images']}
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
for ann in coco['annotations']:
img = images[ann['image_id']]
img_w, img_h = img['width'], img['height']
# bbox в COCO: [x, y, w, h] в пикселях
x, y, w, h = ann['bbox']
# Конвертируем в YOLO: center, normalized
x_center = (x + w / 2) / img_w
y_center = (y + h / 2) / img_h
width = w / img_w
height = h / img_h
class_id = ann['category_id'] - 1 # COCO id с 1, YOLO с 0
# Сохраняем в txt
txt_path = output_dir / f"{Path(img['file_name']).stem}.txt"
with open(txt_path, 'a') as f:
f.write(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n")
coco_to_yolo('annotations.json', 'labels/train/')
Валидация аннотаций
Проверяем, что аннотации корректны:
from pathlib import Path
def validate_yolo_annotations(labels_dir, num_classes):
errors = []
for txt_path in Path(labels_dir).glob('*.txt'):
with open(txt_path) as f:
for line_num, line in enumerate(f, 1):
parts = line.strip().split()
if len(parts) != 5:
errors.append(f"{txt_path.name}:{line_num} - неверное число значений")
continue
class_id, x, y, w, h = map(float, parts)
# Проверки
if not (0 <= class_id < num_classes):
errors.append(f"{txt_path.name}:{line_num} - class_id вне диапазона")
if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < w <= 1 and 0 < h <= 1):
errors.append(f"{txt_path.name}:{line_num} - координаты вне диапазона [0,1]")
return errors
errors = validate_yolo_annotations('labels/train/', num_classes=3)
if errors:
print("Найдены ошибки:")
for err in errors[:10]: # Показываем первые 10
print(f" {err}")
Частые проблемы
- Координаты вне [0,1] в YOLO: забыли нормализовать. Модель выдаст некорректные bbox.
- Несовпадение имён файлов: `image001.jpg` есть, а `image001.txt` нет. Модель пропустит изображение.
- Неверный class_id: в data.yaml 3 класса, в аннотации class_id=5. Обучение упадёт с ошибкой.
- Разные форматы bbox: перепутали YOLO (center) и COCO (top-left). Bbox окажутся не там.
- Пустые аннотации: если на изображении нет объектов, создайте пустой .txt файл (не удаляйте).
Связанные понятия
- Pascal VOC: формат XML, старый стандарт. Сейчас реже используется.
- Labelme: инструмент для разметки, экспортирует в JSON (похож на COCO).
- CVAT: веб-инструмент для разметки, поддерживает YOLO, COCO, Pascal VOC.
Итоги
- YOLO: текстовые файлы, координаты нормализованы (0-1), формат `class x_center y_center width height`.
- COCO: JSON, координаты в пикселях, формат `[x, y, width, height]` (top-left).
- data.yaml: пути к данным, число классов, имена классов.
- Class-map: индекс → имя класса. Алиасы: синонимы для одного класса.
- Валидация аннотаций обязательна — проверяем координаты, class_id, наличие файлов.
Дальше по курсу
В следующем шаге соберём датасет: 300 изображений (или используем демо-пак), разметим в CVAT, экспортируем в YOLO формат. Создадим data.yaml, проверим аннотации скриптом валидации, разобьём на train/val/test.
