首页
/ OpenCV 4.x 结合 OpenVINO 后端的构建与多目标推理实战指南

OpenCV 4.x 结合 OpenVINO 后端的构建与多目标推理实战指南

2026-09-06 17:52:42作者:咎竹峻Karen

本篇技术指南围绕 doc/tutorials/dnn/dnn_openvino/dnn_openvino.markdown 展开,讲解自 OpenVINO 2021.1.1 起不再提供预构建 OpenCV 之后,如何获得与指定版本 OpenVINO 配套的 OpenCV(预构建包或源码编译两条路线),并深入 OpenCV DNN 模块源码,说明 DNN_BACKEND_INFERENCE_ENGINE 后端在 CPU、iGPU、MYRIAD、HDDL、FPGA、NPU 六类目标设备上的配置方式、运行期参数与调用链。读完后你可以独立完成 OpenCV + OpenVINO 的源码级构建、把推理目标设备切换到 Intel 加速硬件,并理解每个 CMake/运行期参数在源码中的实际作用点。

背景:OpenVINO 为何不再附带预构建 OpenCV

教程原文(dnn_openvino.markdown,原作者 Aleksandr Voron,兼容 OpenCV 4.x)开宗明义:

自 2021.1.1 版本起,OpenVINO 不再提供预构建的 OpenCV。这一变化对直接使用 OpenVINO Runtime 或官方示例代码的用户没有影响——它们对 OpenCV 没有强依赖。但如果你使用的是 Open Model Zoo(OMZ)演示程序,或者把 OpenVINO Runtime 作为 OpenCV DNN 模块的推理后端,你就需要自行获取一个 OpenCV 构建。

这背后的接口边界在源码中可以直接印证:OpenCV 侧只需要 OpenVINO 的 C++ Runtime 头文件与链接库。探测脚本 cmake/OpenCVDetectInferenceEngine.cmake 只做一件事——find_package(OpenVINO QUIET),命中后把 openvino::runtime 封装为第三方目标 ocv.3rdparty.openvino,并注入 INF_ENGINE_RELEASEHAVE_NGRAPHHAVE_DNN_NGRAPHHAVE_INF_ENGINE 四个编译宏。也就是说,只要你的机器上装好了对应版本的 OpenVINO 开发包(含 CMake config 文件),OpenCV 就能通过 CMake 自动发现它。

两条路线获取 OpenCV 及其取舍

教程给出两条路线:

路线一:安装其他来源的预构建 OpenCV(系统包管理器、pip、conda、homebrew)。通用预构建包存在以下限制:

  • OpenCV 版本可能已过时;
  • 可能不含启用 OpenVINO 支持的 G-API 模块(部分 OMZ 演示依赖 G-API 功能);
  • 未针对现代硬件优化(通用构建必须覆盖极宽的硬件谱系);
  • 可能不支持 Intel TBB、Intel Media SDK;
  • DNN 模块可能没有启用 OpenVINO 作为推理后端。

路线二:针对特定版本 OpenVINO 从源码构建 OpenCV。这是教程推荐的方式,可解除上述全部限制。完整的逐步构建指令收录在 OpenCV 项目官方的 BuildOpenCV4OpenVINO wiki 页面中(教程原文指向该页面),本文则在此基础上补齐构建时 CMake 选项与运行期行为的源码级细节。

构建开关:WITH_OPENVINO 取代 WITH_INF_ENGINE

在仓库根目录的 CMakeLists.txt 中可以看到关键的构建选项定义:

# replacement for deprecated options: WITH_INF_ENGINE, WITH_NGRAPH
OCV_OPTION(WITH_OPENVINO "Include Intel OpenVINO toolkit support" (WITH_INF_ENGINE)
  VISIBLE_IF TRUE
  VERIFY TARGET ocv.3rdparty.openvino)

要点:

  • WITH_OPENVINO 是现行开关,旧的 WITH_INF_ENGINE / WITH_NGRAPH 已被标记为弃用,其取值会被自动承接(WITH_OPENVINO 的默认值即 (WITH_INF_ENGINE)),因此老构建脚本无需修改;
  • 配置阶段当 WITH_INF_ENGINE OR WITH_OPENVINO 成立时,才会 include OpenCVDetectInferenceEngine.cmake 去探测 OpenVINO 安装;
  • 探测成功后,构建摘要会打印 OpenVINO: YES (<版本号>),这是确认集成是否生效的第一道检查点(见 CMakeLists.txt)。

