【OpenVINO】OpenVINO C# API 常用 API 详解与演示

您所在的位置:网站首页 openvino部署后输入数据需要转Tensor吗 【OpenVINO】OpenVINO C# API 常用 API 详解与演示

【OpenVINO】OpenVINO C# API 常用 API 详解与演示

#【OpenVINO】OpenVINO C# API 常用 API 详解与演示| 来源: 网络整理| 查看: 265

OpenVINO C# API 常用 API 详解与演示 1 安装OpenVINO C# API2 导入程序集 3 初始化OpenVINO 运行时内核4 加载并获取模型信息4.1 加载模型4.2 获取模型信息 5 编译模型并创建推理请求6 张量Tensor6.1 张量的获取与设置6.2 张量的信息获取与设置 7 加载推理数据7.1 获取输入张量7.2 添加推理数据 8 模型推理9 获取推理结果10 释放分配的内存11 Yolov8分类模型示例12 总结

  OpenVINO™ 工具套件可以加快深度学习视觉应用开发速度,帮助用户在从边缘到云的各种英特尔平台上,更加方便快捷的将 AI 模型部署到生产系统中。OpenVINO™ 2023.1 LTS 版本现已发布,可帮助你快速轻松地开发卓越的人工智能应用,并跨边缘和云端部署深度学习推理工作负载,无论你处于人工智能编程的什么阶段。   C# 是由 C 和 C++ 衍生出来的一种安全的、稳定的、简单的、优雅的面向对象编程语言,它综合了 VB 简单的可视化操作和 C++ 的高运行效率,成为支持成为.NET 开发的首选语言。作为人工智能开发人员,如果你希望在 C# 端使用 OpenVINO™ ,OpenVINO C# API将是你的首选,并且制作了 NuGet 程序包,实现在 C# 端了一站式安装与使用 OpenVINO™ 。   项目的首发网址:OpenVINO™ C# API 详解与演示 | 开发者实战。   OpenVINO C# API在制作时参考了OpenVINO™ C++ API,因此对于之前使用过OpenVINO™ 的人十分友好。下面表格向我们展示了 C# 与 C++ API的对应关系

ClassC++ APIC# API说明Core classov::CoreCoreOpenVINO运行时核心实体类Model classov::ModelModel用户自定义模型类CompiledModel classov::CompiledModelCompiledModel已编译的模型类Output classov:: OutputOutput节点输出的句柄类Input classov:: InputInput节点输入的句柄类InferRequest classov::InferRequestov::InferRequest以异步或同步方式运行推断请求的类Tensor classov::TensorTensor张量Shape classov::ShapeShape张量的形状类

  在本文中,将会根据模型部署的一般步骤,演示从模型加载到推理的方法函数使用方式,并于C++ API 做对比。

1 安装OpenVINO C# API

  OpenVINO C# API 支持 NuGet 程序包安装方式,这与在C++中安装过程相比,较为简单,并且程序包中包含了最新版的 OpenVINO™ 2023.1 发行版本的 Release,可以通 过 NuGet 安装后直接使用。

  如果使用Visual Studio 编译该项目,则可以通过 NuGet 程序包管理功能直接安装即可:

在这里插入图片描述

  如果通过dotnet命令方式安装,通过下面语句进行安装即可:

dotnet add package OpenVINO.CSharp.win 2 导入程序集

  OpenVINO C# API 程序集全部在CSharp命名空间下,因此若要使用 OpenVINO C# API,需要先引入命名空间:

using OpenVinoSharp; 3 初始化OpenVINO 运行时内核

  Core类代表一个OpenVINO运行时核心实体,后续的读取模型、加载模型等方法都需要通过 Core 类进行创建,在封装C# API 时,为了与 C++ API 对应,也对 Core 类进行了封装,并封装了与 C++ API 中对应的方法

在C#中的初始化方式:

Core core = new Core();

在C++中的初始化方式:

ov::Core core; 4 加载并获取模型信息 4.1 加载模型

  OpenVINO™ 2022.1版本更新之后,加载,下面是所使用的 API 方法:

API作用Core.read_model ()将模型从硬盘载入内存,并返回Model对象。

在C#中加载模型的方式:

Model model = core.read_model(model_path);

在C++中的初始化方式:

std::shared_ptr model = core.read_model(model_path); 4.2 获取模型信息

  通过 Core.read_model ()方法获得的 Model 对象和通过 Core.compile_model ()方法获得的 CompiledModel 对象,都支持直接访问属性获取输入与输出层信息。以Model对象获取模型信息为例,下面是所使用的 API 方法:

API作用Model.get_friendly_name()获取模型的friendly name。Model.input()获取模型的输入层,并返回 Input对象。Model.output()获取模型的输出层,并返回 Output对象。

  Input/Output 主要是封装了模型网络层,可以通过下面 API 实现获取模型的详细信息:

API作用Output.get_any_name()获取模型网络层的名字。Output.get_element_type()获取模型网络层的数据类型,并返回 OvType对象,OvType主要封装了网络的基本数据类型。Output.get_shape()获取模型网络层的形状,并返回 Shape对象,Shape封装了网络层的形状数组。

  在 C# 中通过下方代码,可以直接获取模型的输入、输入层以及模型的friendly name:

string model_name = model.get_friendly_name(); Input input = model.input(); Output output = model.output();

  然后将模型具体信息打印到控制台页面:

Console.WriteLine("Model name: {0}", model_name); Console.WriteLine("/------- [In] -------/"); Console.WriteLine("Input name: {0}", input.get_any_name()); Console.WriteLine("Input type: {0}", input.get_element_type().to_string()); Console.WriteLine("Input shape: {0}", input.get_shape().to_string()); Console.WriteLine("/------- [Out] -------/"); Console.WriteLine("Output name: {0}", output.get_any_name()); Console.WriteLine("Output type: {0}", output.get_element_type().to_string()); Console.WriteLine("Output shape: {0}", output.get_shape().to_string());

  获取模型网络层信息如下:

Model name: torch_jit /------- [In] -------/ Input name: data Input type: float Input shape: [1,3,224,224] /------- [Out] -------/ Output name: prob Output type: float Output shape: [1,1000]

  同样的输出信息,我们使用 C++ API 实现如下:

std::cout 1, 1000} Output tensor size: 1000

  对于输出Tensor,我们只需要读取输出内存上的数据即可,此处我们封装了get_data()方法,可以直接获取输出内存上的数据,在C#中的代码为:

float[] result = output_tensor.get_data(1000);

同样获取推理结果,在C++中的代码为:

const float* output_data = output_tensor.data(); float result[1000]; for (int i = 0; i < 1000; ++i) { result[i] = *output_data; output_data++; }

  在获取结果后,后续的处理需要根据模型的输出类型做相应的处理。

10 释放分配的内存

  由于C#在封装时采用的C API 接口实现的,因此在C#中会产生较多的 非托管内存,若该对象出现循环重复创建,会导致过多的内存未释放导致内存泄漏,因此对于临时创建的对象在使用后要即使销毁,销毁方式也较为简单,只需要调用对象的dispose()方法即可。

output_tensor.dispose(); input_shape.dispose(); infer_request.dispose(); compiled_model.dispose(); input.dispose(); output.dispose(); model.dispose(); core.dispose(); 11 Yolov8分类模型示例

  下面代码展示了Yolov8分类模型使用OpenVINO C# API API方法部署模型的完整代码:

using OpenCvSharp; using OpenCvSharp.Dnn; using OpenVinoSharp; using System.Data; using System.Runtime.InteropServices; namespace test_openvino_csharp_api { internal class Program { static void Main(string[] args) { string model_path = "E:\\GitSpace\\ OpenVINO-CSharp-API \\model\\yolov8\\yolov8s-cls.xml"; Core core = new Core(); // 初始化推理核心 Model model = core.read_model(model_path); // 读取本地模型 CompiledModel compiled_model = core.compile_model(model, "AUTO"); // 便哟模型到指定设备 // 获取模型的输入输出信息 Console.WriteLine("Model name: {0}", model.get_friendly_name()); Input input = compiled_model.input(); Console.WriteLine("/------- [In] -------/"); Console.WriteLine("Input name: {0}", input.get_any_name()); Console.WriteLine("Input type: {0}", input.get_element_type().to_string()); Console.WriteLine("Input shape: {0}", input.get_shape().to_string()); Output output = compiled_model.output(); Console.WriteLine("/------- [Out] -------/"); Console.WriteLine("Output name: {0}", output.get_any_name()); Console.WriteLine("Output type: {0}", output.get_element_type().to_string()); Console.WriteLine("Output shape: {0}", output.get_shape().to_string()); // 创建推理请求 InferRequest infer_request = compiled_model.create_infer_request(); // 获取输入张量 Tensor input_tensor = infer_request.get_input_tensor(); Console.WriteLine("/------- [Input tensor] -------/"); Console.WriteLine("Input tensor type: {0}", input_tensor.get_element_type().to_string()); Console.WriteLine("Input tensor shape: {0}", input_tensor.get_shape().to_string()); Console.WriteLine("Input tensor size: {0}", input_tensor.get_size()); // 读取并处理输入数据 Mat image = Cv2.ImRead(@"E:\GitSpace\ OpenVINO-CSharp-API \dataset\image\demo_7.jpg"); Mat input_mat = new Mat(); input_mat = CvDnn.BlobFromImage(image, 1.0 / 255.0, new Size(224, 224), 0, true, false); // 加载推理数据 Shape input_shape = input_tensor.get_shape(); long channels = input_shape[1]; long height = input_shape[2]; long width = input_shape[3]; float[] input_data = new float[channels * height * width]; Marshal.Copy(input_mat.Ptr(0), input_data, 0, input_data.Length); input_tensor.set_data(input_data); // 模型推理 infer_request.infer(); // 获取输出张量 Tensor output_tensor = infer_request.get_output_tensor(); Console.WriteLine("/------- [Output tensor] -------/"); Console.WriteLine("Output tensor type: {0}", output_tensor.get_element_type().to_string()); Console.WriteLine("Output tensor shape: {0}", output_tensor.get_shape().to_string()); Console.WriteLine("Output tensor size: {0}", output_tensor.get_size()); // 获取输出数据 float[] result = output_tensor.get_data(1000); List new_list = new List { }; for (int i = 0; i < result.Length; i++) { new_list.Add(new float[] { (float)result[i], i }); } new_list.Sort((a, b) => b[0].CompareTo(a[0])); KeyValuePair[] cls = new KeyValuePair[10]; for (int i = 0; i < 10; ++i) { cls[i] = new KeyValuePair((int)new_list[i][1], new_list[i][0]); } Console.WriteLine("\n Classification Top 10 result : \n"); Console.WriteLine("classid probability"); Console.WriteLine("------- -----------"); for (int i = 0; i < 10; ++i) { Console.WriteLine("{0} {1}", cls[i].Key.ToString("0"), cls[i].Value.ToString("0.000000")); } // 销毁非托管内存 output_tensor.dispose(); input_shape.dispose(); infer_request.dispose(); compiled_model.dispose(); input.dispose(); output.dispose(); model.dispose(); core.dispose(); } } } 12 总结

  在本文中我们基于模型推理流程,演示了OpenVINO C# API使用方法,并和OpenVINO C++API进行了对比,展示了OpenVINO C# API与C++API在使用的区别,这也对使用过C++ API的开发者十分友好,上手会十分容易。

  在本文中我们只展示了基础的模型推理流程代码,也对各个API进行了测试,针对其他比较高级的API方法,我们后续会继续进行测试其他API方法,向各位开发者展示其用法。

  总的来说,目前OpenVINO C# API已经完全支持在Windows环境下的安装使用,欢迎各位开发者安装使用,如有相关问题或优化方法,也欢迎大家提出意见与指导。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3