YOLOv9

Одностадийный свёрточный детектор: за один проход оценивается плотная сетка рамок, а NMS отбрасывает дубликаты. В LibreYOLO есть три его варианта, и у одного из них шага NMS нет.

Задачи
detection
Размеры
yolo9: t, s, m, c at 640 px; yolo9_p2: t, s at 640 px
Установка
pip install libreyolo
Уровень поддержки
Флагманский, начиная с v1.0.0. Здесь функции проектируются и первыми проходят полную проверку на GPU.
Исходный проект
YOLOv9 от MultimediaTechLab, MIT. Статья, исходный код
Лицензии
Код: MIT, веса: MIT. Коммерческое использование

Установка

YOLOv9 не требует ничего сверх базового пакета.

bash
pip install libreyolo

Предсказание

Веса скачиваются с Hugging Face при первом запуске и кэшируются локально.

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt")result = model(SAMPLE_IMAGE, save=True) for box in result.boxes:    print(box.cls, box.conf, box.xyxy)
CLI
libreyolo predict model=LibreYOLO9s.pt save=True \  source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg
Без NMS
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Тот же вызов, другой чекпойнт. End-to-end голова сама возвращает# предсказания с наибольшими оценками, поэтому NMS не запускается, а iou игнорируется.model = LibreYOLO("LibreYOLO9E2Es.pt")result = model(SAMPLE_IMAGE, conf=0.25, max_det=300) print(len(result.boxes))

Возвращаемый объект Results — тот же, что возвращает любое семейство, поэтому замена на другой детектор — правка в одну строку. У базовой модели и у модели с шагом 4 conf задаёт порог уверенности, а iou — порог NMS. End-to-end модель NMS не запускает и iou игнорирует, поэтому её вывод определяется conf и max_det. Про источники, стриминг и обработку результатов см. предсказание.

Варианты

Три варианта используют общий бэкбон. Все три решают только задачу детекции и принимают одни и те же аргументы.

Базовая модель предсказывает на трёх масштабах признаков и убирает дублирующиеся рамки с помощью NMS.

End-to-end модель сохраняет эту голову и добавляет рядом ветку с сопоставлением один к одному. Инференс читает только эту ветку и берёт из неё предсказания с наибольшими оценками, поэтому NMS не запускается. Выбирайте её, когда в среде выполнения, куда вы разворачиваете модель, нет оператора NMS.

Модель с шагом 4 выводит наружу ещё один уровень бэкбона, протягивает до него neck и предсказывает на четырёх масштабах вместо трёх. Дополнительный масштаб нужен для объектов, занимающих мало пикселей; единственный опубликованный для неё чекпойнт обучен на аэрофотоснимках. Базовые детекционные чекпойнты в неё переносятся: бэкбон и neck загружаются без изменений, три предобученные башни головы сдвигаются на одну позицию вверх, а башня с шагом 4 стартует со случайной инициализации.

ЧекпойнтВход (пикс.)mAP 50-95Параметры (млн)
LibreYOLO9c64056.425.5
LibreYOLO9m64055.320.12
LibreYOLO9s64055.97.2
LibreYOLO9t64041.82.04

COCO val2017, 500 images. Измерено системой бенчмарков LibreYOLO и опубликовано на Vision Analysis, где сравниваются задержки на разном оборудовании и в разных средах выполнения и хранятся полные записи запусков.

Обучение

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.train(data="my-dataset.yaml", epochs=100, imgsz=640, batch=16)
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \  epochs=100 imgsz=640 batch=16
Мелкие объекты
from libreyolo import LibreYOLO9P2 # У варианта с шагом 4 нет собственного чекпойнта на COCO, поэтому# укажите базовый детекционный: его бэкбон и neck загрузятся без# изменений, а башня головы с шагом 4 стартует со случайной инициализации.model = LibreYOLO9P2(None, size="s")model.train(data="my-dataset.yaml", epochs=100, pretrained="LibreYOLO9s.pt")

pretrained определяет, с чего начинается запуск. Передайте True, чтобы загрузить опубликованный чекпойнт для той же модели и того же размера, или имя либо путь — для всего остального. Тензоры с несовпадающей формой пропускаются, а не приводят к ошибке, и в лог пишется, сколько их загрузилось, поэтому чекпойнт, обученный на другом числе классов, всё равно годится как стартовая точка.

У модели с шагом 4 нет собственного опубликованного чекпойнта на COCO, поэтому в этом случае True указывает на несуществующий файл, и скачивание падает. Вместо этого укажите базовый детекционный чекпойнт.

Про датасеты, аугментацию, multi-GPU и логгеры см. обучение.

