首页
/ 使用 LibTorch 在 C++ 中部署运行 Ultralytics YOLO:零配置多任务推理实战指南

使用 LibTorch 在 C++ 中部署运行 Ultralytics YOLO:零配置多任务推理实战指南

2026-09-08 20:49:21作者:凌朦慧Richard

本指南以 examples/cpp/LibTorch 示例为线索,讲解如何用 PyTorch 官方 C++ API(LibTorch)与 OpenCV 编写一个支持 YOLOv8 / YOLO11 / YOLO26 全部任务(目标检测、实例分割、姿态估计、旋转框 OBB、图像分类与语义分割)的本地推理程序。读完本文你将掌握 TorchScript 模型的导出、CMake 工程搭建、基于模型元数据的"零配置"加载,以及从张量输出到可视化结果的完整 C++ 实现链路。

示例概览:它解决了什么问题

Ultralytics YOLO 的推理通常以 Python 调用为主,但生产级边缘设备与桌面应用常常需要把模型嵌入 C++ 程序。仓库在 examples/cpp/LibTorch 下提供了一套完整的 C++ 应用:它把任意已导出的 .torchscript 模型作为输入,自动从模型自身携带的元数据读取任务类型、类别名与输入尺寸,并自动选择对应的后处理逻辑,无需任何手工配置。

该示例目录结构如下:

  • main.cc:命令行入口,负责解析参数、读图、调用推理与输出结果;
  • inference.hinference.cc:核心 Predictor 类,封装模型加载、元数据解析与前向推理;
  • CMakeLists.txt:基于 CMake 的构建脚本;
  • examples/cpp/common:所有 C++ 示例共享的纯头文件工具集,包括统一结果类型、CLI 参数解析、前后处理与画图逻辑(本示例通过 include 路径自动引入)。

核心特性

  1. 覆盖全部任务:detect(目标检测)、segment(实例分割)、pose(姿态估计)、OBB(旋转框)、classify(图像分类),以及 YOLO26 的 semantic(语义分割),对应文档见 docs/en/tasks/detect.mdsegment.mdpose.mdobb.mdclassify.mdsemantic.md
  2. 覆盖全部模型代际:Ultralytics YOLOv8、YOLO11 与 YOLO26(对应 docs/en/models/yolov8.mdyolo11.mdyolo26.md),并且能自动识别传统 grid 输出(YOLOv8/11)与 YOLO26 的 end-to-end(端到端)输出布局,无需手工指定。
  3. 零配置:任务类型、类别名与 imgsz(推理输入尺寸)全部来自 Ultralytics 导出时内嵌进 TorchScript 的 config.txt 元数据。

依赖要求

依赖 最低版本 说明
OpenCV >= 4.0.0 图像读写、预处理、后处理(NMS)与标注绘制
C++ 标准 >= 17 CMake 中以 CMAKE_CXX_STANDARD 17 强制启用
CMake >= 3.18 构建系统,与示例中 cmake_minimum_required 一致
LibTorch >= 1.12.1 PyTorch 的 C++ 发行版,提供 torch::jit 推理 API

LibTorch 需要从 PyTorch 官网按操作系统与 CUDA 版本选择下载。若使用 GPU 推理,下载的 LibTorch 必须与你的 CUDA 环境匹配,否则 --cuda 无法生效。

第一步:把模型导出为 TorchScript

TorchScript 是 PyTorch 的序列化模型格式,可脱离 Python 环境由 LibTorch 直接加载。使用 Ultralytics 的 export 模式即可导出任意任务、任意代际的模型:

yolo export model=yolo26n.pt imgsz=640 format=torchscript # detect 检测
yolo export model=yolo26n-seg.pt imgsz=640 format=torchscript # 实例分割
yolo export model=yolo26n-pose.pt imgsz=640 format=torchscript # 姿态估计
yolo export model=yolo26n-obb.pt imgsz=640 format=torchscript # 旋转框 OBB
yolo export model=yolo26n-cls.pt imgsz=640 format=torchscript # 图像分类
yolo export model=yolo26n-sem.pt imgsz=640 format=torchscript # 语义分割(YOLO26)

更完整的导出参数说明可参阅 docs/en/modes/export.md。YOLOv8 / YOLO11 的 grid 模型同样适用,其输出布局会在运行时被自动识别。

导出时内嵌的 config.txt 元数据

这一"零配置"能力的源头在导出实现中:仓库的 ultralytics/utils/export/torchscript.py 会先把元数据字典序列化为 JSON,再作为额外文件 config.txt 随模型一起保存:

extra_files = {"config.txt": json.dumps(metadata or {})}  # torch._C.ExtraFilesMap()
ts.save(output_file, _extra_files=extra_files)

