YOLOX OpenVINO C++ 部署实战:模型转换、环境搭建与推理源码全解析
2026/9/24 19:48:20 网站建设 项目流程
  • 人工智能
  • 计算机视觉
  • 深度学习

【免费下载链接】YOLOX

YOLOX is a high-performance anchor-free YOLO, exceeding yolov3~v5 with MegEngine, ONNX, TensorRT, ncnn, and OpenVINO supported. Documentation: https://yolox.readthedocs.io/

项目地址:https://gitcode.com/gh_mirrors/yo/YOLOX
点击查看免费下载

本指南基于 YOLOX 仓库中的 OpenVINO C++ 部署文档,系统讲解如何将 YOLOX 模型转换为 OpenVINO 中间表示(IR),并借助仓库自带的 C++ 推理示例在 Intel 平台(CPU/GPU/VPU 等)上完成目标检测。读完本文,你将掌握从下载官方 OpenVINO 模型、配置 OpenVINO 环境、以 opset 10 导出 ONNX 并转为 IR 的完整链路,同时能读懂 yolox_openvino.cpp 中预处理、解码、NMS 与坐标还原的每一行实现,具备将 demo 迁移到自定义数据集或嵌入自身 C++ 项目的能力。

一、仓库中的 OpenVINO C++ Demo 一览

YOLOX 的 OpenVINO 部署示例位于demo/OpenVINO目录,其中:

  • cpp/yolox_openvino.cpp:完整的 C++ 推理程序,基于 OpenVINO 2021 版 Inference Engine API 编写,输入模型(IR 或 ONNX)、图片与设备名,输出带检测框的_demo.jpg
  • cpp/CMakeLists.txt:CMake 构建脚本,依赖 OpenCV、InferenceEngine 与 ngraph 三个库;
  • README.md:本指南对应的官方部署文档,涵盖模型下载、环境配置、模型转换、构建与运行四步;
  • python/openvino_inference.py:功能等价的 Python 版推理脚本,可作为 C++ 结果的对照验证。

整个部署链路为:PyTorch 权重 → ONNX(opset 10)→ OpenVINO IR(.xml + .bin)→ C++ 推理。其中 ONNX 导出依赖 ONNXRuntime 部署文档 与 tools/export_onnx.py 脚本,本文会在转换章节一并讲透。

二、下载官方 OpenVINO 模型与规格对照

官方已为 YOLOX 全系列模型提供转换好的 OpenVINO 模型压缩包,格式为yolox_<model>_openvino.tar.gz,随 YOLOX v0.1.1rc0 版本发布。压缩包内即 demo 所需的 IR 文件(.xml拓扑描述与.bin权重),解压后可直接传给 C++ demo 的<XML_MODEL_PATH>参数。

各模型规格如下表(模型名链接到仓库中对应的实验配置,mAP 为 COCO 验证集指标):

模型参数量GFLOPs测试尺寸mAP权重包
YOLOX-Nano0.91M1.08416x41625.8yolox_nano_openvino.tar.gz
YOLOX-Tiny5.06M6.45416x41632.8yolox_tiny_openvino.tar.gz
YOLOX-S9.0M26.8640x64040.5yolox_s_openvino.tar.gz
YOLOX-M25.3M73.8640x64047.2yolox_m_openvino.tar.gz
YOLOX-L54.2M155.6640x64050.1yolox_l_openvino.tar.gz
YOLOX-Darknet5363.72M185.3640x64048.0yolox_dark_openvino.tar.gz
YOLOX-X99.1M281.9640x64051.5yolox_x_openvino.tar.gz

选择要点:

  • 追求极速与低算力平台(如嵌入式/边缘设备)选择YOLOX-Nano / YOLOX-Tiny,其测试尺寸为 416x416,与 demo 源码中默认的INPUT_W = INPUT_H = 416(见 yolox_openvino.cpp)完全一致;
  • 追求精度则选YOLOX-L / YOLOX-X(640x640,mAP 50+);
  • YOLOX-Darknet53对应实验配置 exps/default/yolov3.py,即 Darknet53 骨干版 YOLOX。