Базовая модель может обучать вспомогательную ветвь PGI рядом с основной головой. Ветвь нужна только при обучении: предсказание и экспорт используют основную голову. Запуск подключает её, когда стартовые веса содержат тензоры PGI или когда обучение идёт с нуля. Опубликованные базовые чекпойнты их не содержат, поэтому дообучение с них обучает только основную голову и пишет об этом в лог. aux_weight=0.25 всё равно подключает новую ветвь с этим весом функции потерь, а aux_weight=0 оставляет её выключенной. Возобновлённый запуск сохраняет настройку PGI из своего чекпойнта. В размерах m и c ветвь такая же, как в оригинале: второй бэкбон на входном изображении, стадии которого CBFuse суммирует с отводами CBLinear основного бэкбона, и собственная голова, 12.8M и 25.7M параметров, используемых только при обучении, при 80 классах. У сквозной модели и модели с шагом 4 ветви PGI нет.

Все три варианта обрезают L2-норму градиента на 10 перед каждым шагом оптимизатора; clip_max_norm=0 отключает обрезку. Назначение меток оценивает якоря в fp32, в том числе при автокасте float16. max_labels=300 ограничивает число рамок, сохраняемых на обучающее изображение, а рамки сверх лимита отбрасываются с однократным предупреждением; память назначения зависит от реальных рамок каждого изображения, а не от лимита. Momentum SGD прогревается от 0.8 до 0.937 за три эпохи. letterbox_pad=None наследует отметку чекпойнта: веса без отметки используют topleft, а новые официальные конверсии записывают center.

Mosaic в YOLO9 и YOLOX предпочитает изображения с разметкой, делая не более 20 попыток выбора; MixUp в YOLO9 использует ту же политику. MixUp по умолчанию выключен (mixup_prob=0). Когда он включён, коэффициент смешивания берётся из Beta(1, 1), равномерно на [0, 1], как в MultimediaTechLab/YOLO. Профили входа без RGB описаны в разделе гистограмм событий.

Валидация

val() возвращает словарь с ключами metrics/ для точности, полноты, mAP 50 и mAP 50-95, измеренных на любом датасете в том формате, на котором вы обучались.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="my-dataset.yaml") print(metrics["metrics/mAP50-95"])print(metrics["metrics/mAP50"])
CLI
libreyolo val model=LibreYOLO9s.pt data=my-dataset.yaml
Проверка на COCO
# Во встроенном COCO yaml есть скрипт скачивания, поэтому нужно явное# разрешение, если датасет ещё не лежит локально.libreyolo val model=LibreYOLO9c.pt data=coco.yaml imgsz=640 \  allow_download_scripts=True

Экспорт

ЗадачаONNXTorchScriptExecuTorchTensorRTOpenVINOPaddleMNNRKNNncnnTFLiteCoreMLCore AI
DetectionDetection to ONNX: поддерживаетсяDetection to TorchScript: поддерживаетсяDetection to ExecuTorch: поддерживаетсяDetection to TensorRT: поддерживаетсяDetection to OpenVINO: поддерживаетсяDetection to Paddle: поддерживаетсяDetection to MNN: поддерживаетсяDetection to RKNN: не поддерживаетсяDetection to ncnn: поддерживаетсяDetection to TFLite: не поддерживаетсяDetection to CoreML: не поддерживаетсяDetection to Core AI: поддерживается

Галочка действует для всех трёх вариантов: там, где они расходятся, в таблице стоит самый слабый из трёх.

Экспортированный артефакт загружается обратно через LibreYOLO() по суффиксу файла, поэтому файл .onnx или .engine ведёт себя как чекпойнт и возвращает тот же Results. Запуск графа в чистой среде выполнения, без установленной библиотеки LibreYOLO, тоже поддерживается, но тогда препроцессинг и постпроцессинг придётся писать самостоятельно.

Для базовой детекционной модели половину с постпроцессингом можно перенести в граф. nms=True при экспорте в ONNX помещает подавление внутрь модели, и первый выход становится тензором фиксированной формы (1, max_det, 6), строки которого — x1, y1, x2, y2, score, class, дополненные нулями после числа детекций. Такой граф рассчитан на батч 1 и не содержит динамических осей. End-to-end модель и модель с шагом 4 этот флаг не принимают.

Каждый формат устанавливает свой extra и принимает несколько собственных аргументов. И то и другое описано на странице этого формата.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.export(format="onnx", imgsz=640)
CLI
libreyolo export model=LibreYOLO9s.pt format=onnx imgsz=640
С NMS в графе
libreyolo export model=LibreYOLO9s.pt format=onnx nms=True \  conf=0.25 iou=0.45 max_det=300
Использование экспортированного файла
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Фабрика выбирает путь по суффиксу файла, поэтому экспортированный# артефакт загружается как любой чекпойнт и возвращает тот же объект Results.model = LibreYOLO("LibreYOLO9s.onnx")result = model(SAMPLE_IMAGE) print(result.boxes.xyxy)

TFLite INT8 использует int8=True с калибровочными данными.

Входы и выходы ONNX

LibreYOLO9

Тензорimages float32 [batch, 3, height, width]
ЦветRGB
Масштабированиепиксель / 255
Нормализациянет
Изменение размераletterbox, bilinear, значение заполнения 114, положение заполнения берется из ключа метаданных letterbox_pad

Scale by r = min(height / h, width / w), resize to (int(w * r), int(h * r)) and paste onto a canvas filled with 114.

Paste position comes from the letterbox_pad metadata key: topleft puts the image in the top-left corner, center splits the padding on both sides. A missing key means topleft.

Detection, экспорт по умолчанию
ВыходФормаСмысл
output[batch, 4 + nc, anchors]Rows 0 to 3 are x1, y1, x2, y2 in input-canvas pixels. Rows 4 onward are per-class scores, sigmoid already applied. anchors is the cell count over strides 8, 16 and 32, 8400 at 640 x 640.

Постобработка

  1. Transpose to [anchors, 4 + nc].
  2. Keep every (anchor, class) pair whose score is above the confidence threshold (0.25 by default). One anchor can yield several classes.
  3. Run NMS per class with IoU 0.45 and keep at most 300 detections.
  4. Map boxes back to the original image: subtract the pad offset, divide by r, clip to the image.
  5. Drop boxes whose width or height is 0 after clipping.
Detection, nms=True
ВыходФормаСмысл
output[1, max_det, 6]Rows are x1, y1, x2, y2, score, class in input-canvas pixels, zero-padded past the detection count. Confidence, IoU and max_det are baked in and recorded as nms_conf, nms_iou and max_det metadata.
raw[1, 4 + nc, anchors]The same tensor as the default export's output, before suppression.

Постобработка

  1. Drop rows whose score is 0 or below your threshold.
  2. Map boxes back to the original image: subtract the pad offset, divide by r, clip to the image.

LibreYOLO9E2E

Тензорimages float32 [batch, 3, height, width]
ЦветRGB
Масштабированиепиксель / 255
Нормализациянет
Изменение размераletterbox, bilinear, значение заполнения 114, положение заполнения берется из ключа метаданных letterbox_pad

Scale by r = min(height / h, width / w), resize to (int(w * r), int(h * r)) and paste onto a canvas filled with 114.

Paste position comes from the letterbox_pad metadata key: topleft puts the image in the top-left corner, center splits the padding on both sides. A missing key means topleft.

This model has no nms=True export. The exporter raises NotImplementedError, so only the default export below exists.

Detection, экспорт по умолчанию
ВыходФормаСмысл
output[batch, 4 + nc, anchors]Predictions of the one-to-one head only. Rows 0 to 3 are x1, y1, x2, y2 in input-canvas pixels. Rows 4 onward are per-class scores, sigmoid already applied. anchors is the cell count over strides 8, 16 and 32, 8400 at 640 x 640.

Постобработка

  1. Transpose to [anchors, 4 + nc].
  2. Flatten the [anchors, nc] scores into one list of anchors x nc (anchor, class) pairs. Pair i belongs to anchor i / nc (integer division) and class i % nc.
  3. Keep the 300 highest-scoring pairs (max_det), highest first. One anchor can yield several classes.
  4. Of those, keep the pairs whose score is above the confidence threshold (0.25 by default).
  5. Do not run NMS. The one-to-one head is trained to fire once per object, and LibreYOLO ignores the iou setting for this model.
  6. Map boxes back to the original image: subtract the pad offset, divide by r, clip to the image.
  7. Drop boxes whose width or height is 0 after clipping.

LibreYOLO9P2

Тензорimages float32 [batch, 3, height, width]
ЦветRGB
Масштабированиепиксель / 255
Нормализациянет
Изменение размераletterbox, bilinear, значение заполнения 114, положение заполнения берется из ключа метаданных letterbox_pad

Scale by r = min(height / h, width / w), resize to (int(w * r), int(h * r)) and paste onto a canvas filled with 114.

Paste position comes from the letterbox_pad metadata key: topleft puts the image in the top-left corner, center splits the padding on both sides. A missing key means topleft.

This model has no nms=True export. The exporter raises NotImplementedError, so only the default export below exists.