这份元数据由 ultralytics/engine/exporter.py 在导出时构造,包含 tasknames(类别字典)、imgszstrideend2end(是否为端到端输出)等关键字段。推理端只需把同一份 JSON 原样取出即可实现"拿到什么模型就按它的配置跑"。

第二步:编译构建

仓库中提供了完整的 CMakeLists.txt。构建步骤如下:

git clone https://github.com/ultralytics/ultralytics.git
cd ultralytics/examples/cpp/LibTorch
mkdir build && cd build

# 若 OpenCV / LibTorch 未被自动探测到,追加下面的路径参数:
# -DCMAKE_PREFIX_PATH="/path/to/libtorch;/path/to/opencv"
cmake .. && cmake --build . --config Release

构建脚本的要点(对应 examples/cpp/LibTorch/CMakeLists.txt):

  • 分别通过 find_package(OpenCV REQUIRED)find_package(Torch REQUIRED) 定位依赖,并把 Torch_DIR / OpenCV_DIR 作为可覆写的查找提示;
  • set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") 追加 LibTorch 要求的编译选项;
  • main.cc + inference.cc 两个翻译单元生成可执行文件 yolo_libtorch
  • 共享工具自动引入:通过 target_include_directories(... ../common)examples/cpp/common 加入 include 路径,因此同目录下的 main.cc 可以直接 #include "yolo_render.hpp"#include "yolo_cli.hpp"
  • Windows(MSVC)场景下脚本预留了一段把 Torch DLL 复制到输出目录的逻辑(参照 PyTorch 的 #25457 讨论,防止内存错误),默认处于注释状态,可按需启用。

共享头文件里的"全家桶"

examples/cpp/common 目录下各头文件职责如下:

  • yolo_types.hppTask 枚举与统一的单目标结果结构 Result(包含 class_idconfidencebox、OBB 的 angle、Pose 的 keypoints / keypoint_scores、Segment 的 mask);
  • yolo_cli.hppArgValue / HasFlag 等极简命令行解析工具;
  • yolo_postprocess.hpp:预处理与全任务后处理函数,纯函数式、不依赖具体推理后端,可在 ONNX Runtime、OpenVINO 等示例间复用;
  • yolo_render.hpp / yolo_draw.hpp / yolo_show.hpp:结果标注绘制、控制台打印与窗口显示。

第三步:运行推理

编译产物 yolo_libtorch 的用法如下。若 LibTorch 未安装到系统库路径,需先导出动态库路径:

# 将 LibTorch 的库目录加入动态链接器搜索路径
export LD_LIBRARY_PATH=/path/to/libtorch/lib:$LD_LIBRARY_PATH

# 默认参数:--model yolo26n.torchscript --source bus.jpg --conf 0.25 --iou 0.45 --out result.jpg
./yolo_libtorch --model yolo26n.torchscript --source bus.jpg
./yolo_libtorch --model yolo26n-seg.torchscript --source bus.jpg --out seg.jpg
./yolo_libtorch --model yolo26n-pose.torchscript --source bus.jpg --show

命令行参数

参数 默认值 说明
--model yolo26n.torchscript 已导出的 TorchScript 模型路径(支持任意任务)
--source bus.jpg 输入图片路径
--conf 0.25 置信度阈值
--iou 0.45 NMS IoU 阈值(仅对 grid 输出模型生效,端到端输出已内置 NMS)
--out result.jpg 结果图片输出路径
--cuda 关闭 若 LibTorch 构建与硬件支持则使用 CUDA 推理
--show 关闭 额外弹出一个显示窗口

这些默认值直接定义在 inference.hConfig 结构与 main.cc 的参数解析中,可对照查看。

预期输出行为:标注结果始终写入 --out 指定的文件;每个检测框的关键信息会打印到控制台。程序启动时会打印模型信息,例如:

Model: yolo26n.torchscript | task: detect | classes: 80

taskclasses 数量来自模型元数据而非硬编码——这正是"点哪跑哪"的体现。

源码剖析:Predictor 如何做到"零配置"

入口 main.cc 的流程很直白:解析命令行 → cv::imread 读图 → 构造 yolo::Predictor → 打印任务信息 → predict() 推理 → 渲染并保存。真正的玄机在 Predictor 中。

模型加载与元数据解析

构造函数位于 inference.cc,执行三步关键操作:

  1. 设备选择:仅当 config.cuda == truetorch::cuda::is_available() 时才把设备切到 CUDA;
  2. 带附加文件加载模型:以 extra_files["config.txt"] = "" 为占位调用 torch::jit::load,让加载器把导出时写入的 config.txt 回填进来;
  3. 解析元数据load_metadata 用正则从 JSON 字符串中提取 taskimgsz(取首元素),并同时兼容 Python dict(0: 'person')与 JSON("0": "person")两种类别键值风格构建 names_ 列表;解析不到类别时回退到内置的 COCO 80 类列表(见 coco_names.hpp)。

前向推理与输出分发

predict()inference.cc)是整个示例的主干:

  • 调用共享头文件中的 Preprocess / ToBlob 完成letterbox 填充(检测类任务)或中心裁剪(分类任务)、BGR→RGB 转换与 HWC→CHW 归一化,得到 [1, 3, imgsz, imgsz] 的 float 张量(见 yolo_postprocess.hpp);
  • torch::NoGradGuard 下通过 module_.forward({input_tensor}) 执行前向;
  • 统一收集输出:由于不同任务的 TorchScript 输出类型不同(单个 Tensor、Tuple 或 TensorList),代码对三种情况分别取张量,segment 特有的 4D proto 张量与主输出(2D/3D)一并收集——4D 张量记为辅助输出 aux_idx,其余记为 main_idx
  • 依据解析出的 Task 枚举分发到不同后处理函数;semantic 任务把逐像素类别图写入 semantic 输出参数并返回空结果列表,其余任务返回 Result 列表。

