[onnxruntime]windows上C++ onnxruntime配置vs2022和简单测试

安装onnxruntime

去官方下载自己匹配cuda版本onnxruntime,根据自己的情况选择合适的版本,如果下载慢或者下载不下来可以去国内镜像下载gitee.com/FIRC/onnxruntime_mirror

博主的cuda版本是11.8,cudnn版本是8.9.7,因此选择OnnxRuntime v1.15.0版本。

cmd命令框下输入nvcc -V 查询cuda版本;
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vxx.x\include\cudnn_version.h 查看cuda版本.


在assert下选择onnxruntime-win-x64-gpu-1.15.0.zip下载

双击运行解压后即可:

打开VS 2019:新建新项目---->空项目---->配置项目---->项目路径以及勾选“将解决方案和项目放在同一目录中---->点击创建。
在解决方案–>源文件–>右键添加新建项。这里暂时可以默认空着不做处理。

配置onnxruntime:项目---->属性。假设没有新建cpp文件,空项目的属性页就不会存在C/C++这一项目。

添加附加包含目录:Release | x64---->C/C+±—>常规---->附加包含目录。

D:\C++_demo\onnxruntime-win-x64-gpu-1.15.0\include

链接器:Release | x64---->链接器---->常规---->附加库目录。

D:\C++_demo\onnxruntime-win-x64-gpu-1.15.0\lib

链接器:Release | x64---->链接器---->输入---->附加依赖项。

在D:\C++_demo\onnxruntime-win-x64-gpu-1.15.0\lib下找到附加依赖项的文件(.lib文件)。

onnxruntime.lib
onnxruntime_providers_cuda.lib
onnxruntime_providers_shared.lib

安装OpenCV

使用opencv-4.8.0-windows.exe版本

双击运行解压后即可,博主重命名为opencv4.8.0:

添加附加包含目录:Release | x64---->C/C++—>常规---->附加包含目录。

D:\C++_demo\opencv4.8.0\build\include

链接器:Release | x64---->链接器---->常规---->附加库目录。

D:\C++_demo\opencv4.8.0\build\x64\vc16\lib

链接器:Release | x64---->链接器---->输入---->附加依赖项。

opencv_world480.lib

简化部署

在Release x64模式下测试时,需要将OnnxRuntime所需的.dll文件,以及OpenCV的.dll文件复制到自己项目的Release下。

D:\C++_demo\onnxruntime-win-x64-gpu-1.15.0\lib
D:\C++_demo\opencv4.8.0\build\x64\vc16\bin
===>
D:\C++_demo\onnxruntime_onnx\x64\Release

没有Release目录时,需要在Release | x64模式下运行一遍代码,代码部分在下面提供,读者可以先行新建文件复制代码。

将所有的.dll文件和.exe文件放在同一个目录下可以简化应用程序的部署过程。用户无需手动配置环境变量或安装额外的组件即可运行程序。


ONNXRuntime调用onnx模型

ONNXRuntime推理核心流程

初始化ONNXRuntime环境
通常涉及到创建一个 Ort::Env 对象,它包含了线程池和其他运行时设置。

Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "AlexNet-onnx");
Ort::Env参数日志严重性级别 (logging severity level)环境名称 (environment name)
作用决定了哪些级别的日志信息将被记录下来,运行时提供了几个预定义的宏来表示不同的日志级别。主要用于标识特定的环境实例,尤其是在多线程或多进程环境中可以帮助追踪日志信息来源。
内容ORT_LOGGING_LEVEL_FATAL:仅记录致命错误;ORT_LOGGING_LEVEL_ERROR:记录错误信息;ORT_LOGGING_LEVEL_WARNING:记录警告信息;ORT_LOGGING_LEVEL_INFO:记录信息性消息;ORT_LOGGING_LEVEL_VERBOSE:记录详细的信息,包括调试信息。字符串

设置会话选项
通常包括配置优化器级别、线程数和设备(GPU/CPU)使用等。

Ort::SessionOptions session_options;
session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);
session_options.SetIntraOpNumThreads(4); 
OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);
OrtSessionOptionsAppendExecutionProvider_CPU(session_options, 1);
会换选项优化器级别线程数设备使用
函数SetGraphOptimizationLevelSetIntraOpNumThreadsSetExecutionMode
作用在模型加载到ONNXRuntime之前对其进行图优化的过程,提高执行效率设置每个运算符内部执行时的最大线程数CUDA/CPU设备选择,CUDA优先级设为0,CPU优先级设为1,优先尝试使用CUDA执行。
参数ORT_ENABLE_BASIC:基本的图优化; ORT_DISABLE_ALL:禁用所有优化;ORT_ENABLE_EXTENDED:启用扩展优化;ORT_ENABLE_ALL:启用所有优化。整型session_options:用于配置会话选项; 整型:优先级值,数值越低优先级越高。

加载模型并创建会话
加载预训练的ONNX模型文件,使用运行时环境、会话选项和模型创建一个Ort::Session对象。

Ort::Session session_(env, modelPath.c_str(), session_options);
Ort::Session参数Ort::Envmodel_pathsession_options
内容ONNX 运行时环境对象模型的位置或者模型的二进制数据会话选项

获取模型输入输出信息
从Ort::Session对象中获取模型输入和输出的详细信息,包括数量、名称、类型和形状。

Ort::AllocatorWithDefaultOptions allocator;
int input_nodes_num = session_.GetInputCount();
int output_nodes_num = session_.GetOutputCount();
auto input_name = session_.GetInputNameAllocated(i, allocator);
auto output_name = session_.GetOutputNameAllocated(i, allocator);
session_.GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();
session_.GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();

预处理输入数据
对输入数据进行颜色空间转换,尺寸缩放、标准化以及形状维度扩展操作。

cv::cvtColor(image, rgb, cv::COLOR_BGR2RGB);
cv::resize(rgb, blob, cv::Size(input_w, input_h));
blob.convertTo(blob, CV_32F);
blob = blob / 255.0;
cv::subtract(blob, cv::Scalar(0.485, 0.456, 0.406), blob);
cv::divide(blob, cv::Scalar(0.229, 0.224, 0.225), blob);
cv::Mat timg = cv::dnn::blobFromImage(blob);

这部分不是OnnxRuntime核心部分,根据任务需求不同,代码略微不同。

推理准备
创建输入和输出张量,这些张量是用于存储推理数据的内存块,分配内存给这些张量,以准备数据输入。

std::array<int64_t, 4> input_shape_info{ 1, 3, input_h, input_w };
auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, timg.ptr<float>(), tpixels, input_shape_info.data(), input_shape_info.size());
函数Ort::MemoryInfo::CreateCpuOrt::Value::CreateTensor
作用ONNX Runtime运行一个模型时,用于描述内存分配的信息,包括内存的位置(CPU 或 GPU)以及内存的具体类型(固定内存或常规内存)封装了张量数据,可以作为模型推理的输入或输出。
参数1OrtDeviceAllocator:默认的分配器类型,它用于分配设备(CPU或GPU)上的内存;OrtArenaAllocator:使用内存池来分配内存,可以减少内存分配和释放的开销,提高内存操作的效率;OrtCustomAllocator:自定义内存分配器。用于分配和管理张量数据的内存。
参数2OrtMemTypeCPUInput:表示任何非CPU使用的CPU内存,用于模型的输入,数据将由非CPU执行器(GPU)使用;OrtMemTypeCPUOutput: 由非CPU输出的、CPU可访问的内存,用于模型的输出,确保数据在CPU上可用;OrtMemTypeCPU:通常与 OrtMemTypeCPUOutput 相同,指CPU可访问的内存;OrtMemTypeDefault:表示执行器的默认内存分配器,用于分配内存时没有特别指定其他类型时使用。张量的形状
参数3-----张量的大小
参数4-----张量的指针
参数6-----张量的维度数
参数3-----张量的数据类型

执行推理
调用Ort::Session::Run方法,传入输入张量、输出张量和其他必要的参数,执行推理。

ort_outputs = session_.Run(Ort::RunOptions{ nullptr }, inputNames.data(), &input_tensor_, 1, outNames.data(), outNames.size());
session_.Run参数run_optionsinput_namesinput_valuesinput_countoutput_namesoutput_count
含义是否进行性能分析、是否仅执行到达特定输出的最小子图等,通常是默配置。输入节点名称数组用于存储模型的输入数据Ort::Value输入数量输出节点名称数组输出数量

后处理推理结果
推理完成后,从输出张量中获取结果数据,根据需要对结果进行后处理,以获得最终的预测结果。

const float* pdata = ort_outputs[0].GetTensorMutableData<float>();
cv::Mat prob(num, nc, CV_32F, (float*)pdata);
cv::minMaxLoc(prob, &minv, &maxv, &minL, &maxL);

这部分不是OnnxRuntime核心部分,根据任务需求不同,代码基本不同。


ONNXRuntime推理测试代码,可以随便找个onnx模型

 
#include <iostream>
#include<onnxruntime_cxx_api.h>
using namespace std;
using namespace Ort;
int main()
{
 
    const wchar_t* model_path = L"D:\\yolov8s.onnx";//模型路径
    Ort::Env env;//创建env
    Ort::Session session(nullptr);//创建一个空会话
    Ort::SessionOptions sessionOptions{ nullptr };//创建会话配置
    session = Ort::Session(env, model_path, sessionOptions);
 
    //获取输入节点数量,名称和shape
 
    size_t inputNodeCount= session.GetInputCount();
    std::cout << "输入节点数量:" << inputNodeCount << "\n";
 
    Ort::AllocatorWithDefaultOptions allocator;
 
    std::shared_ptr<char> inputName = std::move(session.GetInputNameAllocated(0, allocator));
    std::vector<char*> inputNodeNames;
    inputNodeNames.push_back(inputName.get());
    std::cout << "输入节点名称:" << inputName << "\n";
 
 
    Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0);
    auto input_tensor_info = inputTypeInfo.GetTensorTypeAndShapeInfo();
    ONNXTensorElementDataType inputNodeDataType = input_tensor_info.GetElementType();
    std::vector<int64_t> inputTensorShape = input_tensor_info.GetShape();
    std::cout << "输入节点shape:";
    for (int i = 0; i<inputTensorShape.size(); i++)
    {
        std::cout << inputTensorShape[i]<<" ";
    }
    std::cout << "\n";
 
 
    //获取输出节点数量、名称和shape
    size_t outputNodeCount = session.GetOutputCount();
    std::cout << "输出节点数量:" << outputNodeCount << "\n";
 
    std::shared_ptr<char> outputName = std::move(session.GetOutputNameAllocated(0, allocator));
    std::vector<char*> outputNodeNames;
    outputNodeNames.push_back(outputName.get());
    std::cout << "输出节点名称:" << outputName << "\n";
 
 
    Ort::TypeInfo type_info_output0(nullptr);
    type_info_output0 = session.GetOutputTypeInfo(0);  //output0
 
    auto tensor_info_output0 = type_info_output0.GetTensorTypeAndShapeInfo();
    ONNXTensorElementDataType outputNodeDataType = tensor_info_output0.GetElementType();
    std::vector<int64_t> outputTensorShape = tensor_info_output0.GetShape();
    std::cout << "输出节点shape:";
    for (int i = 0; i<outputTensorShape.size(); i++)
    {
        std::cout << outputTensorShape[i]<<" ";
    }
    std::cout << "\n";
	getchar();
}

### 回答1: 要在 Maven 项目中使用 Gson 库,需要在 pom.xml 文件中添加以下依赖项: ```xml <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.7</version> </dependency> ``` 添加依赖项后,Maven 会自动从 Maven 仓库下载 Gson 库并将其添加到项目的 classpath 中。然后,你可以通过在代码中导入 Gson 类来使用它,例如: ```java import com.google.gson.Gson; public class Example { public static void main(String[] args) { Gson gson = new Gson(); // 使用 Gson 进行 JSON 序列化反序列化等操作 } } ``` ### 回答2: 要配置 Maven 使用 Gson,首先需要在项目的 pom.xml 文件中引入 Gson 的依赖。在 `<dependencies>` 标签中添加以下代码: ```xml <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.8</version> </dependency> ``` 这将下载 Gson 的 jar 文件并添加到项目的类路径中。 完成依赖配置后,你可以在代码中使用 Gson 了。首先,需要导入 Gson 类: ```java import com.google.gson.Gson; ``` 然后,你可以创建 Gson 对象并使用其提供的方法进行序列化反序列化操作。例如,将一个对象转换为 JSON 字符串: ```java Gson gson = new Gson(); String json = gson.toJson(object); ``` 其中,`object` 是你要转换的对象。你可以将 JSON 字符串转换为对象: ```java String json = "{'name':'John', 'age':30}"; Person person = gson.fromJson(json, Person.class); ``` 其中,`Person` 是你的对象类。 配置完成后,你便可以在项目中使用 Gson 进行 JSON 数据的序列化反序列化操作了。 ### 回答3: 在Maven项目中配置Gson非常简单。首先,需要在项目的pom.xml文件中添加Gson依赖项。可以使用以下代码将Gson添加到Maven项目中: ```xml <dependencies> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> </dependency> </dependencies> ``` 在添加依赖项之后,Maven会自动下载并将Gson库添加到项目中。 完成这一步骤后,就可以在项目的Java代码中使用Gson了。首先,需要在代码中导入Gson类。代码示例如下: ```java import com.google.gson.Gson; ``` 然后,可以创建一个Gson对象并使用其提供的方法进行相关操作。例如,可以将一个Java对象序列化为JSON字符串,或将一个JSON字符串反序列化为一个Java对象。以下是一个简单的示例: ```java public class Main { public static void main(String[] args) { // 创建Gson对象 Gson gson = new Gson(); // 将Java对象序列化为JSON字符串 Person person = new Person("John", "Doe", 30); String json = gson.toJson(person); System.out.println(json); // 将JSON字符串反序列化为Java对象 String json2 = "{\"firstName\":\"Jane\",\"lastName\":\"Smith\",\"age\":25}"; Person person2 = gson.fromJson(json2, Person.class); System.out.println(person2.getFirstName()); System.out.println(person2.getLastName()); System.out.println(person2.getAge()); } } ``` 这样,我们就成功地在Maven项目中配置了Gson并使用它进行了相关操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值