Посмотреть как Markdown

Датасеты

Датасет в LibreYOLO — это YAML-файл, в котором заданы корень, сплиты и имена классов. Всё остальное, включая расположение файлов разметки, выводится из этого файла по соглашению.

Указание датасета для обучения

data= принимает путь к YAML или имя конфига, который поставляется вместе с пакетом.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Подойдёт встроенное имя, относительный путь или абсолютный путь.model.train(data="coco8.yaml", epochs=10)
CLI
libreyolo train model=LibreYOLO9s.pt data=coco8.yaml epochs=10

Имя разрешается в фиксированном порядке: существующий абсолютный путь, затем имя как есть относительно рабочего каталога, затем то же имя с добавленным .yaml, затем каталог встроенных конфигов. Если ничего не совпало, в ошибке перечисляются все просмотренные каталоги и все встроенные конфиги.

Встроенные конфиги

Вместе с пакетом поставляются тринадцать конфигов датасетов — они лежат в libreyolo/config/datasets/.

КонфигЗадачаПримечания
coco8.yamldetect8 изображений, скачивается по обычному URL
coco128.yamldetect128 изображений
coco1000.yamldetect800 на обучение, 200 на валидацию
coco5000.yamldetect4000 на обучение, 1000 на валидацию
coco.yamldetectполный COCO 2017
coco-val-only.yamldetectтолько val2017
coco8-pose.yamlpose8 изображений, ключевые точки COCO-17
coco-pose.yamlposeключевые точки COCO 2017
ade20k.yamlsemantic150 классов
cityscapes.yamlsemantic19 классов, скачивание вручную
cocostuff.yamlsemantic182 класса, скачивание вручную
gopro.yamlrestoreпары для устранения размытия
sr8.yamlrestoreпары для суперразрешения

Обычный URL для скачивания есть только у coco8.yaml и coco128.yaml. Остальные либо содержат Python-блок скачивания, для которого нужно явное разрешение (описано ниже), либо ожидают, что данные уже лежат на диске.

Где датасет лежит на диске

Ключ path в YAML задаёт корень датасета. Абсолютный path используется как есть. Относительный сначала ищется в каталоге датасетов, затем рядом с самим YAML-файлом, а датасет, который предстоит скачать, попадает в каталог датасетов.

Этот каталог — ~/datasets, его переопределяет переменная окружения LIBREYOLO_DATASETS_DIR. Файла настроек для него нет.

Ключи YAML

yaml
path: my-dataset        # корень датасетаtrain: images/train     # нужен для обученияval: images/val         # нужен для валидацииtest: images/test       # необязателенnc: 3                   # необязателен; должен согласовываться с namesnames:  0: person  1: helmet  2: vestdownload: https://example.com/my-dataset.zip   # необязателен

train, val и test принимают каталог с изображениями, файл .txt с одним путём к изображению на строку или список, где смешано и то и другое. Строки в списке .txt могут быть относительными — тогда они разрешаются относительно каталога самого файла со списком, — а строки, начинающиеся с #, пропускаются.

names может быть списком или отображением с целочисленными ключами. nc необязателен; если присутствуют оба и они расходятся, doctor сообщает об этом как об ошибке.

RF-DETR для позы читает kpt_names с ID или именем класса в ключах. Он сохраняет первые именованные строки ключевых точек каждого класса; пустой список обозначает класс только с рамками. Для позы с несколькими классами нужны names и хотя бы один класс с ключевыми точками.

Структура каталогов и файлы разметки

У детекции, сегментации, оценки позы и повёрнутых рамок структура одна. Путь к разметке выводится из пути к изображению: компонент каталога images заменяется на labels, а расширение — на .txt:

my-dataset/  images/train/0001.jpg   ->   labels/train/0001.txt  images/val/0002.jpg     ->   labels/val/0002.txt

Заменяется только целый компонент пути images, поэтому каталог с именем images_old остаётся нетронутым.

Строка детекции — это пять полей, все нормированы к [0, 1] по исходной ширине и высоте изображения:

<class_id> <cx> <cy> <w> <h>

Отсутствующий или пустой файл разметки означает, что на изображении нет объектов: при обучении оно идёт как фон, а не вызывает ошибку. Строка, в которой больше пяти полей, читается как полигон, и рамкой для неё становится габаритный прямоугольник этого полигона, поэтому экспорт сегментации, использованный для обучения детекции, загружается без ошибок. Doctor сообщает, сколько строк прошло по этому пути.

Рамки с конечными координатами, пересекающие границу изображения, одинаково обрезаются при обучении и валидации. Рамки без видимой площади, с неконечными координатами и некорректные полигоны отбрасываются. ID классов вне допустимого диапазона диагностируются до построения целевых значений. train(classes=[...]) фильтрует разметку по исходным ID классов; см. гиперпараметры.

Другие задачи

Сегментация сохраняет ту же структуру, но со строками-полигонами <class_id> <x1> <y1> ... <xN> <yN> минимум из трёх точек. Строка детекции из пяти полей принимается и означает прямоугольный экземпляр.

