【OpenVINO™】在 C# 中使用OpenVINO™ 部署PP-YOLOE实现物体检测

 前言

OpenVINO™ C# API 是一个 OpenVINO™ 的 .Net wrapper,应用最新的 OpenVINO™ 库开发,通过 OpenVINO™ C API 实现 .Net 对 OpenVINO™ Runtime 调用,使用习惯与 OpenVINO™ C++ API 一致。OpenVINO™ C# API 由于是基于 OpenVINO™ 开发,所支持的平台与 OpenVINO™ 完全一致,具体信息可以参考 OpenVINO™。通过使用 OpenVINO™ C# API,可以在 .NET、.NET Framework等框架下使用 C# 语言实现深度学习模型在指定平台推理加速。

OpenVINO™ C# API 项目链接为:

https://github.com/guojin-yan/OpenVINO-CSharp-API.git

项目源码链接为:

https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples.git

1. 简介

   PP-YOLOE是基于PP-YOLOv2的优秀单级无锚模型,超越了各种流行的YOLO模型。PP-YOLOE有一系列型号,命名为s/m/l/x,通过宽度乘数和深度乘数进行配置。PP-YOLOE避免使用特殊的运算符,如可变形卷积或矩阵NMS,以便友好地部署在各种硬件上。 在本文中,我们将使用OpenVINO™ C# API 部署 PP-YOLOE实现物体检测。

2. 项目环境与依赖

  该项目中所需依赖已经支持通过NuGet Package进行安装,在该项目中,需要安装以下NuGet Package:

  • OpenVINO C# API NuGet Package:
OpenVINO.CSharp.API
OpenVINO.runtime.win
OpenVINO.CSharp.API.Extensions
OpenVINO.CSharp.API.Extensions.OpenCvSharp
  • OpenCvSharp NuGet Package:
OpenCvSharp4
OpenCvSharp4.Extensions
OpenCvSharp4.runtime.win

3. 项目输出

  项目使用的是控制台输出,运行后输出如下所示:

<00:00:00> Sending http request to https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Model/ppyoloe_plus_crn_l_80e_coco.tar.
<00:00:02> Http Response Accquired.
<00:00:02> Total download length is 199.68 Mb.
<00:00:02> Download Started.
<00:00:02> File created.
<00:02:03> Downloading: [■■■■■■■■■■] 100% <00:02:03 1.81 Mb/s> 199.68 Mb/199.68 Mb downloaded.
<00:02:03> File Downloaded, saved in E:\GitSpace\OpenVINO-CSharp-API-Samples\model_samples\ppyoloe\ppyoloe_opencvsharp\bin\Release\net6.0\model\ppyoloe_plus_crn_l_80e_coco.tar.
<00:00:00> Sending http request to https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Image/test_det_02.jpg.
<00:00:02> Http Response Accquired.
<00:00:02> Total download length is 0.16 Mb.
<00:00:02> Download Started.
<00:00:02> File created.
<00:00:02> Downloading: [■■■■■■■■■■] 100% <00:00:02 0.06 Mb/s> 0.16 Mb/0.16 Mb downloaded.
<00:00:02> File Downloaded, saved in E:\GitSpace\OpenVINO-CSharp-API-Samples\model_samples\ppyoloe\ppyoloe_opencvsharp\bin\Release\net6.0\model\test_image.jpg.
[ INFO ] Inference device: CPU
[ INFO ] Start RT-DETR model inference.
[ INFO ] 1. Initialize OpenVINO Runtime Core success, time spend: 4.5204ms.
[ INFO ] 2. Read inference model success, time spend: 228.4451ms.
[ INFO ] Inference Model
[ INFO ]   Model name: Model0
[ INFO ]   Input:
[ INFO ]      name: scale_factor
[ INFO ]      type: float
[ INFO ]      shape: Shape : {?,2}
[ INFO ]      name: image
[ INFO ]      type: float
[ INFO ]      shape: Shape : {?,3,640,640}
[ INFO ]   Output:
[ INFO ]      name: multiclass_nms3_0.tmp_0
[ INFO ]      type: float
[ INFO ]      shape: Shape : {?,6}
[ INFO ]      name: multiclass_nms3_0.tmp_2
[ INFO ]      type: int32_t
[ INFO ]      shape: Shape : {?}
[ INFO ] 3. Loading a model to the device success, time spend:501.0716ms.
[ INFO ] 4. Create an infer request success, time spend:0.2663ms.
[ INFO ] 5. Process input images success, time spend:30.1001ms.
[ INFO ] 6. Set up input data success, time spend:2.3631ms.
[ INFO ] 7. Do inference synchronously success, time spend:286.1085ms.
[ INFO ] 8. Get infer result data success, time spend:0.5189ms.
[ INFO ] 9. Process reault  success, time spend:0.4425ms.
[ INFO ] The result save to E:\GitSpace\OpenVINO-CSharp-API-Samples\model_samples\ppyoloe\ppyoloe_opencvsharp\bin\Release\net6.0\model\test_image_result.jpg

  图像预测结果如下图所示:

image-20240505205735624

4. 代码展示

  以下为嘛中所使用的命名空间代码:

using OpenCvSharp.Dnn;
using OpenCvSharp;
using OpenVinoSharp;
using OpenVinoSharp.Extensions;
using OpenVinoSharp.Extensions.utility;
using System.Runtime.InteropServices;
using OpenVinoSharp.preprocess;
using OpenVinoSharp.Extensions.model;
using OpenVinoSharp.Extensions.result;
using OpenVinoSharp.Extensions.process;namespace ppyoloe_opencvsharp
{internal class Program{  ....}
}

  下面为定义的模型预测代码:

  • 一般预测流程:
static void ppyoloe_det(string model_path, string image_path, string device)
{// -------- Step 1. Initialize OpenVINO Runtime Core --------Core core = new Core();// -------- Step 2. Read inference model --------Model model = core.read_model(model_path);OvExtensions.printf_model_info(model);// -------- Step 3. Loading a model to the device --------CompiledModel compiled_model = core.compile_model(model, device);// -------- Step 4. Create an infer request --------InferRequest infer_request = compiled_model.create_infer_request();// -------- Step 5. Process input images --------Mat image = new Mat(image_path); // Read image by opencvsharpfloat[] factor = new float[] { 640.0f / (float)image.Rows, 640.0f / (float)image.Cols };float[] im_shape = new float[] { 640.0f, 640.0f };Mat input_mat = CvDnn.BlobFromImage(image, 1.0 / 255.0, new OpenCvSharp.Size(640, 640), 0, true, false);float[] input_data = new float[640 * 640 * 3];Marshal.Copy(input_mat.Ptr(0), input_data, 0, input_data.Length);// -------- Step 6. Set up input data --------Tensor input_tensor_data = infer_request.get_tensor("image");input_tensor_data.set_shape(new Shape(1, 3, 640, 640));input_tensor_data.set_data<float>(input_data);Tensor input_tensor_factor = infer_request.get_tensor("scale_factor");input_tensor_factor.set_shape(new Shape(1, 2));input_tensor_factor.set_data<float>(factor);// -------- Step 7. Do inference synchronously --------infer_request.infer();// -------- Step 8. Get infer result data --------Tensor output_tensor = infer_request.get_output_tensor(0);int output_length = (int)output_tensor.get_size();float[] output_data = output_tensor.get_data<float>(output_length);// -------- Step 9. Process reault  --------List<Rect> position_boxes = new List<Rect>();List<int> class_ids = new List<int>();List<float> confidences = new List<float>();for (int i = 0; i < 300; ++i){if (output_data[6 * i + 1] > 0.5){class_ids.Add((int)output_data[6 * i]);confidences.Add(output_data[6 * i + 1]);position_boxes.Add(new Rect((int)output_data[6 * i + 2], (int)output_data[6 * i + 3],(int)(output_data[6 * i + 4] - output_data[6 * i + 2]),(int)(output_data[6 * i + 5] - output_data[6 * i + 3])));}}for (int index = 0; index < class_ids.Count; index++){Cv2.Rectangle(image, position_boxes[index], new Scalar(0, 0, 255), 2, LineTypes.Link8);Cv2.Rectangle(image, new OpenCvSharp.Point(position_boxes[index].TopLeft.X, position_boxes[index].TopLeft.Y + 30),new OpenCvSharp.Point(position_boxes[index].BottomRight.X, position_boxes[index].TopLeft.Y), new Scalar(0, 255, 255), -1);Cv2.PutText(image, class_ids[index] + "-" + confidences[index].ToString("0.00"),new OpenCvSharp.Point(position_boxes[index].X, position_boxes[index].Y + 25),HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 0, 0), 2);}string output_path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(image_path)),Path.GetFileNameWithoutExtension(image_path) + "_result.jpg");Cv2.ImWrite(output_path, image);Slog.INFO("The result save to " + output_path);Cv2.ImShow("Result", image);Cv2.WaitKey(0);
}
  • 编译预处理步骤到模型方式推理模型:
static void ppyoloe_det_with_process(string model_path, string image_path, string device)
{// -------- Step 1. Initialize OpenVINO Runtime Core --------Core core = new Core();// -------- Step 2. Read inference model --------Model model = core.read_model(model_path);OvExtensions.printf_model_info(model);PrePostProcessor processor = new PrePostProcessor(model);Tensor input_tensor_pro = new Tensor(new OvType(ElementType.U8), new Shape(1, 640, 640, 3));InputInfo input_info = processor.input("image");InputTensorInfo input_tensor_info = input_info.tensor();input_tensor_info.set_from(input_tensor_pro).set_layout(new Layout("NHWC")).set_color_format(ColorFormat.BGR);PreProcessSteps process_steps = input_info.preprocess();process_steps.convert_color(ColorFormat.RGB).resize(ResizeAlgorithm.RESIZE_LINEAR).convert_element_type(new OvType(ElementType.F32)).scale(255.0f).convert_layout(new Layout("NCHW"));Model new_model = processor.build();// -------- Step 3. Loading a model to the device --------CompiledModel compiled_model = core.compile_model(new_model, device);// -------- Step 4. Create an infer request --------InferRequest infer_request = compiled_model.create_infer_request();// -------- Step 5. Process input images --------Mat image = new Mat(image_path); // Read image by opencvsharpMat input_image = new Mat();Cv2.Resize(image, input_image, new OpenCvSharp.Size(640, 640));float[] factor = new float[] { 640.0f / (float)image.Rows, 640.0f / (float)image.Cols };float[] im_shape = new float[] { 640.0f, 640.0f };// -------- Step 6. Set up input data --------Tensor input_tensor_data = infer_request.get_tensor("image");byte[] input_data = new byte[3 * 640 * 640];Marshal.Copy(input_image.Ptr(0), input_data, 0, input_data.Length);IntPtr destination = input_tensor_data.data();Marshal.Copy(input_data, 0, destination, input_data.Length);Tensor input_tensor_factor = infer_request.get_tensor("scale_factor");input_tensor_factor.set_shape(new Shape(1, 2));input_tensor_factor.set_data<float>(factor);// -------- Step 7. Do inference synchronously --------infer_request.infer();// -------- Step 8. Get infer result data --------Tensor output_tensor = infer_request.get_output_tensor(0);int output_length = (int)output_tensor.get_size();float[] output_data = output_tensor.get_data<float>(output_length);// -------- Step 9. Process reault  --------List<Rect> position_boxes = new List<Rect>();List<int> class_ids = new List<int>();List<float> confidences = new List<float>();for (int i = 0; i < 300; ++i){if (output_data[6 * i + 1] > 0.5){class_ids.Add((int)output_data[6 * i]);confidences.Add(output_data[6 * i + 1]);position_boxes.Add(new Rect((int)output_data[6 * i + 2], (int)output_data[6 * i + 3],(int)(output_data[6 * i + 4] - output_data[6 * i + 2]),(int)(output_data[6 * i + 5] - output_data[6 * i + 3])));}}for (int index = 0; index < class_ids.Count; index++){Cv2.Rectangle(image, position_boxes[index], new Scalar(0, 0, 255), 2, LineTypes.Link8);Cv2.Rectangle(image, new OpenCvSharp.Point(position_boxes[index].TopLeft.X, position_boxes[index].TopLeft.Y + 30),new OpenCvSharp.Point(position_boxes[index].BottomRight.X, position_boxes[index].TopLeft.Y), new Scalar(0, 255, 255), -1);Cv2.PutText(image, class_ids[index] + "-" + confidences[index].ToString("0.00"),new OpenCvSharp.Point(position_boxes[index].X, position_boxes[index].Y + 25),HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 0, 0), 2);}string output_path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(image_path)),Path.GetFileNameWithoutExtension(image_path) + "_result.jpg");Cv2.ImWrite(output_path, image);Slog.INFO("The result save to " + output_path);Cv2.ImShow("Result", image);Cv2.WaitKey(0);
}
  • 使用封装的方法:
static void ppyoloe_det_using_extensions(string model_path, string image_path, string device)
{PPYoloeConfig config = new PPYoloeConfig();config.set_model(model_path);PPYoloeDet det = new PPYoloeDet(config);Mat image = Cv2.ImRead(image_path);DetResult result = det.predict(image);Mat result_im = Visualize.draw_det_result(result, image);Cv2.ImShow("Result", result_im);Cv2.WaitKey(0);
}

  下面为程序运行的主函数代码,该代码会下载转换好的预测模型,并调用预测方法进行预测:

static void Main(string[] args)
{string model_path = "";string image_path = "";string device = "CPU";if (args.Length == 0){if (!Directory.Exists("./model")){Directory.CreateDirectory("./model");}if (!File.Exists("./model/model.pdiparams")&& !File.Exists("./model/model.pdmodel")){if (!File.Exists("./model/ppyoloe_plus_crn_l_80e_coco.tar")){_ = Download.download_file_async("https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Model/ppyoloe_plus_crn_l_80e_coco.tar","./model/ppyoloe_plus_crn_l_80e_coco.tar").Result;}Download.unzip("./model/ppyoloe_plus_crn_l_80e_coco.tar", "./model/");}if (!File.Exists("./model/test_image.jpg")){_ = Download.download_file_async("https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Image/test_det_02.jpg","./model/test_image.jpg").Result;}model_path = "./model/model.pdmodel";image_path = "./model/test_image.jpg";}else if (args.Length >= 2){model_path = args[0];image_path = args[1];device = args[2];}else{Console.WriteLine("Please enter the correct command parameters, for example:");Console.WriteLine("> 1. dotnet run");Console.WriteLine("> 2. dotnet run <model path> <image path> <device name>");}// -------- Get OpenVINO runtime version --------OpenVinoSharp.Version version = Ov.get_openvino_version();Slog.INFO("---- OpenVINO INFO----");Slog.INFO("Description : " + version.description);Slog.INFO("Build number: " + version.buildNumber);Slog.INFO("Predict model files: " + model_path);Slog.INFO("Predict image  files: " + image_path);Slog.INFO("Inference device: " + device);Slog.INFO("Start RT-DETR model inference.");ppyoloe_det(model_path, image_path, device);//ppyoloe_det_with_process(model_path, image_path, device);//ppyoloe_det_using_extensions(model_path, image_path, device);
}