grid 与 end-to-end 输出的自动判别

后处理共享函数通过维度比较区分输出布局:以 [1, dim1, dim2] 为例,若 dim1 > dim2(如 [1, 300, 6])即端到端输出,是已经过内置 NMS 的定长候选集,只需按置信度阈值过滤并按 x1,y1,x2,y2,conf,cls 布局解析;否则按 YOLOv8/11 经典的 [1, 4+nc, 8400] 通道主序 grid 处理。该逻辑实现在 yolo_postprocess.hpp 中,pose / OBB 同理。

各任务后处理要点(源码级)

  • Detect:grid 分支对每条锚点做类别 argmax、cv::dnn::NMSBoxesBatched 做类内抑制;end2end 分支直接读取已排序的候选行。
  • Pose:keypoint 坐标为原图坐标并附逐点置信度,grid 分支以 dim1 = 5 + nkpt*3 推算关键点数(yolo_postprocess.hpp)。
  • OBB:每行末尾携带旋转角 angle,先以轴对齐矩形为代理做 NMS,绘制时再还原为 cv::RotatedRectyolo_postprocess.hpp)。
  • Segment:利用检测头输出与 4D proto 张量做矩阵乘法,经 sigmoid、双线性放大、按 0.5 阈值二值化并裁到目标框范围,产出原图尺寸的 8-bit 掩膜(yolo_postprocess.hpp)。
  • Semantic:对每个像素在所有类别通道上 argmax,得到逐像素类别图后做最近邻放大回原图尺寸(yolo_postprocess.hpp)。
  • Classify:取置信度最高的 top-5 类别输出(yolo_postprocess.hpp)。

结果渲染

main.cc 调用 yolo_render.hpp 中的 RenderAndPrint:检测/分割/姿态任务逐目标绘制边框、掩膜、骨架与 名称 置信度 标签并打印控制台;OBB 额外输出角度;分类在左上角列出 Top-5;语义分割则把类别图直接覆盖到画布。最终 cv::imwrite 写出到 --out--show 开启时再弹出窗口。

注意事项与边界条件

  • --iou 仅对 grid 模型生效:YOLO26 端到端输出的 NMS 在导出阶段已融合进图内,运行期的 IoU 阈值不会影响其候选筛选;
  • 分类模型走中心裁剪而非 letterboxPreprocess 依据 task == Classify 选择不同的缩放策略,这与 Python 侧训练/推理语义保持一致;
  • COCO 之外的类别:若模型类别超过内置 COCO 表(如 ImageNet 1000 类),会优先使用 config.txt 中解析出的 names_,完全缺失时才回退到内置列表并以数字 ID 兜底(见 yolo_cli.hppNameOf);
  • CUDA 生效条件--cuda 只是开关,真正起效还需要 LibTorch 为 CUDA 构建且当前设备可用,二者缺一不可;
  • Windows 用户:请按 CMakeLists 中的注释启用 Torch DLL 复制逻辑,否则可能遇到 DLL 加载导致的内存错误;
  • 运行环境:示例默认读入名为 bus.jpg 的本地图片并输出 result.jpg,请确保输入文件存在于当前工作目录或改用 --source 指定绝对路径。

延伸阅读

如果你想了解其他推理后端的 C++ 用法(同一套前后处理逻辑可平移复用),可参考 examples/cpp/ONNXRuntimeexamples/cpp/OpenVINO 等示例;各示例共用 examples/cpp/common 中的头文件。任务与模型的完整知识可继续阅读 docs/en/tasks/index.mddocs/en/models/index.md

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
858
1.35 K
docsdocs
暂无描述
Markdown
899
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
923
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.83 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
532
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
524
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
393