Оценка позы добавляет в YAML kpt_shape: [K, D] и необязательную перестановку flip_idx. В каждой строке ровно 5 + K * D полей: рамка, затем K ключевых точек вида x y или x y v, где видимость — 0, 1 или 2.

Повёрнутые рамки используют ровно девять полей: класс, а за ним четыре угловые точки в нормированных координатах. Угол в файле не хранится.

Семантическая сегментация сопоставляет каждому изображению одноканальную маску того же разрешения; путь получается подстановкой masks_dir (по умолчанию masks) вместо images. Значение пикселя 255 означает «игнорировать». label_mapping при загрузке переводит исходные id в id для обучения.

Классификация вместо файлов разметки использует дерево ImageFolder: в train/ и val/ лежит по одному каталогу на класс. Соответствие класса и индекса задаётся отсортированным порядком имён каталогов.

Восстановление сопоставляет искажённый вход с чистым целевым изображением того же разрешения через input_dir и target_dir. Оценка глубины, нормали к поверхности и границы сопоставляют изображению плотную карту, каждая через свой ключ каталога.

Полный контракт по каждой задаче, включая соглашения о масштабе глубины и кодирование id паноптических сегментов в PNG, — это docs/dataset_schema.md в репозитории библиотеки.

Нативный COCO JSON

Файл аннотаций COCO JSON можно использовать напрямую. Добавьте отображение annotations, и путь сплита станет корнем с изображениями:

yaml
path: my-datasettrain: images/trainval: images/valannotations:  train: annotations/train.json  val: annotations/val.json

Если names присутствует, имена категорий в JSON должны с ним совпадать, и именно names задаёт id меток, которые предсказывает модель. Без names id категорий COCO сортируются и плотно отображаются в 0..N-1.

Этот путь ожидает по одному каталогу с изображениями на сплит. Список путей или список изображений в .txt вызывает ошибку, а не загружает молча другой набор.

Автоскачивание

Датасет считается на месте, когда его путь train или val разрешается в непустой каталог или в существующий файл. Если это не так, а в YAML есть ключ download, дальнейшее решает его значение.

URL с http или https скачивается и, если это zip, распаковывается в корень датасета. Всё остальное считается встроенным Python-скриптом и запускается только при allow_download_scripts=True. Без этого скрипт пропускается с предупреждением, а обучение продолжается на том, что лежит на диске.

bash
libreyolo train model=LibreYOLO9s.pt data=coco.yaml allow_download_scripts=true

Этот флаг ограничивает выполнение кода, а не доступ к сети. Скачивание по URL происходит в любом случае; флаг нужен именно блокам download: |. CLI печатает предупреждение, когда флаг включён, а doctor не включает его никогда.

Проверка датасета перед обучением

libreyolo doctor читает датасет для детекции и сообщает, что пойдёт не так, ещё до того, как в дело вступит GPU. При найденных ошибках он завершается с кодом 1, поэтому годится как CI-гейт.

Проверка датасета
libreyolo doctor my-dataset.yaml
Завершение CI с ошибкой и на предупреждениях
libreyolo doctor my-dataset.yaml strict=true json=true
Пропуск прохода с декодированием изображений
# Читает только разметку и YAML. Проверки на повреждения, дубликаты# и утечки между сплитами требуют пикселей, поэтому пропускаются.libreyolo doctor my-dataset.yaml fast=true
Python
from libreyolo import doctor report = doctor.diagnose("my-dataset.yaml", imgsz=640) for finding in report.findings:    print(finding.severity.value, finding.check_id, finding.message) raise SystemExit(report.exit_code(strict=False))

Проверки разбиты на шесть семейств:

СемействоЧто ищет
configотсутствующий names, nc, расходящийся с names, отсутствующие или пустые сплиты, повторяющиеся имена классов
filesизображения без файла разметки, разметка без изображения, отсутствующие изображения, перечисленные в сплите, конфликты имён без расширения
labelsнекорректные строки, id классов вне [0, nc), координаты вне [0, 1], рамки нулевой площади, крошечные или огромные рамки, повторяющиеся рамки, побайтово одинаковые файлы разметки
balanceклассы без экземпляров или почти без них, коэффициент дисбаланса классов, классы, встречающиеся только в одном сплите, доля фоновых изображений
imagesфайлы, которые не декодируются, поворот по EXIF, необычная раскладка каналов, однотонные изображения, точные и почти точные дубликаты
splitsодно и то же изображение в двух сплитах, точно или почти точно

--only и --skip принимают id проверки или префикс семейства, поэтому skip=images,labels.tiny_object — корректная запись. --fast отбрасывает все проверки, которым нужно декодировать пиксели, то есть семейства images и splits.

Стоит знать о двух особенностях. С --strict на код возврата влияют не только ошибки, но и предупреждения. И doctor работает только с датасетами для детекции: датасет для оценки позы, сегментации или повёрнутых рамок отклоняется с сообщением о том, что именно распознано, вместо проверки по неподходящему контракту.

Проверено с LibreYOLO v1.6.0.