Meet YOLO26: next-gen vision AI.

Link to this sectionПонимание сквозного (end-to-end) детектирования в Ultralytics YOLO26#

Link to this sectionВведение#

Если ты переходишь на YOLO26 с более ранней модели, такой как YOLOv8 или YOLO11, одно из самых больших изменений, которое ты заметишь, — это удаление Non-Maximum Suppression (NMS). Традиционные модели YOLO создают тысячи перекрывающихся предсказаний, для фильтрации которых до финальных результатов требуется отдельный этап постобработки NMS. Это увеличивает задержку, усложняет графы экспорта и может приводить к несогласованному поведению на разных аппаратных платформах.

В YOLO26 используется другой подход. Она выводит финальные результаты детектирования непосредственно из модели — внешняя фильтрация не требуется. Это называется сквозным object detection, и эта функция включена по умолчанию во всех моделях YOLO26. В результате ты получаешь более простой конвейер развертывания, меньшую задержку и до 43% более быстрое инференс на CPU.

Это руководство поможет тебе разобраться в изменениях, подскажет, нужно ли обновлять код, какие форматы экспорта поддерживают сквозной инференс и как плавно перейти со старых моделей YOLO.

Более подробный взгляд на мотивацию этого архитектурного сдвига можно найти в блоге Ultralytics о том, почему YOLO26 убирает NMS.

Краткая сводка
  • Используешь API или CLI от Ultralytics? Никаких изменений не требуется — просто замени имя модели на yolo26n.pt.
  • Используешь собственный код для инференса (ONNX Runtime, TensorRT и т.д.)? Обнови свою постобработку — выходной результат детектирования теперь имеет формат (N, 300, 6) в виде xyxy, NMS не требуется. Другие задачи добавляют дополнительные данные (коэффициенты маски, ключевые точки или угол).
  • Делаешь экспорт? Большинство форматов поддерживают сквозной вывод нативно. Однако несколько форматов (NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU и QNN) автоматически возвращаются к традиционному выводу из-за ограничений неподдерживаемых операторов (например, torch.topk). Рабочие процессы Hailo HEF компилируются из ONNX с помощью скриптов для Hailo, поэтому проверь настройки детектора и NMS для своей модели.

Link to this sectionКак работает сквозное детектирование#

В YOLO26 используется двухголовочная архитектура во время training. Обе головы разделяют одни и те же backbone и neck, но выдают результаты разными способами:

ГоловаЦельВыход детектированияПостобработка
One-to-One (по умолчанию)Сквозной инференс(N, 300, 6)Только порог уверенности
One-to-ManyТрадиционный выход YOLO(N, nc + 4, 8400)Требует NMS

Указанные выше формы предназначены для detection. Другие задачи расширяют выход one-to-one дополнительными данными для каждого детектирования:

ЗадачаСквозной выходДополнительные данные
Детекция(N, 300, 6)
Instance Segmentation(N, 300, 6 + nm) + proto (N, nm, H, W)nm коэффициенты маски (по умолчанию 32)
Pose(N, 300, 57)17 ключевых точек × 3 (x, y, видимость)
OBB(N, 300, 7)Угол поворота

Во время обучения обе головы работают одновременно — голова one-to-many обеспечивает более богатый обучающий сигнал, а голова one-to-one учится выдавать чистые, неперекрывающиеся предсказания. Во время inference и export по умолчанию активна только голова one-to-one, выдающая до 300 обнаружений на изображение в формате [x1, y1, x2, y2, confidence, class_id].

Когда ты вызываешь model.fuse(), это сворачивает слои Conv + BatchNorm для более быстрого инференса, а в сквозных моделях также удаляет голову one-to-many, уменьшая размер модели и FLOPs. Более подробную информацию о двухголовочной архитектуре см. на странице модели YOLO26.

Link to this sectionНужно ли мне менять свой код?#

Link to this sectionИспользование Python API или CLI от Ultralytics#

Изменения не нужны. Если ты используешь стандартный Ultralytics Python API или CLI, всё работает автоматически — prediction, validation и export поддерживают сквозные модели «из коробки».

Не требуется изменений кода при использовании Ultralytics API
from ultralytics import YOLO

# Load a YOLO26 model
model = YOLO("yolo26n.pt")

# Predict — no NMS step, no code changes
results = model.predict("image.jpg")

Link to this sectionИспользование собственного кода инференса#

Да, формат вывода другой. Если ты написал собственную логику постобработки для YOLOv8 или YOLO11 (например, при запуске инференса с помощью ONNX Runtime или TensorRT), тебе нужно будет обновить её, чтобы она обрабатывала новую форму вывода:

YOLOv8 / YOLO11YOLO26 (сквозной)
Выход детектирования(N, nc + 4, 8400)(N, 300, 6)
Формат боксаxywh (центр x, центр y, ширина, высота)xyxy (левый верхний x, левый верхний y, правый нижний x, правый нижний y)
РасположениеКоординаты бокса + оценки классов для каждого анкора[x1, y1, x2, y2, conf, class_id]
Требуется NMSДаНет
ПостобработкаNMS + фильтр уверенностиТолько фильтр уверенности

Для задач segmentation, pose и OBB YOLO26 добавляет данные, специфичные для задачи, к каждому обнаружению — см. таблицу выходных форм выше.

Где N — это batch size, а nc — количество классов (например, 80 для COCO).

Со сквозными моделями постобработка становится намного проще — например, при использовании ONNX Runtime:

import onnxruntime as ort

# Load and run the exported end-to-end model
session = ort.InferenceSession("yolo26n.onnx")
output = session.run(None, {session.get_inputs()[0].name: input_tensor})

# End-to-end output: (batch, 300, 6) → [x1, y1, x2, y2, confidence, class_id]
detections = output[0][0]  # first image in batch
detections = detections[detections[:, 4] > conf_threshold]  # confidence filter — that's it!

Link to this sectionПереключение на голову One-to-Many#

Если тебе нужен традиционный формат вывода YOLO (например, чтобы повторно использовать существующий код постобработки на основе NMS), ты можешь переключиться на голову one-to-many в любое время, установив end2end=False:

Использование головы one-to-many для традиционного вывода на основе NMS
from ultralytics import YOLO

model = YOLO("yolo26n.pt")

# Prediction with NMS (traditional behavior)
results = model.predict("image.jpg", end2end=False)

# Validation with NMS
metrics = model.val(data="coco.yaml", end2end=False)

# Export without end-to-end
model.export(format="onnx", end2end=False)

Link to this sectionСовместимость форматов экспорта#

Большинство export formats поддерживают сквозной инференс из коробки, включая ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js и MNN.

Следующие форматы не поддерживают сквозной режим и автоматически возвращаются к голове one-to-many: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU и Qualcomm QNN.

Что происходит, когда сквозной режим не поддерживается

Когда ты экспортируешь в один из этих форматов, Ultralytics автоматически переключается на голову one-to-many и записывает предупреждение — ручное вмешательство не требуется. Это означает, что тебе потребуется NMS в твоем конвейере инференса для этих форматов, так же как в YOLOv8 или YOLO11.

Для Hailo HEF этап компиляции происходит вне model.export(format=...) после экспорта ONNX. Используй логи Hailo DFC, скрипт модели .alls и NMS JSON, соответствующие твоей модели детектирования; если сквозной граф YOLO26 не поддерживается твоей цепочкой инструментов Hailo, экспортируй модель ONNX с end2end=False и скомпилируй традиционную голову детектирования.

TensorRT + INT8

TensorRT поддерживает сквозной режим, но он автоматически отключается при экспорте с int8=True на TensorRT 10.3.0 в JetPack 6.

Link to this sectionКомпромиссы точности и скорости#

Сквозное детектирование дает значительные преимущества при развертывании при минимальном влиянии на accuracy:

МетрикаСквозной (по умолчанию)One-to-Many + NMS (end2end=False)
Скорость инференса на CPUДо 43% быстрееБазовая линия
Влияние на mAP~0.5 mAP нижеРавен или превосходит YOLO11
ПостобработкаТолько фильтр уверенностиПолный конвейер NMS
Сложность развертыванияМинимальнаяТребует реализации NMS

Для большинства реальных приложений разница в ~0.5 mAP незначительна, особенно если учитывать выигрыш в скорости и простоте. Если максимальная точность — твой главный приоритет, ты всегда можешь вернуться к голове one-to-many, используя end2end=False.

Смотри показатели производительности YOLO26 для подробных бенчмарков по всем размерам моделей (n, s, m, l, x).

Link to this sectionМиграция с YOLOv8 или YOLO11#

