YOLO Vision 2026:

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

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

Это называется сквозным обнаружением объектов, и оно включено по умолчанию. Результатом является более простой конвейер развертывания и меньшая задержка — YOLO26n работает до на 43% быстрее, чем YOLO11n при инференсе ONNX на CPU (Intel Xeon CPU @ 2.00 GHz).

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

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

Краткая сводка
  • Используешь API или CLI от Ultralytics? Никаких изменений не требуется — просто замени имя модели на yolo26n.pt.
  • Используешь собственный код инференса (ONNX Runtime, TensorRT и т. д.)? Обнови свою постобработку: вывод детекции теперь имеет формат (N, 300, 6) в виде xyxy, NMS не требуется. Для других задач добавляются дополнительные данные (коэффициенты масок, ключевые точки или углы).
  • Экспортируешь? Большинство форматов сохраняют сквозной вывод нативно; некоторые возвращаются к традиционному выводу, а квантование может отключить его — см. Совместимость форматов экспорта.

Как работает сквозное детектирование#

Во время обучения YOLO26 использует архитектуру с двумя головами (dual-head). Обе головы используют общие бэкбон и нек, но выдают результаты по-разному:

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

Формы выше указаны для детекции, где N — это размер батча, nc — количество классов (например, 80 для COCO), а количество якорей 8400 — это значение в imgsz=640. Другие задачи расширяют вывод «один к одному» дополнительными данными для каждого обнаружения:

ЗадачаСквозной выходДополнительные данные
Детектирование(N, 300, 6)
Сегментация экземпляров(N, 300, 6 + nm) + прото (N, nm, H, W)коэффициенты масок nm (по умолчанию 32)
Pose(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.

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

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

Никаких изменений не требуется. Если ты используешь стандартный Python API Ultralytics или CLI, все работает автоматически — предикты, валидация и экспорт работают со сквозными моделями «из коробки».

Не требуется изменений кода при использовании 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")

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

Да, формат вывода отличается. Если ты написал собственную логику постобработки для 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 + фильтр уверенностиТолько фильтр уверенности

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

Со сквозными моделями постобработка становится намного проще — например, при использовании 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] > 0.25]  # confidence filter, no NMS

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

Если тебе нужен традиционный формат вывода YOLO (например, для повторного использования существующего кода постобработки на основе NMS), ты можешь переключиться на голову один-ко-многим (если она доступна), установив 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)

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

Большинство форматов экспорта поддерживают сквозной инференс «из коробки», включая ONNX, TensorRT, CoreML, OpenVINO, LiteRT и MNN.

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

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

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

Для Hailo экспортер выбирает путь вывода из загруженной головы, а не из аргумента, поэтому end2end отклоняется, если передан: модель детекции YOLO26 по умолчанию сохраняет свои выходы «один к одному» без NMS, в то время как контрольная точка, голова которой уже end2end=False, компилирует традиционный путь с HailoRT NMS.

Квантование и версия рантайма могут отключать сквозной режим

TensorRT и LiteRT поддерживают сквозной режим, но эта ветка автоматически отключается на TensorRT старше 8.5.0, на TensorRT 10.3.0 с quantize=8 на JetPack 6 и на LiteRT с quantize=8 или quantize="w8a16". В каждом случае записывается предупреждение, и экспортируется голова «один ко многим».

Компромиссы между точностью и скоростью#

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

МетрикаСквозной (по умолчанию)Один-ко-многим + NMS (end2end=False)
COCO mAPvalна 0.6-0.8 нижеБазовая линия
ПостобработкаТолько фильтр уверенностиПолный конвейер NMS
Сложность развертыванияМинимальнаяТребует реализации NMS

Для пяти масштабов детекции голова «один к одному» стоит 0.6-0.8 mAP на COCO — от 40.9 до 40.1 для YOLO26n и от 57.5 до 56.9 для YOLO26x — в обмен на полный отказ от прохода NMS. Если максимальная точность является твоим приоритетом, вернись к голове «один ко многим» с end2end=False.

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

Миграция с YOLOv8 или YOLO11#

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

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

Заключение#

Сквозное обнаружение является дефолтным в YOLO26 и не требует изменения кода, если ты используешь Python API Ultralytics или CLI. Обновление требуется только для собственных конвейеров постобработки, чтобы считывать новый выход (N, 300, 6) и пропускать шаг NMS (за исключением форматов экспорта, которые возвращаются к выводу один-ко-многим, таких как NCNN и RKNN, где NMS на устройстве все еще необходим). Подробные бенчмарки скорости и точности для всех размеров моделей см. на странице модели YOLO26, а полный набор опций и форматов экспорта описан в документации по режиму экспорта.

FAQ#

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

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

  • Параметр max_det (по умолчанию: 300) задает максимальное количество обнаружений, возвращаемых для одного изображения. Ты можешь изменить его во время инференса или экспорта:

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

    Значение зашивается в экспортированный граф как top-k головы, поэтому max_det=500 расширяет выходной тензор до (1, 500, 6), ограниченного количеством якорей.

  • Да, это ожидаемый формат сквозного вывода для детекции: размер батча 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 угол поворота
  • Ты можешь проверить это из 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

    Эти две проверки отвечают на разные вопросы: метаданные ONNX фиксируют голову, которая была экспортирована, в то время как predictor.model.end2end сообщает, что вывод бэкенда уже обработан и не требует внешней NMS. Они расходятся для модели, экспортированной с end2end=False, nms=True, которая использует голову «один ко многим», но зашивает NMS в граф, а также выводит (1, 300, 6) — поэтому ни флаг, ни форма вывода по отдельности не идентифицируют голову. Информацию о формах других задач см. в разделе часто задаваемых вопросов о формах вывода.

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

    Каждая задача расширяет базовый вывод детекции данными, специфичными для задачи; формы вывода yolo26n.pt, yolo26n-seg.pt, yolo26n-pose.pt и yolo26n-obb.pt перечислены в разделе Как работает сквозная детекция.

Комментарии