Detection, экспорт по умолчанию
ВыходФормаСмысл
output[batch, 4 + nc, anchors]Rows 0 to 3 are x1, y1, x2, y2 in input-canvas pixels. Rows 4 onward are per-class scores, sigmoid already applied. anchors is the cell count over strides 4, 8, 16 and 32, 34000 at 640 x 640. nc is 10 for LibreYOLO9P2s-visdrone.

Постобработка

  1. Transpose to [anchors, 4 + nc].
  2. Keep every (anchor, class) pair whose score is above the confidence threshold (0.25 by default). One anchor can yield several classes.
  3. Run NMS per class with IoU 0.45 and keep at most 300 detections.
  4. Map boxes back to the original image: subtract the pad offset, divide by r, clip to the image.
  5. Drop boxes whose width or height is 0 after clipping.

Чтобы проверить собственную реализацию, пропустите тот же файл через LibreYOLO: LibreYOLO("model.onnx").predict("image.jpg") возвращает эталонные результаты. Проверено на LibreYOLO 1.7.0.

Чекпойнты

Все опубликованные файлы весов этого семейства.

ФайлВход (пикс.)Лицензия весов
Detection
LibreYOLO9t.pt640mit
LibreYOLO9s.pt640mit
LibreYOLO9m.pt640mit
LibreYOLO9c.pt640mit
LibreYOLO9E2Et.pt640mit
LibreYOLO9E2Es.pt640mit
LibreYOLO9E2Em.pt640mit
LibreYOLO9E2Ec.pt640mit
LibreYOLO9P2s-visdrone.ptcc-by-nc-sa-3.0

Все перечисленные выше файлы уже доступны в организации LibreYOLO и скачиваются при первом использовании.

Лицензирование

Проверяйте лицензию в репозитории конкретных весов на Hugging Face. Она указана для каждого чекпойнта в организации LibreYOLO и может различаться даже внутри одного семейства. Этот репозиторий считается авторитетным источником, а сводка ниже описывает условия на момент последней проверки страницы.

Это описание соответствующих лицензий, а не юридическая консультация. Если ответ важен для коммерческого использования, прочитайте лицензии самостоятельно и проконсультируйтесь с юристом.

Оригинальная работа
YOLOv9, MultimediaTechLab
Лицензия исходного проекта
MIT
Исходный код проекта
github.com/MultimediaTechLab/YOLO
Код LibreYOLO
MIT
Веса
MIT, повторно опубликованы на huggingface.co/LibreYOLO
Толкование
MIT is a permissive license, so these weights can be used in commercial and closed-source products. The one standing obligation is to keep the license text and the copyright notice, Kin-Yiu Wong and Hao-Tang Tsui, with any copy you redistribute. It places no condition on your own application code, and a model you train yourself on your own data is yours. Two things are worth knowing beyond that. The code is ported from the authors' MIT re-release of YOLOv9, MultimediaTechLab/YOLO at commit c4cb5f6f, not the GPL-3.0 repository that carries the same model, so the permissive terms come from the source LibreYOLO actually derives from. And one checkpoint in this family is not MIT: the weight repository of the stride-4 VisDrone model, LibreYOLO9P2s-visdrone.pt, declares CC BY-NC-SA 3.0, which rules out commercial use and requires share-alike on derivatives.

Код всех трёх вариантов портирован из MultimediaTechLab/YOLO на коммите c4cb5f6f (MIT). Однозначный предиктор сквозной модели следует дизайну DATE Yiqun Chen (Apache-2.0), реализованному для LibreYOLO без копирования кода DATE. Уровень с шагом 4 — код LibreYOLO.

Чекпойнт для аэросъёмки с шагом 4 предсказывает классы VisDrone. Используйте лицензию, заявленную издателем в репозитории весов.

Цитирование

@inproceedings{wang2024yolov9,
      title={{YOLOv9}: Learning What You Want to Learn Using Programmable Gradient Information},
      author={Wang, Chien-Yao and Yeh, I-Hau and Liao, Hong-Yuan Mark},
      year={2024},
      booktitle={Proceedings of the European Conference on Computer Vision (ECCV)},
}

Скопировано из блока цитирования авторов на странице github.com/MultimediaTechLab/YOLO#citations.

Проверено с LibreYOLO v1.6.0. Таблицы поддержки, чекпойнты и результаты бенчмарков на этой странице сгенерированы из выпущенной библиотеки и опубликованных весов, а не написаны вручную.

Архитектура YOLOv9

Выберите вариант или обзор семейства, затем блок для просмотра подробностей. Откройте полную схему для увеличения или скачивания SVG и PNG. Схемы на английском языке.