若模型测试尺寸不是 416x416,则必须在转换阶段指定对应的--input_shape,并同步修改 C++ 源码中的输入宽高常量,详见下文第四节。

三、安装 OpenVINO Toolkit 并配置环境

官方文档要求安装 OpenVINO 2021 版本工具包(安装方式请以 OpenVINO 官方安装指南为准,仓库文档原文指向其官网 get_started 页面)。安装完成后,关键路径为/opt/intel/openvino_2021,其下包含setupvars.sh环境脚本与 Model Optimizer 转换工具。

3.1 临时配置环境(每次开新终端都要执行)

source /opt/intel/openvino_2021/bin/setupvars.sh

该命令会把 OpenVINO 的动态库、Model Optimizer 等工具路径注入当前 shell。由于只对当前会话生效,每次新建终端窗口后都必须重新执行。

3.2 永久配置环境(推荐)

Step1.编辑 shell 配置文件:

vim ~/.bashrc

Step2.在文件末尾追加一行:

source /opt/intel/openvino_2021/bin/setupvars.sh

Step3.保存退出后使其立即生效:

source ~/.bashrc

配置完成后,setupvars.sh会在每个交互式终端启动时自动执行,后续构建与运行 demo 前无需再手动 source。

四、模型转换:PyTorch → ONNX → OpenVINO IR

OpenVINO 不直接消费 PyTorch 权重,需要先导出 ONNX,再用 Model Optimizer(mo.py)转为 OpenVINO IR。

4.1 第一步:导出 ONNX(opset 必须为 10)

关键前提:官方文档明确强调,若后续要转换为 OpenVINO,导出 ONNX 时必须指定--opset 10,否则下一步 Model Optimizer 转换会失败。而 tools/export_onnx.py 中 opset 的默认值是 11,因此必须显式传参。

以 YOLOX-Tiny 为例:

cd <YOLOX_HOME> python3 tools/export_onnx.py --output-name yolox_tiny.onnx -n yolox-tiny -c yolox_tiny.pth -o 10

脚本核心参数(源自 tools/export_onnx.py 的参数定义):

  • --output-name:导出 ONNX 文件名,默认yolox.onnx
  • -n, --name:指定预置模型名,可取yolox-nano / yolox-tiny / yolox-s / yolox-m / yolox-l / yolox-x / yolov3
  • -f, --exp_file:指定自定义实验配置文件(.py)路径,与-n二选一;
  • -c, --ckpt:训练得到的权重文件路径;
  • -o, --opset:ONNX opset 版本,默认 11,转 OpenVINO 时必须设为 10
  • --no-onnxsim:禁用 onnx-simplifier 简化,默认会启用简化并校验;
  • --dynamic:是否导出动态 batch 输入;
  • --input/--output:输入/输出节点名,默认分别为images/output
  • --decode_in_inference:是否在导出模型内部完成解码。

-f指定实验文件的方式(等价写法):

python3 tools/export_onnx.py --output-name yolox_tiny.onnx -f exps/default/yolox_tiny.py -c yolox_tiny.pth -o 10

自定义模型则用:

python3 tools/export_onnx.py --output-name your_yolox.onnx -f exps/your_dir/your_yolox.py -c your_yolox.pth -o 10

关于输入尺寸:脚本使用torch.randn(batch_size, 3, exp.test_size[0], exp.test_size[1])构造 dummy input(见 tools/export_onnx.py),即 ONNX 的输入形状由实验配置的test_size决定。例如 exps/default/yolox_tiny.py 中test_size = (416, 416),而 exps/default/yolox_s.py 未显式覆盖test_size,继承默认的 640x640。若想自定义导出尺寸,需在实验配置中调整test_size(或按官方 ONNX 文档方式修改 dummy input 构造),并确保与 C++ demo 的INPUT_W/INPUT_H一致。

