尧图精选

Linux C++ OpenVINO 部署 YOLOv8s 物体检测实战

🕒 发布时间:2026/10/1 17:37:03 📁 来源:尧图网络
简介这份资源是面向Linux平台C开发者与计算机视觉入门者的OpenVINO物体检测实战Demo帮助读者在边缘设备上完成基于YOLOv8s的推理部署适合具备一定C基础、希望快速上手深度学习推理的工程师学习参考。压缩包为rar格式共6个文件、约35.53MB包含2张测试图片、1个模型结构xml、1个权重bin、1个主程序cpp及1个说明txt覆盖从模型加载到结果可视化的完整链路。资源以YOLOv8s的IR文件为核心配合主程序演示了初始化推理引擎、加载模型、图像预处理、执行推理与解析边界框等关键环节并附带CMake构建配置便于在Linux下直接编译运行。目前已有352人学习下载读者可借此理解OpenVINO的Model Optimizer与Inference Engine协作机制掌握模型部署与图像输入输出处理流程并在此基础上定制优化自己的物体检测应用。1. 拆开这个 Linux C OpenVINO 物体检测 Demo它到底能跑出什么结果如果你手头正好有一台装了 Ubuntu 的工控机或者开发板想用 C 把 YOLOv8s 的推理跑起来又不想从零去啃 OpenVINO 那一堆 API这个linux_cpp_openvino_test.rar就是那种「解压完改两行就能编译」的起点。包里给的东西很实在CMakeLists.txt负责构建main.cpp是推理主逻辑yolov8s.xml和yolov8s.bin是已经转好的 IR 模型外加test.jpg、test2.jpg两张测试图。它解决的不是「教你训练模型」而是「模型已经有了怎么在 Linux 上用 C 把它喂进 OpenVINO 并拿到检测框」这一段最容易被卡住的落地环节。适合谁写过一点 C、知道 CMake 大概怎么回事、但没怎么碰过 OpenVINO 推理接口的工程师如果你连g和cmake都没用过建议先把编译工具链补齐再往下看。2. OpenVINO 推理链路拆解从 IR 文件到 C 可执行程序2.1 为什么是 IR 文件而不是直接加载 ONNXOpenVINO 的推理引擎不直接吃 PyTorch 的.pt也不推荐在 C 端现场解析 ONNX。它的标准做法是先离线转成 Intermediate Representation也就是.xml.bin这一对。.xml描述网络拓扑——每一层的类型、输入输出张量的名字和形状.bin存的是权重二进制。这个 Demo 里yolov8s.xml和yolov8s.bin就是干这个的。为什么不在 C 里直接读 ONNX因为 ONNX Runtime 和 OpenVINO 是两套运行时OpenVINO 对 ONNX 的支持通常是通过前端解析后内部再转 IR多一层不确定性。而 IR 是 OpenVINO 的原生格式加载路径最短版本兼容性也最可控。常见做法是在 Python 端用openvino.convert_model或者mo命令把 YOLOv8s 的 ONNX 转成 IR然后把.xml和.bin拷到 C 工程目录。这个 Demo 已经把这一步替你做了你拿到的是成品 IR。有一点要注意IR 文件不是跨版本无限兼容的。OpenVINO 2022 和 2024 的 IR 格式有过调整如果你用的 OpenVINO 版本比生成 IR 的版本老加载时可能直接报Cannot read the model或者Unsupported opset。所以拿到别人的 IR 包第一件事是确认你本机 OpenVINO 版本不低于生成端。2.2 CMakeLists.txt 里真正要盯的几个变量CMakeLists.txt看起来短但它是整个工程能不能编过的命门。OpenVINO 的 CMake 支持靠的是OpenVINOConfig.cmake这个文件在你安装 OpenVINO 时会被放到某个路径下。如果你是用官方压缩包解压的通常在runtime/cmake目录如果是 apt 装的一般在/usr/lib/cmake/openvino*。一个能用的CMakeLists.txt骨架大概长这样cmake_minimum_required(VERSION 3.10) project(openvino_yolo_demo CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指向 OpenVINO 的 CMake 配置目录按你本机实际路径改 set(OpenVINO_DIR /opt/intel/openvino/runtime/cmake) find_package(OpenVINO REQUIRED) add_executable(yolo_demo main.cpp) target_link_libraries(yolo_demo openvino::runtime openvino::runtime::dev )逻辑说明find_package(OpenVINO REQUIRED)会去OpenVINO_DIR指定的目录找OpenVINOConfig.cmake找到后导入openvino::runtime这个 imported target。你不需要手动写-I和-Ltarget 会带出头文件路径和链接库。参数上OpenVINO_DIR是最容易写错的地方——很多人装完 OpenVINO 没设环境变量CMake 找不到就直接报Could not find a package configuration file provided by OpenVINO。解决办法要么在 CMakeLists 里硬编码路径要么在命令行传-DOpenVINO_DIR...。另外openvino::runtime::dev这个 target 不是所有版本都有如果你编译时报找不到它先去掉只留openvino::runtime因为推理主流程用不到 dev 包。2.3 main.cpp 的推理主流程六步走main.cpp是整个 Demo 的核心。不管 OpenVINO 版本怎么变C 推理的骨架基本是固定的六步。下面按这个 Demo 的场景把每一步拆开。第一步创建 Core 对象并读取模型#include openvino/openvino.hpp #include opencv2/opencv.hpp int main() { ov::Core core; // 同时传 xml 和 binOpenVINO 会自动配对 auto model core.read_model(yolov8s.xml, yolov8s.bin); // ... }ov::Core是 OpenVINO 运行时的入口负责管理插件和设备。read_model接受.xml路径.bin可以省略因为同名.bin会被自动找到。但如果你把.bin改了名就必须显式传第二个参数。第二步编译模型到指定设备// 编译到 CPU也可以换成 GPU 或 AUTO auto compiled_model core.compile_model(model, CPU);compile_model这一步会把 IR 转成设备能执行的底层表示耗时通常在几百毫秒到几秒。设备名CPU是最稳的GPU需要你有 Intel 核显并装了对应驱动AUTO会让 OpenVINO 自己选。第一次跑建议先用 CPU确认流程通了再换。第三步拿到输入输出端口信息auto input_port compiled_model.input(); auto output_port compiled_model.output(); ov::Shape input_shape input_port.get_shape(); // YOLOv8 常见输入是 [1, 3, 640, 640]这里input_shape的格式是 NCHWYOLOv8s 通常是[1, 3, 640, 640]。你要用这个形状去预处理图像而不是凭感觉 resize。如果输入尺寸对不上推理不会报错但输出框会全乱——这是新手最容易翻车的地方。第四步读图并预处理cv::Mat img cv::imread(test.jpg); cv::Mat resized; cv::resize(img, resized, cv::Size(640, 640)); resized.convertTo(resized, CV_32F, 1.0 / 255.0); // HWC - CHW ov::Tensor input_tensor(input_port.get_element_type(), input_shape, resized.data);cv::resize把图缩到 640x640convertTo做归一化到 0~1。然后构造ov::Tensor直接把resized.data塞进去。注意这里没有做 letterbox所以长宽比会被拉伸检测框坐标映射回原图时会有偏移。Demo 级别够用但如果你要精确框得自己补 letterbox 逻辑。第五步推理auto infer_request compiled_model.create_infer_request(); infer_request.set_input_tensor(input_tensor); infer_request.infer(); auto output_tensor infer_request.get_output_tensor();create_infer_request创建一个推理请求set_input_tensor绑定输入infer()同步执行。输出通过get_output_tensor()拿。YOLOv8 的输出通常是[1, 84, 8400]84 是 4 个框坐标加 80 个类别分数8400 是候选框数量。第六步解析输出并画框float* data output_tensor.datafloat(); // 遍历 8400 个候选找分数超过阈值的 for (int i 0; i 8400; i) { float score data[4 * 8400 i]; // 简化写法实际按布局取 if (score 0.5) { // 取 cx, cy, w, h 并映射回原图 // 用 cv::rectangle 画框 } }这段解析逻辑是 Demo 里最需要你自己补全的部分。YOLOv8 的输出布局和 YOLOv5 不同它是[batch, 84, anchors]前 4 个是cx, cy, w, h后面 80 个是类别分数。你需要按正确的 stride 去取数否则拿到的全是错位的浮点数。3. 编译与运行从解压到看到检测框的完整命令3.1 环境准备与依赖确认在编译之前先把三样东西确认好OpenVINO 运行时、OpenCV 开发包、CMake 和编译器。OpenVINO 可以用官方压缩包解压后source setupvars.sh也可以用 apt 装openvino和openvino-dev。OpenCV 在 Ubuntu 上直接sudo apt install libopencv-dev就行。# 确认 OpenVINO 环境变量已生效 echo $OpenVINO_DIR # 确认 OpenCV 能找到 pkg-config --modversion opencv4 # 确认 cmake 和 g 版本 cmake --version g --version如果echo $OpenVINO_DIR是空的说明你没 source 环境脚本。OpenVINO 压缩包解压后setupvars.sh在根目录source一下就会设好OpenVINO_DIR和LD_LIBRARY_PATH。这一步不做后面 CMake 必挂。3.2 编译命令与常见报错进入解压后的目录标准流程是mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease make -j$(nproc)-DCMAKE_BUILD_TYPERelease会开-O3优化推理性能比 Debug 高不少。-j$(nproc)用满所有核并行编译。如果 CMake 报Could not find a package configuration file provided by OpenVINO说明OpenVINO_DIR没设对。手动指定cmake .. -DOpenVINO_DIR/opt/intel/openvino/runtime/cmake如果 make 阶段报undefined reference to ov::Core::...说明链接库没带上。检查target_link_libraries里有没有openvino::runtime。如果报opencv2/opencv.hpp: No such file说明 OpenCV 开发包没装或者 CMake 没找到补一个find_package(OpenCV REQUIRED)和target_link_libraries(... ${OpenCV_LIBS})。3.3 运行与结果验证编译成功后build目录下会有yolo_demo可执行文件。把test.jpg和模型文件放在同一目录然后./yolo_demo如果一切正常程序会读test.jpg跑推理然后在控制台打印检测到的类别和置信度或者弹出一个窗口显示画了框的图。Demo 里通常是用cv::imshow显示但如果你在无桌面的服务器上跑imshow会报GTK 2.x symbols not found。解决办法是把显示部分改成cv::imwrite(result.jpg, img)存文件再拉出来看。验证结果是否合理看两点一是框的位置有没有明显偏移二是置信度是不是集中在 0.5 以上。如果框全堆在左上角大概率是预处理没做对如果置信度全是 0.01 左右可能是输出解析的 stride 取错了。4. 避坑与排查这个 Demo 最容易翻车的五个地方4.1 现象编译通过但运行时报Cannot load library libopenvino.so原因LD_LIBRARY_PATH没包含 OpenVINO 的运行时库目录。OpenVINO 的.so文件不在系统默认搜索路径里编译时链接到了运行时找不到。解决在运行前export LD_LIBRARY_PATH/opt/intel/openvino/runtime/lib/intel64:$LD_LIBRARY_PATH或者把路径写进/etc/ld.so.conf.d/然后ldconfig。最省事的办法是每次开终端先source setupvars.sh。4.2 现象推理结果全是乱框坐标明显不对原因预处理时没有保持长宽比或者输出解析时把cx, cy, w, h当成了x1, y1, x2, y2。YOLOv8 输出的是中心点加宽高需要先转成左上右下再映射回原图。解决确认输出布局是[1, 84, 8400]前 4 个通道依次是cx, cy, w, h。映射公式是x1 (cx - w/2) * scale_x其中scale_x 原图宽 / 640。如果做了 letterbox还要减去 padding 偏移。4.3 现象read_model报Unsupported opset version原因IR 文件是用比你本机更新的 OpenVINO 版本生成的旧版本运行时读不了新 opset。解决升级本机 OpenVINO 到不低于生成 IR 的版本。如果升不了只能在 Python 端用旧版本 OpenVINO 重新转一次 IR。转的时候指定--opset参数往下压。4.4 现象cv::imshow在服务器上直接崩原因无桌面环境没有 GTK 或 Qt 后端OpenCV 的 highgui 模块初始化失败。解决把显示逻辑换成cv::imwrite或者编译 OpenCV 时关掉 highgui。更彻底的做法是在代码里加一个判断检测到没有DISPLAY环境变量就自动走存文件分支。4.5 现象推理速度比预期慢很多原因用了 Debug 编译或者compile_model时选了CPU但没开性能模式或者输入尺寸被意外放大。解决确认CMAKE_BUILD_TYPERelease在compile_model前设置core.set_property(CPU, ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT))检查input_shape是不是 640x640 而不是更大。另外第一次推理会包含模型加载时间测速要从第二次开始算。5. 进阶技巧把 Demo 改成能批量跑图的推理工具Demo 默认只读一张test.jpg但包里还给了test2.jpg说明作者本来就打算让你跑多张。与其每次改代码里的文件名不如把main.cpp里的单图逻辑抽成一个函数然后遍历目录下所有.jpg。#include filesystem namespace fs std::filesystem; void infer_one(ov::CompiledModel compiled, const std::string path) { cv::Mat img cv::imread(path); // ... 预处理、推理、解析、画框 ... cv::imwrite(out_ fs::path(path).filename().string(), img); } int main() { ov::Core core; auto model core.read_model(yolov8s.xml, yolov8s.bin); auto compiled core.compile_model(model, CPU); for (auto entry : fs::directory_iterator(.)) { if (entry.path().extension() .jpg) { infer_one(compiled, entry.path().string()); } } }这样改的好处是模型只加载一次compiled_model复用省掉了每张图重新read_model和compile_model的开销。实测在 640x640 输入下CPU 单张推理大概几十毫秒模型加载却要一两秒批量跑的时候差距非常明显。另一个值得做的优化是异步推理。OpenVINO 的InferRequest支持start_async()你可以同时提交多个请求让 CPU 的多个核并行跑。对于批量图片场景吞吐量能提升不少。但异步的坑在于输出张量的生命周期管理——你得等wait()返回后再去读get_output_tensor()否则拿到的可能是上一帧的数据。还有一个实际部署时绕不开的问题类别标签。Demo 里通常只打印类别索引但你要的是「人」「车」「狗」这种可读标签。YOLOv8 的 80 类标签是固定的 COCO 顺序自己建一个std::vectorstd::string存好解析输出时用索引去查就行。别去网上随便找一个标签文件就用顺序错一位整个结果就全错了。从那以后我每次拿到别人转好的 IR 包都强制先跑一遍core.read_model加compile_model确认模型能加载再动业务代码。这个习惯帮我省掉了至少三次「以为是解析写错了其实是模型版本不兼容」的无效排查。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →