理解 Ultralytics YOLO26 中的端到端检测
介绍
If you're upgrading to YOLO26 from an earlier model like YOLOv8 or YOLO11, one of the biggest changes you'll notice is the removal of Non-Maximum Suppression (NMS). Traditional YOLO models produce thousands of overlapping predictions that need a separate NMS post-processing step to filter down to final detections. This adds latency, complicates export graphs, and can behave inconsistently across different hardware platforms.
YOLO26 采用了不同的方法。它直接从模型输出最终检测结果,无需外部筛选。这就是所谓的端到端 目标检测,并且在所有 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) 由于不受支持的算子限制(例如
torch.topk),会自动回退到传统输出。
端到端检测的工作原理
YOLO26 在 训练 期间使用了双头架构。两个头共享相同的骨干网络 (backbone) 和颈部 (neck),但以不同的方式产生输出:
| 头 (Head) | 目的 | 检测输出 | 后处理 |
|---|---|---|---|
| 一对一 (One-to-One) (默认) | 端到端推理 | (N, 300, 6) | 仅置信度阈值过滤 |
| 一对多 (One-to-Many) | 传统 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) | 旋转角度 |
在训练期间,两个头同时运行——一对多头提供更丰富的学习信号,而一对一头则学习产生干净、无重叠的预测。在 推理 和 导出 过程中,默认仅激活 一对一头,每张图像最多生成 300 个检测结果,格式为 [x1, y1, x2, y2, confidence, class_id]。
当你调用 model.fuse() 时,它会融合 Conv + BatchNorm 层以实现更快的推理,并且在端到端模型上,还会移除一对多头——从而减小模型大小并降低 FLOPs。有关双头架构的更多详细信息,请参阅 YOLO26 模型页面。
我需要更改我的代码吗?
使用 Ultralytics Python API 或 CLI
无需更改。 如果你使用标准的 Ultralytics Python API 或 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")使用自定义推理代码
是的,输出格式不同。 如果你为 YOLOv8 或 YOLO11 编写了自定义后处理逻辑(例如,在使用 ONNX Runtime 或 TensorRT 进行推理时),你需要对其进行更新以处理新的输出形状:
| YOLOv8 / YOLO11 | YOLO26 (端到端) | |
|---|---|---|
| 检测输出 | (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 会在每个检测结果后附加任务特定的数据——请参阅上面的 输出形状表格。
其中 N 是 批次大小,nc 是类别数量(例如,COCO 为 80)。
使用端到端模型时,后处理变得简单得多——例如,使用 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!切换到一对多头
如果你需要传统的 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)导出格式兼容性
大多数 导出格式 都原生支持端到端推理,包括 ONNX、TensorRT、CoreML、OpenVINO、TFLite、TF.js 和 MNN。
以下格式 不支持 端到端,并会自动回退到一对多头:NCNN、RKNN、PaddlePaddle、ExecuTorch、IMX 和 Edge TPU。
TensorRT 支持端到端,但在 TensorRT ≤10.3.0 版本上使用 int8=True 导出时,它会被 自动禁用。
精度与速度的权衡
端到端检测提供了显著的部署优势,且对 精度 的影响极小:
| 指标 | 端到端 (默认) | 一对多 + 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),外加 分割、姿态估计 和 OBB 的任务特定数据。还要注意框格式从xywh到xyxy的变化 - 导出流水线: 检查上述 格式兼容性 部分以获取你的目标格式信息
- TensorRT + INT8: 验证你的 TensorRT 版本是否 >10.3.0 以获得端到端支持
- FP16 导出: 如果你需要所有输出为 FP16,请使用
end2end=False导出——请参阅 为什么 output0 在使用 half=True 和 end2end=True 导出时保持 FP32 - iOS / CoreML: 完全支持端到端。如果你需要 Xcode 预览支持,请使用
end2end=False配合nms=True - 边缘设备 (NCNN, RKNN): 这些格式会自动回退到一对多,因此请在设备端流水线中包含 NMS
常见问题 (FAQ)
我能同时使用 end2end=True 和 nms=True 吗?
No. These options are mutually exclusive. If you set nms=True on an end-to-end model during export, it will be automatically forced to nms=False with a warning. The end-to-end head already handles duplicate filtering internally, so external NMS is unnecessary.
但是,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 个掩码系数,外加一个原型掩码张量 |
| 姿态 | (1, 300, 57) | 6 个框值 + 17 个关键点 × 3(x, y, 可见性) |
| OBB | (1, 300, 7) | 6 个框值 + 1 个旋转角度 |
如何检查我的导出模型是否为端到端?
你可以使用 Ultralytics Python API,或者直接检查导出的 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或者,检查输出形状——端到端检测模型的输出为 (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) |
| OBB | yolo26n-obb.pt | (N, 300, 7) |