C++测试程序-例程
本页使用 OpenIVS 的 dlcv_infer_cpp_qt_demo 演示 C++ 模型加载、图片预处理、推理和结果读取。接口定义见 高性能SDK套件 - C++接口。
代码地址
- OpenIVS:https://github.com/dl-cv/OpenIVS
- C++ Qt 例程:https://github.com/dl-cv/OpenIVS/tree/master/dlcv_infer_cpp_qt_demo
- 主窗口代码:MainWindow.cpp
- 程序入口:main.cpp
- Visual Studio 工程:dlcv_infer_cpp_qt_demo.vcxproj
例程通过 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 例程
- 启动
dlcv_infer_cpp_qt_demo。 - 选择设备。GPU 编号从
0开始;-1表示 CPU,是否支持由模型格式决定。 - 单击“加载模型”,选择 balloon 模型。
- 将批量大小设为
1、阈值设为0.5,均值计算保持关闭。 - 单击“打开图片推理”,选择 balloon 图片。
- 文本区显示推理耗时、目标数量、类别、分数和检测框等结构化信息;图像区按照结果字段绘制检测框与 mask。
- 需要查看 JSON 时,单击“推理JSON”。
- 更换模型前先单击“释放模型”,程序退出时还会调用
Utils::FreeAllModels()。
下面是 Qt 例程加载气球模型后的完整窗口。左侧显示推理信息,右侧显示气球的检测框和分割结果。

命令行气球示例
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.cpp 的 onLoadModel | 选择模型、释放旧模型、创建 dlcv_infer::Model |
| 图像读取 | MainWindow.cpp 的 loadCurrentImage | 使用 OpenCV 保留原始位深与通道 |
| RGB 转换 | MainWindow.cpp 的 prepareImageForInference | BGR/BGRA 转换为 RGB |
| 结构化推理 | MainWindow.cpp 的 onInfer | 组织参数并调用 InferBatch |
| JSON 推理 | MainWindow.cpp 的 onInferJson | 调用 InferOneOutJson |
| 全部释放 | MainWindow.cpp 的 onFreeAllModels、main.cpp | 调用 Utils::FreeAllModels() |
常见检查
模型加载失败
确认以下文件和环境可用:
dlcv_infer_cpp.dll与调用程序位数一致dlcv_infer.dll或dlcv_infer_v.dll可由封装层找到- 模型授权环境可用
- OpenCV 与 Visual C++ 运行库版本满足工程配置
图片无法读取
OpenCV 的窄字符串图片路径在 Windows 下使用本地编码。图片路径包含中文且读取失败时,可改用纯英文目录,或参考例程命令行模式中 QFile 读取字节后调用 cv::imdecode 的方式。
结果为空
确认输入彩色图已转换为 RGB,并检查阈值是否适合当前模型。不要依据固定目标数量判断成功,应结合模型信息、结构化结果和可视化结果检查。