DNN 模块侧还有第二道开关,位于 modules/dnn/CMakeLists.txt

ocv_option(OPENCV_DNN_OPENVINO "Build with OpenVINO support (2021.4+)" (TARGET ocv.3rdparty.openvino))
if(TARGET ocv.3rdparty.openvino AND OPENCV_DNN_OPENVINO)
  if(NOT HAVE_OPENVINO AND NOT HAVE_NGRAPH)
    message(FATAL_ERROR "DNN: Inference Engine is not supported without enabled 'nGraph'. Check build configuration.")
  endif()
  ...

这里有两个实操要点:

  1. 注释中 2021.4+ 表明该源码树按 OpenVINO 2021.4 及以上版本的 C++ API 对接,构建时应保证 OpenVINO 版本不低于此基线;
  2. 若目标 ocv.3rdparty.openvino 存在但既没有 HAVE_OPENVINO 也没有 HAVE_NGRAPH 宏,CMake 会直接 FATAL_ERROR 终止配置——即“只有旧版 nGraph 集成、没有 OpenVINO Runtime”的组合已不被接受。

链接方式上,默认情况下 OpenVINO 作为 dnn_runtime_libs 随主库链接;若启用了 DNN 插件机制(DNN_PLUGIN_LISTopenvinoall),则会改为构建独立插件 misc/plugin/openvino,由 modules/dnn/CMakeLists.txt 分支处理。

把 OpenVINO 设为默认推理后端

DNN 模块允许在构建期指定默认后端,避免每次调用 setPreferableBackend

# modules/dnn/CMakeLists.txt
set(OPENCV_DNN_BACKEND_DEFAULT "" CACHE STRING "Default backend used by the DNN module (DNN_BACKEND_OPENCV if empty)")

modules/dnn/CMakeLists.txt#L568-L571。留空(默认)时回落到 DNN_BACKEND_OPENCV;设为 DNN_BACKEND_INFERENCE_ENGINE(或字符串 inf_engine)后,该值会作为编译期宏注入 dnn_params.cpp。运行期解析逻辑同样在 dnn_params.cpp 中:

static int PARAM_DNN_BACKEND_DEFAULT = (int)utils::getConfigurationParameterSizeT("OPENCV_DNN_BACKEND_DEFAULT",
#ifdef OPENCV_DNN_BACKEND_DEFAULT
        (size_t)OPENCV_DNN_BACKEND_DEFAULT
#else
        (size_t)DNN_BACKEND_OPENCV
#endif
);

即优先级为:运行期配置参数 OPENCV_DNN_BACKEND_DEFAULT(环境变量或配置文件)> 构建期编译宏 > 默认 DNN_BACKEND_OPENCV。这意味着你可以为同一份 OpenCV 构建在不同部署环境里切换默认后端而无需重新编译。

支持的推理目标设备

教程的“Supported targets”一节列出了 DNN_BACKEND_INFERENCE_ENGINE 支持的六类目标。该列表与 dnn.hppDNN_BACKEND_INFERENCE_ENGINE = 2 枚举项的文档注释一致,并可通过 dnn.hppTarget 枚举核对。逐条说明如下:

目标常量 运行设备 依赖条件
DNN_TARGET_CPU CPU 无额外依赖
DNN_TARGET_OPENCLDNN_TARGET_OPENCL_FP16 集成显卡 iGPU 需要 OpenCL 驱动;Ubuntu 上需安装 intel-opencl-icd
DNN_TARGET_MYRIAD Intel VPU(如 Neural Compute Stick 2,MyriadX) 按 NCS2 官方文档安装驱动
DNN_TARGET_HDDL Intel Movidius Myriad X 高密度 VPU(HDDL) 按 Intel 文档配置 HDDL 平台支持
DNN_TARGET_FPGA Intel Altera 系列 FPGA 使用 Inference Engine 的 Heterogeneous 插件,FPGA 上带 CPU 回退(见 dnn.hpp 注释)
DNN_TARGET_NPU 集成 Intel AI Boost 处理器 Linux 或 Windows 官方 NPU 驱动

教程特别指出 Ubuntu 下 iGPU 推理需要 intel-opencl-icd 包(OpenCL ICD 加载器与 Intel 实现)。

目标常量到 OpenVINO 设备名的映射

上述常量在底层并不是直接透传的。在 ie_ngraph.cpp 中可以看到严格的 switch 映射:

switch (targetId)
{
    case DNN_TARGET_CPU:
        device_name = "CPU";
        break;
    case DNN_TARGET_OPENCL:
    case DNN_TARGET_OPENCL_FP16:
        device_name = "GPU";
        break;
    case DNN_TARGET_MYRIAD:
        device_name = "MYRIAD";
        break;
    case DNN_TARGET_HDDL:
        device_name = "HDDL";
        break;
    case DNN_TARGET_FPGA:
        device_name = "FPGA";
        break;
    case DNN_TARGET_NPU:
        device_name = "NPU";
        break;
    default:
        CV_Error(Error::StsNotImplemented, "Unknown target");
};

注意 DNN_TARGET_OPENCLDNN_TARGET_OPENCL_FP16 都映射到同一个 "GPU" 设备名,FP16 与否的差异体现在精度处理上;传入其他目标(如 DNN_TARGET_CUDA)会直接抛 Unknown target 错误。同样地,NetImplOpenVINO::validateBackendAndTarget()net_openvino.cpp 中对 preferableTarget 做了同样的白名单校验,非法目标会在配置阶段就被 CV_Check 拦截。

从源码结构看还有两处针对特定设备的适配逻辑(ie_ngraph.cpp):

  • MYRIADHDDL 设备,会设置编译属性 MYRIAD_DETECT_NETWORK_BATCH = "NO"
  • FPGA 被标记为异构(Hetero)设备,运行时会走 CPU 回退路径;而纯 CPU 目标在非 Windows 平台还会通过 ov::inference_num_threads 限制 CPU 线程数(ie_ngraph.cpp)。

运行期使用:后端切换、设备选择与相关参数

基本调用方式

dnn.hpp 中的官方后端/目标支持矩阵(dnn.hpp)表明:DNN_BACKEND_OPENCV 支持 DNN_TARGET_CPU/OPENCL/OPENCL_FP16;而 DNN_BACKEND_INFERENCE_ENGINE 支持 CPUOPENCLOPENCL_FP16MYRIADFPGAHDDL(加上源码中额外校验通过的 NPU)。仓库自带测试 test_ie_models.cpp 展示了标准用法骨架:

// 读取 OpenVINO IR 模型(.xml + .bin)
Net net = readNet(xmlPath, binPath);
net.setInput(inputMat);

// 指定后端与目标设备
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(target);   // DNN_TARGET_CPU / MYRIAD / NPU / ...

std::vector<String> outNames = net.getUnconnectedOutLayersNames();
net.forward(outs, outNames);

两点源码级细节值得注意:

  • 一旦网络已交给 OpenVINO 后端,setPreferableBackend 再传入 OpenVINO 系枚举是 no-op;若尝试切回其他后端且网络是 OpenVINO 原生加载器创建的,会直接报错(net_openvino.cpp);
  • 切换 preferableTarget 会触发 clear() 释放既有资源(net_openvino.cpp),即每次改目标都会重新建图,属于预期行为。

异步推理

OpenVINO 后端还支持异步前向。Net::forwardAsync() 的文档注明“需要 DNN_BACKEND_INFERENCE_ENGINE 后端”(dnn.hpp)。底层实现在 ie_ngraph.cpp:异步模式下输入/输出 blob 会先复制到独立内存(copyBlob),推理请求以 promise/future 形式管理,AsyncArray 的等待逻辑据此完成同步。

与设备相关的运行期参数

以下参数均可通过环境变量或 utils::setConfigurationParameter 在运行期注入:

参数 作用 源码位置
OPENCV_DNN_BACKEND_DEFAULT 运行期默认后端,优先级高于构建期宏 dnn_params.cpp
OPENCV_DNN_IE_GPU_CACHE_DIR GPU(iGPU)编译内核缓存目录,默认落在用户缓存目录下的 dnn_ie_cache_GPU;设为 disabled 可关闭 ie_ngraph.cpp
OPENCV_DNN_IE_EXTRA_PLUGIN_PATH 指向自定义插件的完整路径,用于补充某些网络所需的额外算子;加载失败时会打印警告并提示通过该参数指定路径 ie_ngraph.cpp
OPENCV_DNN_IE_VPU_TYPE 指定 VPU 型号,取值见 inference_engine.hppMyriad2(NCS)/ MyriadX(NCS2) 同上
OPENCV_DNN_IE_CPU_TYPE 指定 OpenVINO 插件的 CPU 类型:X86ARM_COMPUTE(ARM 平台用) 同上

头文件 inference_engine.hpp 还暴露了几个与设备生命周期相关的工具函数,对应教程中提到的特殊硬件约束:

  • resetMyriadDevice():释放 Myriad 设备绑定。注释明确“单个 Myriad 设备不能被多个使用 Inference Engine Myriad 插件的进程共享”,这是 NCS/NCS2 用户最常踩的坑;
  • releaseHDDLPlugin():释放 HDDL 插件;
  • getInferenceEngineVPUType() / getInferenceEngineCPUType():查询当前生效的 VPU/CPU 类型。

另外注意一处版本语义:历史上 OpenVINO 后端内部有 NN_BUILDER 与 nGraph 两套 API(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API / CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH),现已全部标记 @deprecated,且运行期参数 OPENCV_DNN_BACKEND_INFERENCE_ENGINE_TYPE 自 4.6.0 起被忽略(inference_engine.hpp)。当前源码树中 NetImplOpenVINO 也固定使用 DNN_BACKEND_INFERENCE_ENGINE_NGRAPH 作为内部后端标识(net_openvino.cpp),即 nGraph/OpenVINO 原生加载路径是唯一实现。

构建验证与测试入口

构建完成后,可以通过两条路径验证 OpenVINO 集成:

  1. 配置摘要:CMake 输出中的 OpenVINO: YES (<版本>)CMakeLists.txt)是最直接的确认;
  2. DNN 测试modules/dnn/CMakeLists.txt 中的 OPENCV_TEST_DNN_OPENVINO 选项默认跟随 ocv.3rdparty.openvino 目标存在性,开启后为 opencv_test_dnn 链接 OpenVINO 运行时,测试套件 test_ie_models.cpp 会在不同目标设备上加载 IR 模型执行前向推理,并与 OpenCV 后端的结果做交叉验证。此外 test_backends.cpptest_common.impl.hpp 等测试文件中也大量出现 DNN_BACKEND_INFERENCE_ENGINE 相关的条件分支,覆盖后端切换、量化、算子一致性等场景。

小结:适用前提与限制

  • 本文所有结论基于当前 OpenCV 4.x 源码树,对应教程声明的兼容性范围(OpenCV == 4.x);DNN 的 OpenVINO 支持按 OpenVINO 2021.4+ API 对接;
  • WITH_INF_ENGINE / WITH_NGRAPH 已弃用,新构建脚本应使用 WITH_OPENVINO(可自动承接旧选项值);
  • 目标设备能力取决于运行环境:iGPU 需要 OpenCL ICD 驱动,MYRIAD/NPU 需要对应硬件驱动,FPGA 走 Heterogeneous 插件带 CPU 回退;构建成功不代表所有目标都可用,运行期 setPreferableTarget 的白名单校验(net_openvino.cpp)会拦截非法组合;
  • Myriad 设备单进程独占、HDDL 插件释放等特殊约束,通过 inference_engine.hpp 提供的 API 处理。

按照“源码构建 + OPENCV_DNN_BACKEND_DEFAULT/setPreferableBackend 切换 + 目标设备常量”这条主线,你即可把 OpenCV DNN 模块部署到从桌面 CPU 到 AI Boost NPU 的完整 Intel 加速谱系上。

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