Link to this sectionПонимание сквозного обнаружения в Ultralytics YOLO26#
Link to this sectionВведение#
Если ты переходишь на YOLO26 с более ранней модели, такой как YOLOv8 или YOLO11, одно из самых больших изменений, которое ты заметишь, — это удаление Non-Maximum Suppression (NMS). Традиционные модели YOLO создают тысячи перекрывающихся предсказаний, для фильтрации которых до финальных результатов обнаружения требуется отдельный этап постобработки NMS. Это увеличивает задержку, усложняет графы экспорта и может приводить к несогласованному поведению на различных аппаратных платформах.
YOLO26 использует другой подход. Она выдает финальные результаты обнаружения напрямую из модели — внешняя фильтрация не требуется. Это называется сквозным object detection, и данная функция включена по умолчанию во всех моделях YOLO26. В результате конвейер развертывания становится проще, задержка ниже, а скорость вывода на CPU выше до 43%.
Это руководство поможет тебе понять, что изменилось, нужно ли обновлять твой код, какие форматы экспорта поддерживают сквозной вывод и как плавно перейти с более старых моделей YOLO.
Для более глубокого понимания мотивации этого архитектурного сдвига ознакомься с блоге Ultralytics о том, почему YOLO26 удаляет NMS.
- Используешь Ultralytics API или CLI? Изменения не требуются — просто замени имя модели на
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 использует двухголовую архитектуру во время обучения. Обе головы используют общие backbone и neck, но выдают результаты разными способами:
| Голова | Назначение | Выход обнаружения | Постобработка |
|---|---|---|---|
| Один-к-одному (по умолчанию) | Сквозной вывод | (N, 300, 6) | Только порог уверенности |
| Один-ко-многим | Традиционный выход YOLO | (N, nc + 4, 8400) | Требует NMS |
Указанные выше размерности относятся к обнаружению. Другие задачи расширяют выход один-к-одному дополнительными данными для каждого обнаруженного объекта:
| Задача | Сквозной выход | Дополнительные данные |
|---|---|---|
| Обнаружение | (N, 300, 6) | — |
| Сегментация экземпляров | (N, 300, 6 + nm) + proto (N, nm, H, W) | Коэффициенты маски nm (по умолчанию 32) |
| Позы | (N, 300, 57) | 17 ключевых точек × 3 (x, y, видимость) |
| OBB | (N, 300, 7) | Угол поворота |
Во время обучения обе головы работают одновременно — голова один-ко-многим предоставляет более богатый сигнал обучения, в то время как голова один-к-одному учится создавать чистые, неперекрывающиеся предсказания. Во время вывода и экспорта активна только голова один-к-одному по умолчанию, выдавая до 300 обнаружений на изображение в формате [x1, y1, x2, y2, confidence, class_id].
Когда ты вызываешь model.fuse(), это объединяет слои Conv + BatchNorm для более быстрого вывода, а в моделях со сквозным обнаружением также удаляет голову один-ко-многим, сокращая размер модели и количество FLOPs. Более подробную информацию о двухголовой архитектуре смотри на странице модели YOLO26.
Link to this sectionНужно ли мне менять свой код?#
Link to this sectionИспользование Python API или CLI от Ultralytics#
Изменения не требуются. Если ты используешь стандартный Python API Ultralytics или CLI, все работает автоматически — предсказание, валидация и экспорт поддерживают сквозные модели «из коробки».
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 / YOLO11 | YOLO26 (сквозное) | |
|---|---|---|
| Выход обнаружения | (N, nc + 4, 8400) | (N, 300, 6) |
| Формат bbox | xywh (центр x, центр y, ширина, высота) | xyxy (верхний левый x, верхний левый y, нижний правый x, нижний правый y) |
| Расположение | Координаты bbox + оценки классов для каждого якоря | [x1, y1, x2, y2, conf, class_id] |
| Требуется NMS | Да | Нет |
| Постобработка | NMS + фильтр уверенности | Только фильтр уверенности |
Для задач сегментации, поз и OBB YOLO26 добавляет специфические для задачи данные к каждому обнаружению — см. таблицу выходных форм выше.
Где N — это размер пакета, а 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Переключение на голову один-ко-многим#
Если тебе нужен традиционный формат вывода YOLO (например, для повторного использования существующего кода постобработки на основе NMS), ты можешь в любой момент переключиться на голову один-ко-многим, установив end2end=False:
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Совместимость форматов экспорта#
Большинство форматов экспорта поддерживают сквозной вывод «из коробки», включая ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js и MNN.
Следующие форматы не поддерживают сквозное обнаружение и автоматически возвращаются к голове один-ко-многим: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU и Qualcomm QNN.
Для Hailo HEF этап компиляции происходит вне model.export(format=...) после экспорта в ONNX. Используй логи Hailo DFC, скрипт модели .alls и JSON с NMS, которые соответствуют твоей конкретной модели обнаружения; если сквозной граф YOLO26 не поддерживается твоим инструментарием Hailo, экспортируй модель ONNX с параметром end2end=False и скомпилируй традиционную голову обнаружения.
TensorRT поддерживает сквозное обнаружение, но оно автоматически отключается при экспорте с int8=True в версиях TensorRT ≤10.3.0.
Link to this sectionКомпромиссы между точностью и скоростью#
Сквозное обнаружение обеспечивает значительные преимущества при развертывании с минимальным влиянием на точность:
| Показатель | Сквозное (по умолчанию) | Один-ко-многим + NMS (end2end=False) |
|---|---|---|
| Скорость вывода на CPU | До 43% быстрее | Базовый уровень |
| Влияние на mAP | ~0.5 mAP ниже | Соответствует или превышает YOLO11 |
| Постобработка | Только фильтр уверенности | Полный конвейер NMS |
| Сложность развертывания | Минимальная | Требует реализации NMS |
Для большинства реальных приложений разница в ~0.5 mAP пренебрежимо мала, особенно если учесть выигрыш в скорости и простоте. Если максимальная точность — твой главный приоритет, ты всегда можешь вернуться к голове один-ко-многим, используя 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)для обнаружения плюс специфические для задач данные для сегментации, поз и OBB. Также обрати внимание на изменение формата bbox сxywhнаxyxy - Конвейеры экспорта: Проверь раздел совместимости форматов выше для твоего целевого формата
- TensorRT + INT8: Убедись, что твоя версия TensorRT выше 10.3.0 для поддержки end-to-end.
- Экспорт в FP16: Если тебе нужны все выходные данные в FP16, используй экспорт с
end2end=False— см. почему output0 остается в FP32. - iOS / CoreML: End-to-end поддерживается полностью. Если тебе нужна поддержка Xcode Preview, используй
end2end=Falseвместе сnms=True. - Периферийные устройства (NCNN, RKNN): Эти форматы автоматически переключаются на режим one-to-many, поэтому включай NMS в свой конвейер на устройстве.
Link to this sectionFAQ#
Link to this sectionМожно ли использовать end2end=True и nms=True одновременно?#
Нет. Эти опции взаимоисключающие. Если ты установишь nms=True для end-to-end модели во время экспорта, значение будет автоматически изменено на nms=False с предупреждением. Внутренний механизм end-to-end уже выполняет фильтрацию дубликатов, поэтому внешняя NMS не нужна.
Тем не менее, комбинация end2end=False и nms=True является допустимой конфигурацией — она встраивает традиционную NMS в граф экспорта. Это может быть полезно для экспорта в CoreML, так как позволяет использовать функцию Preview в Xcode напрямую с моделью детектирования.
Link to this sectionЗа что отвечает параметр max_det в end-to-end моделях?#
Параметр max_det (по умолчанию: 300) задает максимальное количество детектирований, которое «голова» модели one-to-one может выдать для одного изображения. Ты можешь настроить его во время инференса или экспорта:
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]. Просто отфильтруй результаты по порогу достоверности, и все готово — 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 модели напрямую:
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) + proto (N, 32, 160, 160) |
| Поза | yolo26n-pose.pt | (N, 300, 57) |
| OBB | yolo26n-obb.pt | (N, 300, 7) |