Если ты обновляешь существующий проект до YOLO26, вот краткий список для обеспечения плавного перехода:

  • Пользователи Ultralytics API / CLI: Изменения не нужны — просто обнови имя модели до yolo26n.pt (или yolo26n-seg.pt, yolo26n-pose.pt, yolo26n-obb.pt)
  • Собственный код постобработки: Обнови его для работы с новыми формами вывода — (N, 300, 6) для детектирования плюс данные по конкретной задаче для segmentation, pose и OBB. Также обрати внимание на изменение формата бокса с xywh на xyxy
  • Конвейеры экспорта: Проверь раздел совместимости форматов выше для целевого формата
  • TensorRT + INT8: На JetPack 6 TensorRT 10.3.0 автоматически отключает сквозной режим при int8=True — используй другую версию TensorRT, чтобы сохранить сквозной режим
  • Экспорт FP16: Если тебе нужны все выходы в FP16, экспортируй с end2end=False — см. почему output0 остается FP32
  • iOS / CoreML: Сквозной режим полностью поддерживается. Если тебе нужна поддержка предварительного просмотра в Xcode, используй end2end=False с nms=True
  • Edge-устройства (NCNN, RKNN): Эти форматы автоматически возвращаются к one-to-many, поэтому включи NMS в свой конвейер на устройстве

Link to this sectionFAQ#

Link to this sectionМогу ли я использовать end2end=True и nms=True вместе?#

Нет. Эти опции взаимоисключающие. Если ты установишь nms=True для сквозной модели во время export, она будет автоматически принудительно установлена в nms=False с предупреждением. Сквозная голова уже обрабатывает фильтрацию дубликатов внутри себя, поэтому внешняя NMS не нужна.

Однако комбинация end2end=False и nms=True является допустимой конфигурацией — она встраивает традиционную NMS в граф экспорта. Это может быть полезно для экспорта в CoreML, поскольку позволяет напрямую использовать функцию предварительного просмотра в Xcode с моделью детектирования.

Link to this sectionЗа что отвечает параметр max_det в end-to-end моделях?#

Параметр max_det (по умолчанию: 300) задает максимальное количество обнаружений, которое «one-to-one» голова может выдать на изображение. Ты можешь настроить его во время вывода (inference) или экспорта:

model.predict("image.jpg", max_det=100)  # fewer detections, slightly faster
model.export(format="onnx", max_det=500)  # more detections for dense scenes

Обрати внимание, что стандартные чекпоинты YOLO26 были обучены с max_det=300. Хотя ты можешь увеличить это значение, «one-to-one» голова была оптимизирована в процессе обучения для создания до 300 качественных обнаружений, поэтому результаты сверх этого лимита могут быть более низкого качества. Если тебе нужно более 300 обнаружений на изображение, рассмотри возможность переобучения с более высоким значением max_det.

Link to this sectionМоя экспортированная модель ONNX выдает (1, 300, 6) — это правильно?#

Да, это ожидаемый формат вывода end-to-end для детекции: размер пакета 1, до 300 обнаружений, каждое из которых содержит 6 значений [x1, y1, x2, y2, confidence, class_id]. Просто отфильтруй их по порогу достоверности (confidence threshold) — и готово, NMS больше не нужен.

Для других задач форма вывода отличается:

ЗадачаФорма выводаОписание
Детектирование(1, 300, 6)[x1, y1, x2, y2, conf, class_id]
Сегментация(1, 300, 38) + (1, 32, 160, 160)6 значений рамки + 32 коэффициента маски, плюс тензор прототипов масок
Поза(1, 300, 57)6 значений рамки + 17 ключевых точек × 3 (x, y, видимость)
OBB(1, 300, 7)6 значений рамки + 1 угол поворота

Link to this sectionКак проверить, является ли моя экспортированная модель end-to-end?#

Ты можешь проверить это с помощью Python API Ultralytics или напрямую просмотрев метаданные экспортированной модели ONNX:

Проверка модели на end-to-end
from ultralytics import YOLO

model = YOLO("yolo26n.onnx")
model.predict(verbose=False)  # run predict to setup predictor first
print(model.predictor.model.end2end)  # True if end-to-end is enabled

Или проверь форму вывода — end-to-end модели детекции выводят (1, 300, 6), в то время как традиционные модели выводят (1, nc + 4, 8400). Информацию о формах для других задач смотри в FAQ по формам вывода.

Link to this sectionПоддерживается ли end-to-end для задач сегментации экземпляров, оценки позы и OBB?#

Да. Варианты задач в стиле детекции YOLO26 — детекция, сегментация экземпляров, оценка позы и ориентированная детекция объектов (OBB) — поддерживают end-to-end вывод по умолчанию. Резервный вариант end2end=False также доступен для всех этих задач.

Каждая задача дополняет базовый вывод детекции данными, специфичными для задачи:

ЗадачаМодельСквозной выход
Детектированиеyolo26n.pt(N, 300, 6)
Сегментация экземпляровyolo26n-seg.pt(N, 300, 38) + прототип (N, 32, 160, 160)
Позаyolo26n-pose.pt(N, 300, 57)
OBByolo26n-obb.pt(N, 300, 7)

Комментарии