4.2 第二步:安装 Model Optimizer 的 ONNX 转换依赖

进入 Model Optimizer 目录并安装 ONNX 转换所需的 Python 依赖:

cd <INSTALL_DIR>/openvino_2021/deployment_tools/model_optimizer sudo ./install_prerequisites/install_prerequisites_onnx.sh

4.3 第三步:ONNX → OpenVINO IR

仍在 Model Optimizer 目录下执行:

python3 mo.py --input_model <ONNX_MODEL> --input_shape <INPUT_SHAPE> [--data_type FP16]

参数说明:

  • --input_model:上一步导出的 ONNX 文件;
  • --input_shape:必须与 ONNX 导出时的输入形状一致,格式如[1,3,416,416]
  • --data_type FP16:可选,将权重压缩为 FP16,可减小模型体积并提升部分设备上的推理速度。

官方示例(YOLOX-Tiny,416 输入):

python3 mo.py --input_model yolox_tiny.onnx --input_shape [1,3,416,416] --data_type FP16

一致性检查:转换时指定的--input_shape必须与 C++ 源码中定义的输入宽高常量保持一致,即 yolox_openvino.cpp 中的INPUT_W = 416INPUT_H = 416;否则推理时输入 Blob 尺寸不匹配,会直接报错。

转换成功后,工作目录会生成同名的.xml.bin文件,二者共同构成 OpenVINO IR,后续传给 demo 的是.xml路径。

五、C++ 推理源码深度解析

理解了模型来源后,我们来逐段拆解 yolox_openvino.cpp 的完整推理流程。该程序严格遵循 OpenVINO 2021 推理样板的标准八步,同时内嵌了 YOLOX 特有的解码与后处理逻辑,可直接作为移植到其他推理框架的参考。

5.1 命令行参数与关键常量

main函数首先校验参数个数(yolox_openvino.cpp):

if (argc != 4) { tcout << "Usage : " << argv[0] << " <path_to_model> <path_to_image> <device_name>" << std::endl; return EXIT_FAILURE; }

即运行格式为./yolox_openvino <XML_MODEL_PATH> <IMAGE_PATH> <DEVICE>

文件顶部定义了几个影响检测行为的关键常量(yolox_openvino.cpp):

常量默认值含义
NMS_THRESH0.45NMS 的 IoU 阈值
BBOX_CONF_THRESH0.3候选框置信度阈值
INPUT_W/INPUT_H416 / 416网络输入尺寸
NUM_CLASSES80COCO 类别数,自定义数据集需修改

5.2 推理主流程(OpenVINO 标准八步)

主流程代码(yolox_openvino.cpp)依次为:

  1. 初始化 Inference Engine CoreCore ie;(2021 版新 API,替代旧版InferencePlugin);
  2. 读取模型ie.ReadNetwork(input_model)可同时读取 IR(.xml)或 ONNX(.onnx);随后校验拓扑必须为单输入单输出,否则抛出异常;
  3. 配置输入输出:获取输入输出节点名,并将输出精度强制设为FP32output_info->setPrecision(Precision::FP32)),保证解码时按 float 解释数据;
  4. 加载模型到设备ie.LoadNetwork(network, device_name)device_name即运行参数<DEVICE>,常见取值CPUGPUMYRIAD(Intel Movidius VPU)、HDDLHETERO等,与 python/openvino_inference.py 中-d参数支持的设备列表一致;
  5. 创建推理请求infer_request = executable_network.CreateInferRequest()
  6. 准备输入:读图、letterbox 缩放、写入输入 Blob(见 5.3);
  7. 执行推理infer_request.Infer()(同步推理);
  8. 处理输出:读取输出 Blob,经解码 + NMS + 坐标还原后绘制保存(见 5.4~5.6)。

5.3 预处理:letterbox 等比缩放 + 灰度填充

