Перейти к содержанию

Понимание сквозного обнаружения в Ultralytics YOLO26

Введение

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

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

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

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

Краткое резюме

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

Как работает сквозное обнаружение

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

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

Приведенные выше формы предназначены для detect. Другие задачи расширяют вывод «один-к-одному» дополнительными данными для каждого detect:

ЗадачаСквозной выводДополнительные данные
Обнаружение(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)Угол поворота

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

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

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

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

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

При использовании Ultralytics не требуется вносить изменения в код

from ultralytics import YOLO

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

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

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

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

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

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

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

С помощью сквозных моделей постобработка значительно упрощается — например, при использовании ONNX :

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!

Переключение на детектирующую голову один-ко-многим

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

Использование разъема «один ко многим» для традиционного вывода 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)
yolo predict model=yolo26n.pt source=image.jpg end2end=False
yolo val model=yolo26n.pt data=coco.yaml end2end=False
yolo export model=yolo26n.pt format=onnx end2end=False

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

Большинство форматов экспорта изначально поддерживают сквозное вычисление, в том числе ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js и MNN.

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

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

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

TensorRT + INT8

TensorRT поддерживает сквозное обнаружение, но оно автоматически отключается при экспорте с использованием int8=True на TensorRT ≤10.3.0.

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

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

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

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

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

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

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

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

Часто задаваемые вопросы

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

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

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

Что контролирует параметр max_det в сквозных моделях?

Параметр max_det параметр (по умолчанию: 300) устанавливает максимальное количество detect, которое может выводить голова «один к одному» на изображение. Вы можете настроить его во время инференса или экспорта:

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. Хотя вы можете увеличить это значение, голова «один к одному» была оптимизирована во время обучения для получения до 300 чистых detect, поэтому detect за пределами этого лимита могут быть более низкого качества. Если вам требуется более 300 detect на изображение, рассмотрите возможность переобучения с более высоким значением max_det значением.

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

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

Как мне проверить, является ли моя экспортированная модель сквозной?

Вы можете проверить, используя либо API Ultralytics Python, либо непосредственно инспектируя метаданные экспортированной модели 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
import onnxruntime as ort

session = ort.InferenceSession("yolo26n.onnx")
metadata = session.get_modelmeta().custom_metadata_map
print(metadata.get("end2end"))  # 'True' if end-to-end is enabled

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

Поддерживается ли сквозной режим для задач segment, оценки позы и obb?

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

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

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


📅 Создано 12 дней назад ✏️ Обновлено 10 дней назад
glenn-jocherraimbekovm

Комментарии