5. 总结

  在该项目中,我们结合之前开发的 OpenVINO™ C# API 项目部署PP-YOLOE模型,实现物体检测。

  • 项目完整代码链接为:
https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/blob/master/model_samples/ppyoloe/ppyoloe_opencvsharp/Program.cs
  • 为了方便EmguCV用户使用需求,同时开发了EmguCV版本,项目链接为:
https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/blob/master/model_samples/ppyoloe/ppyoloe_emgucv/Program.cs

最后如果各位开发者在使用中有任何问题,欢迎大家与我联系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/11903.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DevOps 温故知新

【引】伴随着微服务架构以及云技术的广泛使用&#xff0c;DevOps相应地引起了人们的关注&#xff0c;尤其在互联网企业展开了大量的探索和实践。去年赋闲在家的时候&#xff0c; 有幸精读了三本书&#xff0c;分别是《持续架构实践——敏捷和DevOps时代下的软件架构》&#xff…

Linux安装MySQL(CentOS 7)

安装步骤 下载的MySQL版本为mysql-8.0.26 进入网站MySQL&#xff0c;点击下载 找到mysql社区版 点击Archive&#xff0c;查看所有相关不同版本 点击MySQL Community Server 注意下载MySQL对应的Linux版本&#xff0c;CentOS7 对应 Linux7&#xff0c;如果下成Linux 8 则后面…

解决SpringBoot整合MyBatis和MyBatis-Plus,请求后不打印sql日志

问题发现 在整合springBootmyBatis时&#xff0c;发现请求不打印sql日志&#xff0c;示例代码如下&#xff1a; RestController public class MyController {AutowiredProductMapper productMapper;GetMapping("/test")public void test() {System.out.println(&qu…

全国大学生数学建模竞赛【集训营E题】丨 近5年赛题实现,模拟参赛体验

全国大学生数学建模竞赛E题集训营即将开营 基于Python的近5年E题数学建模基础巩固 近5年E题赛题实现 模拟参赛体验与作品评审

数据库笔记-【视图】

视图 视图通俗是企业想展示给用户看的&#xff0c;数据库存储的数据有很多&#xff0c;但是也有很多是不能对外公开的&#xff0c;做项目的过程就通过视图这个媒介达到这种效果 视图也可以保证数据库表结构字段的隐私安全等 create or replace view stu_v_1 as select id st…

✨✨使用vue3打造一个el-form表单及高德地图的关联组件实例✨

✨1. 实现功能 &#x1f31f;表单内显示省市县以及详细地址 点击省市县输入框时&#xff0c;打开对应地图弹窗&#xff0c;进行位置选择选择位置回显入对应输入框表单内的省市县以及地址输入框同外嵌表单走相同的校验方式触发校验后点击reset实现清除校验与清空数据 &#x1f…

Base64在线编码解码方法

Base64在线编码解码 打开网站 在线工具网-梦幻加菲猫 选择“Base64编码解码” 输入需要编码/解码的内容&#xff0c;点击“编码”/“解码”按钮 编码&#xff1a; 解码&#xff1a; 4. 复制已经编码/解码后的内容。

【云原生】Kubeadm搭建K8S

一、部署Kubernetes 实验环境 服务器主机名IP地址主要组件k8s集群master01 etcd01master01192.168.10.100kube-apiserver kube-controller-manager kube-schedular etcdk8s集群node01 etcd02node01192.168.10.101kubelet kube-proxy docker flannelk8s集群node02 etcd03nod…

数据结构-题目

1.已知一颗完全二叉树的第6曾&#xff08;设根为第1层&#xff09;&#xff0c;有8个结点&#xff0c;则完全二叉树的结点个数&#xff0c;最少和最多分别是多少&#xff1f; 因此最少为39&#xff0c;最多为111 2.假设一棵三叉树的结点数为50&#xff0c;则它的最小高度为&…

【声呐仿真】学习记录3-待续

【声呐仿真】学习记录3-后续 第五阶段-获取数据1.运行赫尔库勒斯沉船的世界&#xff1a;2.键盘操纵rov至合适的位置&#xff0c;调整Image topic&#xff0c;查看输出图像3.RVIZ SONAR 图像查看器插件&#xff08;没有对应的topic&#xff09;4.点云5.录制rosbag 第六阶段-查看…

守护数据安全:精选七款数据加密软件

在数字化日益普及的今天&#xff0c;数据安全成为了企业和个人不可忽视的重要问题。加密软件作为数据安全的第一道防线&#xff0c;扮演着至关重要的角色。本文将为读者精选七款优秀的加密软件&#xff0c;帮助大家更好地守护数据安全。 Ping32数据加密软件 Ping32数据加密软…

Timestamp Unix时间戳在线转换

Timestamp Unix时间戳在线转换 打开网站 在线工具网-梦幻加菲猫 选择“时间戳转换” 在前半部分输入框输入时间/时间戳&#xff0c;点击“转换>>”按钮&#xff0c;即可转换完成 得到转换结果

Python自动化SQL注入和数据库取证工具库之sqlmap使用详解

概要 在网络安全领域,SQL注入仍然是最常见的攻击之一。sqlmap是一个开源的自动化SQL注入和数据库取证工具,它提供了广泛的功能来检测和利用SQL注入漏洞。本文将详细介绍sqlmap的安装、特性、基本与高级功能,并结合实际应用场景,展示其在网络安全测试中的应用。 安装 sqlm…

银行监管报送系统系列介绍(十七):一表通2.0

国家金融监督管理总局于9月发布了【一表通2.0&#xff08;试用版&#xff09;】&#xff08;简称&#xff1a;一表通2.0&#xff09;&#xff0c;在原试点报送范围的基础上扩大了试点报送区域&#xff0c;意味着将陆续扩大试报送机构范围&#xff0c;推进的速度已明显加快。尽早…

HQChart使用教程98-右键菜单2.0使用介绍

HQChart使用教程98-右键菜单2.0使用介绍 内置右键菜单启用右键菜单定制右键菜单内容1. 注册内置右键菜单创建回调事件2. 修改内置菜单的显示内容回调函数格式菜单数据结构示例 3. 注册菜单项点击事件回调 右键事件完整示例HQChart代码地址 内置右键菜单 HQChart h5版本内置提供…

Spring Boot + Mybatis-plus代码生成器 自动生成项目结构

首先创建一个新的springboot项目 项目初始化结构如下&#xff1a; 运行自动生成结构代码后的效果如下&#xff1a; 对比初始化项目结构可以发现结构中多了以下几个部分; controller文件夹存储接口类mapper文佳夹存储数据库映射model文件夹存储数据库模型类Service文件夹存储业…

未授权访问:Docker未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 4、通过crontab反弹宿主机shell 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬总结好…

万字长文带你掌握 IDEA 2024 的30个Debug调试绝技,让你开发与修复 Bug 的效率提升亿倍

万字长文带你掌握 IDEA 2024 的30个Debug调试绝技&#xff0c;让你开发与修复 Bug 的效率提升亿倍 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — …

QCC---Aptx Lossless验证

因为aptx Lossless属于高通骁龙声音的一部分&#xff0c;一般支持高通骁龙声音的设备会支持到&#xff0c;比如说手机&#xff0c;而且还要支持最新的aptx adaptive协议R2.2版本。但是如果手上没有这样的手机的话&#xff0c;有source芯片也可以去做测试验证。在最新的784.1版本…

钽酸锂集成光子芯片:引领光电集成新纪元

在信息技术飞速发展的今天&#xff0c;光电集成技术已成为推动全球集成电路产业持续创新的重要力量。随着全球集成电路产业发展步入“后摩尔时代”&#xff0c;芯片性能提升的难度和成本不断攀升&#xff0c;业界急需寻找新的技术突破口。在这一背景下&#xff0c;中国科学院上…