static_resize(yolox_openvino.cpp)实现标准 YOLOX letterbox:

float r = std::min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0)); int unpad_w = r * img.cols; int unpad_h = r * img.rows; cv::resize(img, re, re.size()); cv::Mat out(INPUT_H, INPUT_W, CV_8UC3, cv::Scalar(114, 114, 114)); // 114 灰度填充 re.copyTo(out(cv::Rect(0, 0, re.cols, re.rows)));

即按比例缩放图片至 416x416 内,多余区域用 RGB(114,114,114) 填充(与训练时数据增强的填充值一致),避免直接拉伸导致的形变。

blobFromImage(yolox_openvino.cpp)将cv::Mat的 HWC 数据按 NCHW 顺序写入内存 Blob,注意这里只做类型转换(uint8 → float),不做 /255 归一化——因为导出 ONNX 时模型内部已包含归一化层。

5.4 解码:无锚框输出解析

YOLOX 是无锚框(anchor-free)检测器,输出为各 stride 特征图网格上的原始预测,需配合网格坐标解码为边界框。源码实现分两步:

  • generate_grids_and_stride(yolox_openvino.cpp):按strides = {8, 16, 32}(对应 PAFPN 三个检测层)枚举每个网格坐标(grid0, grid1)与对应 stride;
  • generate_yolox_proposals(yolox_openvino.cpp):逐网格解码,代码注释明确标注了与 yolox/models/yolo_head.py 中 decode 逻辑的一致性:
// outputs[..., :2] = (outputs[..., :2] + grids) * strides // outputs[..., 2:4] = torch.exp(outputs[..., 2:4]) * strides float x_center = (feat_ptr[basic_pos + 0] + grid0) * stride; float y_center = (feat_ptr[basic_pos + 1] + grid1) * stride; float w = exp(feat_ptr[basic_pos + 2]) * stride; float h = exp(feat_ptr[basic_pos + 3]) * stride;

随后计算目标置信度与类别分数的乘积box_prob = box_objectness * box_cls_score,仅保留大于BBOX_CONF_THRESH(0.3)的候选框。

5.5 NMS:按置信度降序排序 + IoU 抑制

  • qsort_descent_inplace(yolox_openvino.cpp):快速排序将候选框按置信度降序排列,递归分支用 OpenMP#pragma omp parallel sections并行化;
  • nms_sorted_bboxes(yolox_openvino.cpp):按序贪婪选择,若与已保留框的 IoU 大于NMS_THRESH(0.45)则剔除,实现标准单类别 NMS(遍历所有类别,等价于将 80 类视为一个大类做一次 NMS)。

5.6 坐标还原、裁剪与可视化

decode_outputs(yolox_openvino.cpp)在 NMS 之后把框坐标从 416x416 空间还原到原始图像空间:

float x0 = (objects[i].rect.x) / scale; // scale 为预处理时的缩放比 ... x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f); // 裁剪到图像边界

draw_objects(yolox_openvino.cpp)完成:

  • 对每个检测框按类别取固定调色板颜色绘制矩形与标签文本(class_names数组为完整 COCO 80 类列表);
  • 在 stderr 打印结构化结果:label = prob at x y w h
  • 将结果图保存为当前目录下的_demo.jpg

六、CMake 构建详解

CMakeLists.txt 内容非常精简,依赖三个通过find_package查找的库:

cmake_minimum_required(VERSION 3.4.1) set(CMAKE_CXX_STANDARD 14) project(yolox_openvino_demo) find_package(OpenCV REQUIRED) find_package(InferenceEngine REQUIRED) find_package(ngraph REQUIRED) ... add_executable(yolox_openvino yolox_openvino.cpp) target_link_libraries(yolox_openvino ${InferenceEngine_LIBRARIES} ${NGRAPH_LIBRARIES} ${OpenCV_LIBS})

