跳到主要内容

C++测试程序-例程

本页使用 OpenIVS 的 dlcv_infer_cpp_qt_demo 演示 C++ 模型加载、图片预处理、推理和结果读取。接口定义见 高性能SDK套件 - C++接口

代码地址

例程通过 dlcv_infer.h 调用 C++ API,链接 dlcv_infer_cpp.lib,运行时使用 dlcv_infer_cpp.dll

环境准备

开始前准备以下环境:

  • Windows x64
  • Visual Studio 2022,安装“使用 C++ 的桌面开发”
  • Qt 6
  • OpenCV 4.x
  • 已安装并可正常授权的高性能 SDK 套件

核心 SDK 通过 AI 平台安装,C++ 接口和 Qt 例程从 OpenIVS 构建,运行时 DLL 放在例程同目录。

获取代码

git clone https://github.com/dl-cv/OpenIVS.git

打开 OpenIVS.sln,选择 x64 配置,将 dlcv_infer_cpp_qt_demo 设为启动项目。Qt、OpenCV 和 SDK 头文件目录应按本机安装位置配置。

配置路径
C++ 包装头文件<OpenIVS>/dlcv_infer_cpp
底层 SDK 头文件<Python环境>/Lib/site-packages/dlcvpro_infer/include
C++ DLL 与导入库<OpenIVS>/<配置>/
Qt 例程输出<OpenIVS>/<配置>/dlcv_infer_cpp_qt_demo/

balloon 推理流程

可使用 balloon 语义分割模型和对应图片完成入门操作。示例文件名:

  • 模型:气球-语义分割_120_50_s.dvt
  • 图片:气球.jpg

实际文件名可不同,但模型与图片内容应匹配。为减少 Windows 窄字符串路径的编码影响,可将演示文件复制到仅含英文和数字的目录,并在自写代码中优先使用 std::wstring 模型路径。

使用 Qt 例程

  1. 启动 dlcv_infer_cpp_qt_demo
  2. 选择设备。GPU 编号从 0 开始;-1 表示 CPU,是否支持由模型格式决定。
  3. 单击“加载模型”,选择 balloon 模型。
  4. 将批量大小设为 1、阈值设为 0.5,均值计算保持关闭。
  5. 单击“打开图片推理”,选择 balloon 图片。
  6. 文本区显示推理耗时、目标数量、类别、分数和检测框等结构化信息;图像区按照结果字段绘制检测框与 mask。
  7. 需要查看 JSON 时,单击“推理JSON”。
  8. 更换模型前先单击“释放模型”,程序退出时还会调用 Utils::FreeAllModels()

下面是 Qt 例程加载气球模型后的完整窗口。左侧显示推理信息,右侧显示气球的检测框和分割结果。

C++测试程序气球语义分割结果

命令行气球示例

dlcv_infer_cpp_qt_demo 提供不启动窗口的 infer 模式。以下命令使用气球语义分割模型、阈值 0.5 和 GPU 0,并把 JSON 写入系统临时目录:

dlcv_infer_cpp_qt_demo.exe infer ^
--model "D:\dlcv_demo\气球-语义分割_120_50_s.dvt" ^
--image "D:\dlcv_demo\气球.jpg" ^
--threshold 0.5 ^
--device 0 ^
--with-mask true ^
--calc-mean false ^
--output "%TEMP%\dlcv_cpp_balloon.json"

该组示例文件的结果摘要如下:

{
"consistent": true,
"threshold_check_passed": true,
"structured": {
"count": 1,
"categories": ["气球"],
"scores": [1.0]
},
"json": {
"count": 1,
"categories": ["气球"],
"scores": [1.0]
}
}

consistent=true 表示结构化接口与 JSON 接口的类别、分数等摘要一致。更换模型文件、图片或运行硬件后,目标数量、分数和耗时可能变化。

保存可视化结果

