Linux中怎么用cat命令创建文件并写入数据
262
2024-01-26
作者:颜国进 英特尔边缘计算创新大使技术指导:武卓,李翊玮 OpenVINO工具套件可以加快深度学习视觉应用开发速度,帮助用户在从边缘到云的各种英特尔平台上,更加方便快捷的将 AI 模型部署到生产系统中。
C# 是由 C 和 C++ 衍生出来的一种安全的、稳定的、简单的、优雅的面向对象编程语言,它综合了 VB 简单的可视化操作和 C++ 的高运行效率,成为支持成为.NET 开发的首选语言作为人工智能开发人员,如果你希望在 C# 端使用 OpenVINO ,OpenVINOSharp 将是你的首选,并且制作了 NuGet 程序包,实现在 C# 端了。
一站式安装与使用 OpenVINO OpenVINOSharp 在制作时参考了 OpenVINO C++ API,因此对于之前使用过 OpenVINO 的人十分友好下面表格向我们展示了 C# 与 C++ API 的对应关系。
在本文中,将会根据模型部署的一般步骤,演示从模型加载到推理的方法函数使用方式,并于 C++ API 做对比1.1安装 OpenVINOSharp OpenVINOSharp 支持 NuGet 程序包安装方式,这与在 C++ 中安装过程相比,较为简单,并且程序包中包含了 OpenVINO 2023.0 发行版本,可以通过 NuGet 安装后直接使用。
如果使用 Visual Studio 编译该项目,则可以通过 NuGet 程序包管理功能直接安装即可:
如果通过 dotnet 命令方式安装,通过下面语句进行安装即可:dotnet add package OpenVinoSharp.win 向右滑动查看完整代码1.2导入程序集 OpenVINOSharp 程序集全部在命名空间 OpenVinoSharp 下,因此若要使用 OpenVINOSharp ,需要先引入命名空间:
using OpenVinoSharp1.3初始化 OpenVINO 运行时内核 Core 类代表一个 OpenVINO 运行时核心实体,后续的读取模型、加载模型等方法都需要通过 Core 类进行创建,在封装 C# API 时,为了与 C++ API 对应,也对 Core 类进行了封装,并封装了与 C++ API 中对应的方法。
在 C# 中的初始化方式:Core core = new Core() 在 C++ 中的初始化方式:ov::Core core;1.4加载并获取模型信息1.4.1 加载模型 OpenVINO 2022.1版本更新之后,加载,下面是所使用的 API 方法:
API作用 Core.read_model () 将模型从硬盘载入内存,并返回Model对象 在 C# 中加载模型的方式:Model model = core.read_model(model_path);。
向右滑动查看完整代码 在 C++ 中的初始化方式:std::shared_ptrmodel = core.read_model(model_path); 向右滑动查看完整代码1.4.1 获取模型信息
通过 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 << "Model name: "
input = model->input(); std::cout << "/------- [In] -------/" << std::endl; std::cout << "Input name: " << input.get_any_name() << std::endl; std::cout << "Input type: " << input.get_element_type().c_type_string() << std::endl; std::cout << "Input shape: " << input.get_shape().to_string() << std::endl; ov::Output
output = model->output(); std::cout << "/------- [Out] -------/" << std::endl; std::cout << "Output name: " << output.get_any_name() << std::endl; std::cout << "Output type: " << output.get_element_type().c_type_string() << std::endl; std::cout << "Output shape: " << output.get_shape().to_string() << std::endl;
向右滑动查看完整代码1.5编译模型并创建推理请求 在读取本地模型后,调用模型编译方法将模型编译为可以在目标设备上执行的 compile_model 对象,并通过该对象创建用于推断已编译模型的推断请求对象。
下面是所使用的 API 方法:API作用 Core.compile_model() 将模型编译为可以在目标设备上执行的 compile_model 对象 CompiledModel.create_infer_request()。
创建用于推断已编译模型的推断请求对象,创建的请求已经分配了输入和输出张量 在 C# 中编译模型并创建推理请求的方式:CompiledModel compiled_model = core.compile_model(model, "AUTO"); InferRequest infer_request = compiled_model.create_infer_request();。
向右滑动查看完整代码 使用 C++ API 中编译模型并创建推理请求的方式:CompiledModel compiled_model = core.compile_model(model, "AUTO"); InferRequest infer_request = compiled_model.create_infer_request();
向右滑动查看完整代码1.6张量Tensor1.6.1 张量的获取与设置 在创建推理请求后,系统会自动创建和分配输入和输出的张量,张量可以通过 InferRequest 对象获得,并且可以自定义张量并加载到模型指定节点;可以根据张量的输入输出序号、名称以及模型节点 Node 对象获取和设置,主要 C# API 如下:
API作用 InferRequest.set_tensor() 设置要推断的输入/输出张量 InferRequest.set_input_tensor() 设置要推断的输入张量。
InferRequest.set_output_tensor() 设置要推断的输出张量 InferRequest.get_tensor() 获取用于推理的输入/输出张量。
InferRequest.get_input_tensor() 获取用于推理的输入张量 InferRequest.get_output_tensor() 设置要推理的输出张量。
1.6.2 张量的信息获取与设置 张量中主要包含的信息有张量的形状 (Shape)、张量的数据格式 (OvType-> element.Type) 以及张量中的内存数据可以通过以下 API 方法操作张量的。
参数:API作用 Tensor.set_shape () 给张量设置一个新的形状 Tensor.get_shape() 获取张量的形状 Tensor.get_element_type()。
获取张量的数据类型 Tensor.get_size() 获取张量的数据长度 Tensor.get_byte_size() 获取张量的字节大小 Tensor.data()。
获取张量的内存地址 Tensor.set_data() 将指定类型的数据加载到张量内存下 Tensor.get_data() 从张量中读取指定类型的数据 以上方法是对张量的一些基础操作,除了 set_data、get_data 是 OpenVINOSharp 独有的,其他
接口都与 C++API 一致1.7加载推理数据1.7.1 获取输入张量 对于单输入的模型可以直接通过 get_input_tensor() 方法获得,并调用 Tensor 的相关方法获取 Tensor 的相关信息,C# 代码如下所示:。
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());
向右滑动查看完整代码 获取输出结果为:/------- [Input tensor] -------/ Input tensor type: f32 Input tensor shape: Shape : {1, 3, 224, 224} Input tensor size: 150528
向右滑动查看完整代码 对于上述的同样输出内容,我们也可以通过 C++ API 实现,C++ 代码如下:ov::Tensor input_tensor = infer_request.get_input_tensor(); std::cout << "/------- [Input tensor] -------/" << std::endl; std::cout << "Input tensor type: " << input_tensor.get_element_type().c_type_string() << std::endl; std::cout << "Input tensor shape: " << input_tensor.get_shape().to_string() << std::endl; std::cout << "Input tensor size: " << input_tensor.get_size() << std::endl;
向右滑动查看完整代码1.7.2 添加推理数据 这一步主要是将处理好的图片数据加载到 Tensor 数据内存中,OpenVINO 的 API 中提供了访问内存地址的接口,可以获取数据内存首地址,不过为了更好的加载推理数据,我们此处封装了 set_data
() 方法,可以实现将处理后的图片数据加载到数据内存上在 C# 中的代码为:Mat input_mat = new Mat(); 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]; Ma。
rshal.Copy(input_mat.Ptr(0), input_data, 0, input_data.Length); input_tensor.set_data(input_data); 向右滑动查看完整代码
下面是在 C++ 中实现上述功能的代码:cv::Mat input_mat; float* input_data = input_tensor.data(); ov::Shape input_shape = input_tens
or.get_shape(); size_t channels = input_shape[1]; size_t height = input_shape[2]; size_t width = input_shape[3]; for (size_t c = 0; c < channels; ++c) { for (size_t h = 0; h < height; ++h) { for (size_t w = 0; w < width; ++w) { input_data[c * height * width + h * width + w] = input_mat.at
>(h, w)[c]; } } } 向右滑动查看完整代码1.8模型推理 在加载完推理数据后,就可以调用模型推理的 API 方法推理当前数据,主要使用到的 API 方法为:API作用 InferRequest.infer()
在同步模式下推断指定的输入 调用该方法也较为简单,只需要调用该 API 接口即可,在 C# 中的代码为:infer_request.infer(); 向右滑动查看完整代码 C++ 中的代码与 C++ 中一致。
1.9获取推理结果 对于单输出的模型可以直接通过 get_output_tensor() 方法获得,并调用 Tensor 的相关方法获取 Tensor 的相关信息,C# 代码如下所示: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());
向右滑动查看完整代码 获取输出 output_tensor 信息为:/------- [Output tensor] -------/ Output tensor type: f32 Output tensor shape: Shape : {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++; }
向右滑动查看完整代码 在获取结果后,后续的处理需要根据模型的输出类型做相应的处理1.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();
1.11Yolov8 分类模型示例 下面代码展示了 Yolov8 分类模型使用 OpenVINOSharp API 方法部署模型的完整代码:using OpenCvSharp; using OpenCvSharp.Dnn; using OpenVinoSharp; using System.Data; using System.Run
time.InteropServices; namespace test_openvinosharp_api { internal class Program { static void Main(string[] args) { string model_path = "E:\GitSpace\OpenVinoSharp\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:GitSpaceOpenVinoSharpdatasetimagedemo_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 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(" Classification Top 10 result : "); 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(); } } }
向右滑动查看完整代码1.12总结 在本文中我们基于模型推理流程,演示了 OpenVINOSharp API 使用方法,并和 OpenVINO C++API 进行了对比,展示了 OpenVINOSharp API 与 C++API 在使用的区别,这也对使用过 C++ API 的
开发者十分友好,上手会十分容易 在本文中我们只展示了基础的模型推理流程代码,也对各个 API 进行了测试,针对其他比较高级的 API 方法,我们后续会继续进行测试其他 API 方法,向各位开发者展示其用法。
总的来说,目前 OpenVINOSharp 已经完全支持在 Windows 环境下的安装使用,欢迎各位开发者安装使用,如有相关问题或优化方法,也欢迎大家提出意见与指导。 审核编辑:汤梓红
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~