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

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

Введение

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

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

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

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

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

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

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

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

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

Приведенные выше фигуры используются для распознавания. Другие задачи расширяют однозначный вывод, добавляя дополнительные данные для каждого распознавания:

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

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

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

Мне нужно изменить свой код?

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

Изменений не требуется. Если вы используете стандартный 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 .3.0.

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

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

МетрикаОт начала до конца (по умолчанию)«Один ко многим» + NMSend2end=False)
Скорость CPUНа 43 % быстрееБазовая линия
mAPна ~0,5 mAPСоответствует или превосходит YOLO11
ПостобработкаТолько фильтр достоверностиПолный NMS
Сложность развертыванияМинимальныйТребуется NMS

Для большинства реальных приложений значение ~0,5 mAP Разница незначительна, особенно если учесть выигрыш в скорости и простоте. Если максимальная точность является вашим главным приоритетом, вы всегда можете вернуться к использованию головки «один ко многим» с помощью end2end=False.

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

Переход с YOLOv8 YOLO11

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

  • CLI Ultralytics / CLI Ultralytics : Изменений не требуется — просто обновите название модели на yolo26n.pt (или yolo26n-seg.pt, yolo26n-pose.pt, yolo26n-obb.pt)
  • Пользовательский код постобработки: Обновление для поддержки новых форматов вывода — (N, 300, 6) для обнаружения, а также данные, относящиеся к конкретным задачам, для сегментация, 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 с предупреждением. Концентратор «end-to-end» уже обеспечивает фильтрацию дубликатов на внутреннем уровне, поэтому внешняя NMS не NMS .

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

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

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

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

Моя экспортированная ONNX выдает (1, 300, 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 коэффициента маски, а также tensor прототипной маски
Поза(1, 300, 57)6 значений ячеек + 17 ключевых точек × 3 (x, y, видимость)
OBB(1, 300, 7)6 значений положения + 1 угол поворота

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

Вы можете проверить это с помощьюPython 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). О других формах задач см. Часто задаваемые вопросы о формах выходного сигнала.

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

Да. Все варианты задач YOLO26 — обнаружение, сегментация, оценка позыи ориентированное обнаружение объектов (OBB) — по умолчанию поддерживают сквозную инференцию. 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)


📅 Создано 0 дней назад ✏️ Обновлено 0 дней назад
raimbekovm

Комментарии