render 模式使用与图形界面相同的结果绘制组件,并把检测框与 mask 保存为 PNG:

dlcv_infer_cpp_qt_demo.exe render ^
--model "D:\dlcv_demo\气球-语义分割_120_50_s.dvt" ^
--image "D:\dlcv_demo\气球.jpg" ^
--threshold 0.5 ^
--device 0 ^
--with-mask true ^
--output "%TEMP%\dlcv_cpp_balloon.png"

命令执行成功时返回退出码 0,输出图片保持输入图片尺寸,并绘制类别、分数、检测框和实例分割 mask。

最小 C++ 代码

以下代码与 Qt 例程使用相同的 dlcv_infer::Model、RGB 输入和结构化结果接口:

#include <iostream>
#include <stdexcept>
#include <vector>

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include "dlcv_infer.h"

int main()
{
try {
const std::wstring modelPath = LR"(D:\dlcv_demo\balloon.dvt)";
const std::string imagePath = R"(D:\dlcv_demo\balloon.jpg)";

dlcv_infer::Model model(modelPath, 0);

cv::Mat decoded = cv::imread(imagePath, cv::IMREAD_UNCHANGED);
if (decoded.empty()) {
throw std::runtime_error("image decode failed");
}

cv::Mat inferImage;
if (decoded.channels() == 3) {
cv::cvtColor(decoded, inferImage, cv::COLOR_BGR2RGB);
} else if (decoded.channels() == 4) {
cv::cvtColor(decoded, inferImage, cv::COLOR_BGRA2RGB);
} else {
inferImage = decoded.clone();
}

dlcv_infer::json params;
params["threshold"] = 0.5;
params["with_mask"] = true;
params["calc_mean"] = false;

const dlcv_infer::Result result = model.Infer(inferImage, params);

for (const auto& sample : result.sampleResults) {
for (const auto& object : sample.results) {
std::cout << "category_id=" << object.categoryId
<< ", score=" << object.score;

if (object.withBbox && object.bbox.size() >= 4) {
std::cout << ", bbox=["
<< object.bbox[0] << ", "
<< object.bbox[1] << ", "
<< object.bbox[2] << ", "
<< object.bbox[3] << "]";
}
std::cout << std::endl;
}
}

model.FreeModel();
return 0;
}
catch (const std::exception& error) {
std::cerr << error.what() << std::endl;
return 1;
}
}

模型对象离开作用域时会自动释放,因此示例中的 model.FreeModel() 可以省略;保留该调用便于展示主动释放方式。

例程代码对应位置

功能源码位置说明
模型加载dlcv_infer_cpp_qt_demo/MainWindow.cpponLoadModel选择模型、释放旧模型、创建 dlcv_infer::Model
图像读取MainWindow.cpploadCurrentImage使用 OpenCV 保留原始位深与通道
RGB 转换MainWindow.cppprepareImageForInferenceBGR/BGRA 转换为 RGB
结构化推理MainWindow.cpponInfer组织参数并调用 InferBatch
JSON 推理MainWindow.cpponInferJson调用 InferOneOutJson
全部释放MainWindow.cpponFreeAllModelsmain.cpp调用 Utils::FreeAllModels()

常见检查

模型加载失败

确认以下文件和环境可用:

  • dlcv_infer_cpp.dll 与调用程序位数一致
  • dlcv_infer.dlldlcv_infer_v.dll 可由封装层找到
  • 模型授权环境可用
  • OpenCV 与 Visual C++ 运行库版本满足工程配置

图片无法读取

OpenCV 的窄字符串图片路径在 Windows 下使用本地编码。图片路径包含中文且读取失败时,可改用纯英文目录,或参考例程命令行模式中 QFile 读取字节后调用 cv::imdecode 的方式。

结果为空

确认输入彩色图已转换为 RGB,并检查阈值是否适合当前模型。不要依据固定目标数量判断成功,应结合模型信息、结构化结果和可视化结果检查。