要点:

  • 要求 C++14 标准与 CMake 3.4.1+;
  • InferenceEnginengraph两个包的查找路径正是由第三节setupvars.sh注入的,必须先 source 环境脚本再执行 cmake,否则会因找不到包而配置失败;
  • 需要系统已安装 OpenCV(cv::imread / cv::resize / cv::rectangle等均来自 OpenCV)。

Linux 下完整构建步骤:

source /opt/intel/openvino_2021/bin/setupvars.sh mkdir build cd build cmake .. make

构建成功后,build目录下生成可执行文件yolox_openvino

七、运行 Demo 并验证结果

./yolox_openvino <XML_MODEL_PATH> <IMAGE_PATH> <DEVICE>

例如(使用转换好的 YOLOX-Tiny IR 与 CPU 设备):

./yolox_openvino yolox_tiny.xml dog.jpg CPU

运行说明与验证手段:

  • 程序要求恰好 4 个参数(可执行文件名 + 模型 + 图片 + 设备),参数个数不对会打印 Usage 后退出;
  • 推理过程中会在 stderr 逐行打印检测结果,格式为label = prob at x y w h(如16 = 0.93152 at 104.00 170.00 261.00 x 379.00);
  • 检测结果图保存在当前工作目录的_demo.jpg,可直接查看;若需 GUI 显示,可取消draw_objects末尾cv::imshow / cv::waitKey的注释;
  • 设备名可尝试CPUGPU(需安装 GPU 插件)或MYRIAD(需接入 Intel NCS2 等 VPU 设备)。

若同时安装了 Python 环境,可用 python/openvino_inference.py 做交叉验证:

python3 openvino_inference.py -m yolox_tiny.xml -i dog.jpg -o demo_output -s 0.3 -d CPU

Python 版内部复用 yolox/utils/demo_utils.py 中的demo_postprocess / multiclass_nms / vis等工具函数,与 C++ 版在解码与 NMS 策略上保持等价。

八、常见问题与注意事项

  1. opset 必须是 10:导出 ONNX 时若使用默认 opset 11(或更高),Model Optimizer 转换会失败,务必加-o 10
  2. 输入形状三方一致mo.py--input_shape、ONNX 导出时的test_size、C++ 源码的INPUT_W/INPUT_H必须统一。换用 640x640 模型(如 YOLOX-S)时,请同步修改 yolox_openvino.cpp 中的常量并重新编译;
  3. 单输入单输出限制:demo 只支持单输入单输出拓扑,若自定义模型导出后输入输出节点异常(例如开启了多输出解码),需调整导出配置;
  4. 自定义数据集:修改NUM_CLASSES为实际类别数,并同步替换class_names数组与color_list长度(yolox_openvino.cpp);
  5. FP16 模型:使用--data_type FP16转换可缩小体积,代码中已强制输出精度为 FP32 供解码使用,不受影响;
  6. 每次构建前 source 环境:新终端必须先执行source /opt/intel/openvino_2021/bin/setupvars.sh(或配置进~/.bashrc),否则 CMake 无法找到 InferenceEngine/ngraph。

至此,从官方权重、ONNX 导出、IR 转换到 C++ 推理的完整 YOLOX OpenVINO 部署链路已全部打通,你可以基于 yolox_openvino.cpp 快速集成到自己的边缘端或服务端 C++ 推理工程中。

  • 人工智能
  • 计算机视觉
  • 深度学习

【免费下载链接】YOLOX

YOLOX is a high-performance anchor-free YOLO, exceeding yolov3~v5 with MegEngine, ONNX, TensorRT, ncnn, and OpenVINO supported. Documentation: https://yolox.readthedocs.io/

项目地址:https://gitcode.com/gh_mirrors/yo/YOLOX
点击查看免费下载

相关推荐

上一篇:Metalsmith未来能源:可再生技术的静态网站资源库
下一篇:让流程图不再有障碍:js-sequence-diagrams无障碍优化指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询