高性能SDK套件 - C++接口
信息
本文对应 OpenIVS 提供的 C++ API,接口源码与 Visual Studio 工程位于 OpenIVS 仓库。
完整调用示例见 C++测试程序-例程。
开发文件
核心 SDK 通过 AI 平台安装,C++ 接口和 Qt 例程从 OpenIVS 构建,运行时 DLL 放在例程同目录。
| 配置 | 正确位置 |
|---|---|
| 底层 SDK DLL 与头文件 | <Python环境>/Lib/site-packages/dlcvpro_infer |
| C++ 包装头文件 | <OpenIVS>/dlcv_infer_cpp/dlcv_infer.h、dlcv_sntl_admin.h |
| C ABI 头文件 | <OpenIVS>/dlcv_infer_cpp/dlcv_infer_c_api.h |
| C++ DLL 与导入库(解决方案构建) | <OpenIVS>/<配置>/dlcv_infer_cpp.dll、dlcv_infer_cpp.lib |
| C++ DLL 与导入库(单独构建工程) | <OpenIVS>/dlcv_infer_cpp/<配置>/ |
| Qt 例程输出 | <OpenIVS>/<配置>/dlcv_infer_cpp_qt_demo/ |
独立调用工程需要配置以下目录:
- 包含目录:
<OpenIVS>/dlcv_infer_cpp、<Python环境>/Lib/site-packages/dlcvpro_infer/include和 OpenCV 4.x 头文件目录 - 库目录:选择与调用工程配置一致的 OpenIVS 构建输出目录
- 运行目录:放置同一配置生成的
dlcv_infer_cpp.dll;底层dlcv_infer.dll或dlcv_infer_v.dll由封装层从核心 SDK 目录加载
C++ 接口使用 std::string、std::vector、nlohmann::json 和 cv::Mat。调用工程应使用 x64、C++17,并采用与 SDK 兼容的 Visual C++ 与 OpenCV 运行环境。Debug 与 Release 文件不可混用。
常用接口
namespace dlcv_infer
{
using json = nlohmann::json;
class Model
{
public:
int modelIndex = -1;
bool OwnModelIndex = true;
Model();
Model(const std::string& modelPath, int device_id);
Model(const std::wstring& modelPath, int device_id);
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
Model(Model&& other) noexcept;
Model& operator=(Model&& other) noexcept;
virtual ~Model();
void FreeModel();
json GetModelInfo();
json GetDvsModelInfo();
Result Infer(
const cv::Mat& image,
const json& params_json = nullptr);
Result InferBatch(
const std::vector<cv::Mat>& image_list,
const json& params_json = nullptr);
json InferOneOutJson(
const cv::Mat& image,
const json& params_json = nullptr);
static void GetLastInferTiming(
double& dlcvInferMs,
double& totalInferMs);
static std::vector<FlowNodeTiming> GetLastFlowNodeTimings();
static bool GetLastInspectionStatus(
bool& ok,
std::vector<std::string>& reasons,
size_t sampleIndex = 0);
};
class Utils
{
public:
static std::string JsonToString(const json& value);
static void FreeAllModels();
static json GetDeviceInfo();
static Result OcrInfer(
Model& detectModel,
Model& recognizeModel,
const cv::Mat& image);
static json GetGpuInfo();
static void KeepMaxClock();
};
json GetAllDogInfo();
}
以上签名与 dlcv_infer_cpp.dll 的 C++ 导出一致。动态库还包含流程模型、C ABI 和测试检查使用的导出;普通 C++ 推理程序主要使用本页列出的接口。
加载模型
Windows 下推荐使用 std::wstring 传递模型路径,避免中文路径经过窄字符串转换:
#include "dlcv_infer.h"
std::wstring modelPath = LR"(D:\dlcv_demo\balloon.dvt)";
int deviceId = 0;
dlcv_infer::Model model(modelPath, deviceId);
modelPath:模型文件路径。std::wstring直接传入 UTF-16 路径;std::string重载会先尝试按 UTF-8 解析,无法往返转换时再按 GBK 解析device_id:-1表示 CPU,非负整数表示 GPU 编号;可用设备还受模型格式和运行环境限制- 构造函数完成模型加载,加载失败时抛出异常
获取模型信息:
auto info = model.GetModelInfo();
std::cout << dlcv_infer::Utils::JsonToString(info) << std::endl;
图像输入
Infer 和 InferBatch 接收 cv::Mat。彩色输入采用 RGB 通道顺序,OpenCV imread 默认返回 BGR,需要在调用前转换:
cv::Mat decoded = cv::imread(R"(D:\dlcv_demo\balloon.jpg)", 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;
dlcv_infer::Result result = model.Infer(inferImage, params);
批量图
std::vector<cv::Mat> images = {inferImage, inferImage};
dlcv_infer::json params;
params["threshold"] = 0.5;
params["with_mask"] = true;
params["calc_mean"] = false;
params["batch_size"] = static_cast<int>(images.size());
dlcv_infer::Result result = model.InferBatch(images, params);
InferBatch 返回的 sampleResults 与输入图片顺序对应。批量大小应在模型支持范围内,并与传入图片数量一致。
JSON 结果
dlcv_infer::json resultJson = model.InferOneOutJson(inferImage, params);
普通模型返回当前图片的结果数组,实例分割的 mask 会转换为轮廓点。流程模型产生判定状态时,返回对象包含 result_list、ok 和 reason;也可在同一线程调用 GetLastInspectionStatus 读取最近一次判定状态。
结果结构
struct ObjectResult
{
int categoryId;
std::string categoryName;
float score;
float area;
std::vector<double> bbox;
bool withMask;
cv::Mat mask;
bool withBbox;
bool withAngle;
float angle;
bool withMean;
double foregroundMean;
double backgroundMean;
};
struct SampleResult
{
std::vector<ObjectResult> results;
};
struct Result
{
std::vector<SampleResult> sampleResults;
};
categoryName:Windows C++ 结构化结果使用 GBK 编码bbox:水平框为[x, y, width, height];旋转框中心、宽高保存在bbox,角度保存在anglemask:withMask=true时为CV_8UC1图像withMean:表示foregroundMean和backgroundMean是否有效InferOneOutJson返回的类别名称使用 JSON 的 UTF-8 字符串
结果遍历示例:
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不可复制,可以移动Model析构时默认释放其拥有的底层模型,也可提前调用FreeModel()Infer、InferBatch和InferOneOutJson会在内部释放底层返回指针,调用端无需另行释放Utils::FreeAllModels()会释放当前进程中由封装层管理的全部模型,应在推理工作停止后调用- 不需要共享已有
modelIndex时,不要修改OwnModelIndex