【OpenVINOSharp】 基于C#和OpenVINO2023.0部署Yolov8全系列模型

news2024/11/24 22:58:19

基于C#和OpenVINO2023.0部署Yolov8全系列模型

  • 1 项目简介
    • 1.1 OpenVINOTM
  • 2 OpenVinoSharp
    • 2.1 OpenVINOTM 2023.0安装配置
    • 2.2 C++ 动态链接库
    • 2.3 C#构建Core推理类
    • 2.4 NuGet安装OpenVinoSharp
  • 3 获取和转换Yolov8模型
    • 3.1 安装ultralytics
    • 3.2 导出yolov8模型
    • 3.3 安装OpenVINOTM Python版
  • 4 OpenVinoSharp部署Yolov8模型
    • 4.1 Yolov8-det预测结果
    • 4.2 Yolov8-cls预测结果
    • 4.3 Yolov8-seg预测结果
    • 4.4 Yolov8-pose预测结果

文章原文收录在英特尔物联网:基于 C# 和 OpenVINO™ 2023.0部署 YOLOv8 全系列模型 | 开发者实战

1 项目简介

1.1 OpenVINOTM

  英特尔发行版 OpenVINO™ 工具套件基于oneAPI 而开发,可以加快高性能计算机视觉和深度学习视觉应用开发速度工具套件,适用于从边缘到云的各种英特尔平台上,帮助用户更快地将更准确的真实世界结果部署到生产系统中。通过简化的开发工作流程, OpenVINO™ 可赋能开发者在现实世界中部署高性能应用程序和算法。
  在推理后端,得益于 OpenVINO™ 工具套件提供的“一次编写,任意部署”的特性,转换后的模型能够在不同的英特尔硬件平台上运行,而无需重新构建,有效简化了构建与迁移过程。可以说,如果开发者希望在英特尔平台上实现最佳的推理性能,并具备多平台适配和兼容性, OpenVINO™ 是不可或缺的部署工具首选。在这里插入图片描述

图 1 OpenVINO™
  《OpenVINO™5周年重头戏!2023.0版本持续升级AI部署和加速性能》(https://mp.weixin.qq.com/s/UWIA1EeX7M2-XhoJ5OfT7w)文章中介绍了OpenVINO™ 最新版本2023.0,引入了一系列旨在增强开发人员体验的新功能、改进和弃用,突出亮点是通过最大限度地减少离线转换、扩大模型支持和推进硬件优化来改善开发者之旅。 ## 1.2 Yolov8   由Ultralytics开发的Ultralytics YOLOv8是一种尖端的,最先进的(SOTA)模型,它建立在以前的YOLO版本成功的基础上,并引入了新功能和改进,以进一步提高性能和灵活性。YOLOv8 设计为快速、准确且易于使用,使其成为各种对象检测、图像分割和图像分类任务的绝佳选择。

在这里插入图片描述

图 2 Yolov8
  YOLOv8是YOLO系列目标检测算法的最新版本,相比于之前的版本,YOLOv8具有更快的推理速度、更高的精度、更加易于训练和调整、更广泛的硬件支持以及原生支持自定义数据集等优势。这些优势使得YOLOv8成为了目前业界最流行和成功的目标检测算法之一。

在这里插入图片描述

图 3 Yolov8-det模型
  Yolov8提供了Yolov8-det、Yolov8-seg、Yolov8-pose和Yolov8-cls预训练模型,每种模型官方还提供了n、s、m、l、s五种模型格式。 1.1.3 项目内容   该项目基于OpenVINOTM 2023.0模型推理库,在C#语言下,调用封装的OpenVINOTM动态链接库,实现Yolov8模型部署推理,实现了在C#平台调用OpenVINOTM部署Yolov8模型。 为了防止复现代码出现问题,列出以下代码开发环境,可以根据自己需求设置,注意OpenVINOTM一定是2022版本,其他依赖项可以根据自己的设置修改。 - 操作系统:Windows 11 - OpenVINOTM:2023.0 - OpenCV:4.5.5 - Visual Studio:2022 - C#框架:.NET 6.0 - OpenCvSharp:OpenCvSharp4   项目所有代码已经在开源代码仓开源,开源地址:
GitHub: https://github.com/guojin-yan/OpenVinoSharp.git
Gitee: https://gitee.com/guojin-yan/OpenVinoSharp.git

2 OpenVinoSharp

  C#是微软公司发布的一种由C和C++衍生出来的面向对象的编程语言、运行于.NET Framework和.NET Core(完全开源,跨平台)之上的高级程序设计语言。但OpenVINOTM未提供C#语言接口,因此无法直接在C#中使用,之前发布的文章《在C#中调用OpenVINO™ 模型》通过动态链接库特性,实现了在C#中调用OpenVINOTM部署深度学习模型,简称:OpenVinoSharp。目前根据日常使用以及OpenVINOTM升级,OpenVinoSharp也进行了相应的改进。
  目前OpenVinoSharp 2.1已经推出,支持OpenVINOTM 2023.0版本,图 4中给出了OpenVinoSharp实现原理。

在这里插入图片描述

图 4 OpenVinoSharp实现原理

2.1 OpenVINOTM 2023.0安装配置

  访问OpenVINOTM (openvino.ai)官网,进入到下载页面,按照图 5 进行选择,最后进行下载,下载后将文件解压到C:\Program Files (x86)\Intel文件夹下,并在Path环境变量下增加线面的环境变量:

C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\bin\intel64\Debug
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\bin\intel64\Release
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\3rdparty\tbb\bin

对于C++项目,增加以下配置:

Release模式下: 
包含目录:
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\include
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\include\ie
库目录
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\lib\intel64\Release
附加依赖项
openvino.lib
Debug模式
包含目录
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\include
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\include\ie
库目录
C:\Program Files (x86)\Intel\openvino_2023.0.0.10926\runtime\lib\intel64\Debug
附加依赖项
openvinod.lib

在这里插入图片描述

图 5 下载选择

2.2 C++ 动态链接库

  C++可以封装dll动态链接库,由于C#是基于C/C++发展来的一门语言,因此C#可以通过动态链接库的形式调用C++代码。下面简单对动态链接库接口进行介绍,具体实现可以参考源码。
(1)推理引擎结构体
  Core是OpenVINOTM 工具套件里的推理核心类,该类下包含多个方法,可用于创建推理中所使用的其他类。在此处,需要在各个方法中传递模型信息,因此选择构建一个推理引擎结构体,用于存放各个变量。

// @brief 推理核心结构体
typedef struct openvino_core {
    ov::Core core; // core对象
    std::shared_ptr<ov::Model> model_ptr; // 读取模型指针
    ov::CompiledModel compiled_model; // 模型加载到设备对象
    ov::InferRequest infer_request; // 推理请求对象
} CoreStruct;

  其中Core是OpenVINO工具套件里的推理机核心;shared_ptr<ov::Model>是读取本地模型的方法,可支持读取Paddlepaddle飞桨模型、ONNX模型以及IR模型;CompiledModel主要是将读取的本地模型映射到计算内核,由所指定的设备编译模型;InferRequest是一个推理请求类,在推理中主要用于对推理过程的操作。CoreStruct结构体指针会贯穿下面的各个接口方法,实现模型信息的传递。
(2)初始化推理模型
  OpenVINO推理引擎结构体是联系各个方法的桥梁,后续所有操作都是在推理引擎结构体中的变量上操作的,为了实现数据在各个方法之间的传输,因此在创建推理引擎结构体时,采用的是创建结构体指针,并将创建的结构体地址作为函数返回值返回。推理初始化接口主要整合了原有推理的初始化Core对象、读取本地推理模型、载入模型到执行硬件和创建推理请求步骤,并将这些步骤所创建的变量放在推理引擎结构体中。
初始化推理模型接口方法为:

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void* STDMETHODCALLTYPE core_init(const wchar_t* w_model_dir, const wchar_t* w_device, const wchar_t* w_cache_dir);

  其中w_model_dir为推理模型本地地址,w_device为模型运行设备名,w_cache_dir是缓存文件路径。
(3)配置输入数据形状
  OpenVINOTM 2022.1之后的版本支持了模型的动态输入并且支持动态设置模型输入形状,因此此处增加了模型形状设置接口:

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void* STDMETHODCALLTYPE set_input_sharp(
	void* core_ptr, const wchar_t* w_node_name, size_t * input_shape, int input_size);

  其中core_ptrCoreStruct结构体指针,在读取模型后,后续所有操作都是基于该结构体实现的;w_node_name是待修改模型节点,input_shape是模型节点,input_size是形状长度。
(4)配置输入数据
  模型读取后就需要项模型中加载推理数据,常见的推理数据为图片数据,图片一般为一个三通道的二维数据,因此无法直接在C#与C++中传递,在该项目中主要是将图片数据转为二进制数据数据进行传递,下面接口实现了图片数据的加载:

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void* STDMETHODCALLTYPE load_image_input_data(void* core_ptr, const wchar_t* w_node_name, uchar * image_data, size_t image_size, int type);

  其中w_node_name为莫模型输入节点名,image_data为图片数据的二进制数组,image_size为图片数据长度,type为数据处理方式,目前已经实现了常规变换、仿射变换、均方差归一化和常规归一化等方式。除了图片输入,一些模型还要求其他数据的输入,因此在该方法中,还增加了常规数据的加载方法:

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void* STDMETHODCALLTYPE load_input_data(void* core_ptr, const wchar_t* w_node_name, float* input_data);

(5)模型推理
  将数据加载到模型后,就可以进行模型的推理,获取模型的推理结果,下面方法中封装了模型推理的方法,可以实现加载的数据进行推理。

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void* STDMETHODCALLTYPE core_infer(void* core_ptr);

(6)读取推理结果
  在进行完模型推理后,就可以获取模型的推理结果,由于不同模型要求的数据格式不同,此处封装了float和int数据的读取方式:

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void STDMETHODCALLTYPE read_infer_result_I32(void* core_ptr, const wchar_t* w_node_name, int* infer_result);
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void STDMETHODCALLTYPE read_infer_result_I64(void* core_ptr, const wchar_t* w_node_name, long long* infer_result);

  其中w_node_name为输出节点名称,infer_result为推理结果数组指针。
(7)删除推理核心结构体指针
推理完成后,我们需要将在内存中创建的推理核心结构地址删除,防止造成内存泄露,影响电脑性能,其接口该方法为:

EXTERN_C __MIDL_DECLSPEC_DLLEXPORT void STDMETHODCALLTYPE core_delet(void* core_ptr);

2.3 C#构建Core推理类

  上一步中我们将模型推理方法封装到了dll动态链接库中,生成了OpenVinoSharpExtern.dll文件,在C#中可以通过[DllImport()]方式通过函数名称与参数对应,将C++中的方法引入当C#中。

private const string dll_extern = " OpenVinoSharpExtern.dll";
[DllImport(dll_extern, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr core_init(string model_dir, string device, string w_cache_dir);

  上述代码通过core_init名称对应和参数返回指定应,将core_init()方法引入到C#中,同样的方式,可以将其他方法引入到C#中。
  上一步我们引入了封装的OpenVINO动态链接库,为了更方便的使用,将其封装到Core类中。在不同方法之间,主要通过推理核心结构体指针在各个方法之间传递,在C#是没有指针这个说法的,不过可以通过IntPtr结构体来接收这个指针,为了防止该指针被篡改,将其封装在类中作为私有成员使用。
  根据模型推理的步骤,构建模型推理类,表 1 中个除了构建的Core模型推理类的API接口,具体代码实现可以参考源码。
在这里插入图片描述

2.4 NuGet安装OpenVinoSharp

  为了方便使用OpenVinoSharp,该项目提供了NuGet包,使用者可以直接通过NuGet包管理器直接安装使用,程序包中包含OpenVINO2023.0版本的库文件,因此使用时无需再安装OpenVINO2023.0,直接安装NuGet包即可使用。
在这里插入图片描述

图 6 NuGet包安装

3 获取和转换Yolov8模型

3.1 安装ultralytics

  为了更好的管理python库,此处采用conda安装ultralytics环境,使用CMD窗口输入如以下指令,进行环境创建并安装ultralytics依赖项:

conda create -n ultralytics python==3.10
conda activate ultralytics
pip install ultralytics

在这里插入图片描述

图 7 ultralytics安装结果

3.2 导出yolov8模型

  Ultralytics支持直接导出预训练模型,并且可以直接导出onnx格式的模型,以Yolov8-det模型为例,直接导出yolov8s.onnx文件,在命令行中输入以下命令

yolo export model=yolov8s.pt format=onnx	

在这里插入图片描述

图 8 yolov8模型导出果

  通过上述命令可以获得yolov8s.onnx模型文件,同样的方式可以将Yolov8-seg、Yolov8-pose和Yolov8-cls的模型文件。

3.3 安装OpenVINOTM Python版

  OpenVINOTM提供了Python语言接口,因此是可以直接安装Python版本使用,且Python版本至此模型的转换和量化,此处采用conda安装OpenVINOTM环境,使用CMD窗口输入如以下指令,进行环境创建并安装OpenVINOTM依赖项:

conda create -n openvino2023_0 python=3.10
conda activate openvino2023_0
python -m pip install --upgrade pip
pip install openvino-dev[ONNX,pytorch,tensorflow2]==2023.0.0

在这里插入图片描述

图 9 OpenVINOTM安装
## 3.4 Yolov8模型量化   OpenVINOTM提供了模型优化的工具,yolov8模型精度默认为f32格式,该工具可以直接使用命令将模型转为f16,以Yolov8-det模型yolov8s.onnx文件为例,在命令行中输入: ``` mo -m yolov8s.onnx --compress_to_fp16 ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/0b19323d0d8f41fa89b9b314abdb8fb2.png#pic_center)
图 10 Yolov8模型量化
  通过上述命令可以获得f16精度的IR格式的模型:yolov8s.xml、yolov8s.bin。同样的方式可以将Yolov8-seg、Yolov8-pose和Yolov8-cls模型的精度转为f16。 ## 3.5 Benchmark_app 测试 Yolov8模型 ``benchmark_app`` 是 OpenVINO™️ 工具套件自带的 AI 模型推理计算性能测试工具,可以指定在不同的计算设备上,在同步或异步模式下,测试出不带前后处理的纯 AI 模型推理计算性能。以Yolov8-det模型为例,在命令行中输入以下命令: ``` benchmark_app -m yolov8s.xml -d CPU ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/bf12b9f1f1c74ca5a711375d2a1e9eaf.png#pic_center)
图 11 Yolov8-det模型推理计算性能

  上图为Yolov8-det模型在CPU:AMD R7 5800异步推理计算性能,最多可以实现21帧推理。

4 OpenVinoSharp部署Yolov8模型

  为了更好的演示Yolov8模型在C#中部署,此处使用WinForm搭建了一个简单的软件进行展示,软件搭建详细代码可以参考源码,下面代码演示了OpenVinoSharp部署Yolov8模型的核心代码:

// 配置图片数据
Mat image = new Mat(image_path); // 读取本地图片
int max_image_length = image.Cols > image.Rows ? image.Cols : image.Rows;
Mat max_image = Mat.Zeros(new OpenCvSharp.Size(max_image_length, max_image_length), MatType.CV_8UC3);
Rect roi = new Rect(0, 0, image.Cols, image.Rows);
image.CopyTo(new Mat(max_image, roi));
float[] factors = new float[2]; // 图片缩放比例
factors[0] = factors[1] = (float)(max_image_length / 640.0);
// 读取模型,初始化推理核心
Core core = new Core(model_path, "CPU");
// 将图片转为二进制数据
byte[] image_data = max_image.ImEncode(".bmp");
//存储byte的长度
ulong image_size = Convert.ToUInt64(image_data.Length);
// 加载推理图片数据
core.load_input_data("images", image_data, image_size, 1);
// 模型推理
core.infer();
// 读取推理结果
float[] result_array = core.read_infer_result<float>("output0", 8400 * 84);
// 清理内存占用
core.delet();
// 创建结果处理类
DetectionResult result_pro = new DetectionResult(classer_path, factors);
// 处理推理结果
result_image = result_pro.draw_result(result_pro.process_result(result_array), image.Clone());

4.1 Yolov8-det预测结果

  用Netron软件打开yolov8s.onnx,可以看到模型的输入和输出:
在这里插入图片描述

图 12 Yolov8-det模型节点

  模型的输入节点为images,数据类型为float32,输入为[1,3,640,640]大小的张量,代表输入为一个640×640大小的图片,图片加载模型前需要对数据进行归一化处理。
  模型的输出节点为output0,数据类型为float32,输出为[1,84,8400]的张量,其中“84”的定义为:cx,cy,h,w和80种类别的分数。8400是指 YOLOv8 的3个检测头在图像尺寸为640时,有640/8=80, 640/16=40, 640/32=20, 80x80+40x40+20x20=8400个输出单元格。
下图为Yolov8-det模型的推理结果:
在这里插入图片描述
在这里插入图片描述

图 13 Yolov8-det模型预测结果

4.2 Yolov8-cls预测结果

  用Netron软件打开yolov8s-cls.onnx,可以看到模型的输入和输出:
在这里插入图片描述

图 14 Yolov8-cls模型节点

  模型的输入节点为images,数据类型为float32,输入为[1,3,224,224]大小的张量,代表输入为一个224×224大小的图片,图片加载模型前需要对数据进行归一化处理。
  模型的输出节点为output0,数据类型为float32,输出为[1,1000]的张量,其中1000代表1000个分类情况的置信值,后续直接通过最大值索引和类别标签判断结果。
下图为Yolov8-cls模型的推理结果:
在这里插入图片描述
在这里插入图片描述

图 15 Yolov8-cls模型预测结果

4.3 Yolov8-seg预测结果

  用Netron软件打开yolov8s-seg.onnx,可以看到模型的输入和输出:
在这里插入图片描述

图 16 Yolov8-seg模型节点

  模型的输入节点与Yolov8一致。模型的输出节点有两个,输出节点1为output0,数据类型为float32,输出为[1,116,8400]的张量,其中 116 的前 84 个字段跟 YOLOv8目标检测模型输出定义完全一致,后 32 个字段用于计算mask。输出节点2为output1,数据类型为float32,输出为[1,32,160,160]的张量, output0 后 32 个字段与 output1 的数据做矩阵乘法后得到的结果,即为对应目标的mask。
  下图为Yolov8-seg模型的推理结果:

在这里插入图片描述在这里插入图片描述

图 17 Yolov8-seg模型预测结果

4.4 Yolov8-pose预测结果

  用Netron软件打开yolov8s-pose.onnx,可以看到模型的输入和输出:
在这里插入图片描述
图 18 Yolov8-pose模型节点

图 19 Yolov8-pose模型预测结果

  模型的输入节点与Yolov8一致。模型的输出节点为 output0,数据类型为 float32,输出为 [1,56,8400]的张量, 56指人体的预测框 (cx,cy,w,h,score)和人体17个关键点 (x,y,score)的预测结果, 5+17×3=56
  下图为Yolov8-pose模型的推理结果:

在这里插入图片描述
在这里插入图片描述

图 19 Yolov8-pose模型预测结果
# 5 总结   C#作为一门比较高级的编程语言,在Windows平台上有很好的支持,可以很容易实现桌面软件的开发,并且拥有自动的垃圾回收机制,可以实现自动内存管理,极大的见挂了编码过程,因此在当前工业领域有很广泛的应用。而OpenVINO™凭借着齐强的推理性能和硬件支持,在模型部署领域大放异彩。   因此实现在C#平台使用OpenVINO™部署深度学习模型,打破了OpenVINO™与C#之间的壁垒,会使得模型部署在工业领域应用变得更加容易。

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

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

相关文章

杭电多校 Rikka with Square Numbers 费马平方和定理

&#x1f468;‍&#x1f3eb; Rikka with Square Numbers &#x1f9c0; 参考题解 &#x1f37b; AC code import java.util.Scanner;public class Main {static boolean isSqu(int x){int t (int) Math.sqrt(x);return t * t x;}public static void main(String[] args…

Vue2:组件基础(上)

Vue2&#xff1a;组件基础&#xff08;上&#xff09; Date: July 29, 2023 Sum: 生命周期、Vue-cli、组件的使用、小黑记账清单、小兔鲜首页 生命周期&#xff1a; 生命周期介绍 思考&#xff1a; 什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#x…

Aviator这么丝滑,怎么实现的呢?

大家好&#xff0c;我是老三&#xff0c;在上期 里我们介绍了轻量级规则引擎AviatorScript的基本用法和一些使用案例&#xff0c;这期我们来研究一下&#xff0c;这么丝滑的规则脚本是怎么实现的。 概览 我们先来回顾一个简单的例子&#xff1a; Testpublic void test(){//表…

一道RSA题(忘了名字)-云上贵州-网络安全攻防竞赛个人赛

题目&#xff1a; 很遗憾&#xff0c;这道题当时没做出来。 话不多说&#xff0c;直接开始&#xff0c;题目只给了一个式子&#xff0c;这里就命名为hint&#xff1a; 最开始我的想法是化为模q的形式&#xff0c;也就是&#xff1a; 然后就变成了&#xff1a; 接着就一直卡在这…

国产数据库排行

目录 一、理论 1.国产数据库排行 2.数据 一、理论 1.国产数据库排行 &#xff08;1&#xff09;墨天轮榜单 墨天轮国产数据库流行度排行于2019年6月推出&#xff0c;通过近50个维度的数据来考察近300个国产数据库的流行度排行&#xff0c;每月1日更新排行数据&#xff0c…

js 使用 Object.defineProperty() 对属性进行限制 06

小夏小夏&#xff0c;可爱到爆炸 &#x1f923; &#x1f495;&#x1f495;&#x1f495; 文章目录 一、对属性操作的控制二、属性描述符三、数据属性描述符四、存取属性描述符五、vue2 响应式原理六、defineProerties 同时定义多个属性七、对象方法补充 一、对属性操作的控制…

勘探开发人工智能技术:机器学习(5)

0 提纲 6.1 矩阵分解 6.2 全连接 BP 神经网络 6.3 卷积神经网络 6.4 LSTM 6.5 Transformer 6.6 U-Net 1 矩阵分解 把稀疏矩阵分解成两个小矩阵的乘积, 恢复后的矩阵用于预测. 1.1 基本概念 矩阵分解是使用数学应对机器学习问题的一类典型而巧妙的方法. 矩阵分解是把将一个…

数字万用表测量基础知识--DMM的显示位数

概览 DMM&#xff08;即数字万用表&#xff09;是一种电气测试和测量仪器&#xff0c;可测量直流和交流信号的电压、电流和电阻。本文介绍如何正确使用和理解数字万用表(DMM)。 DMM的显示位数 数字万用表(DMM)可用于进行各种测量。在选择DMM或理解所使用的DMM时&#xff0c;首…

jupyter切换conda虚拟环境

环境安装 conda install nb_conda 进入你想使用的虚拟环境&#xff1a; conda activate your_env_name 在你想使用的conda虚拟环境中&#xff1a; conda install -y jupyter 在虚拟环境中安装jupyter&#xff1a; conda install -y jupyter 重启jupyter 此时我们已经把该安装…

【学习FreeRTOS】第3章——FreeRTOS移植及配置文件

1.FreeRTOS源码简介 【一级目录&#xff1a;/】以下FreeRTOS的源码&#xff0c;其中&#xff0c;FreeRTOS文件夹最为重要&#xff0c;代笔FreeRTOS内核 【二级目录&#xff1a;/FreeRTOS】以下为FreeRTOS文件夹的内容&#xff0c;比较重要的有Demo文件夹和Source文件夹 【三级…

【使用Hilbert变换在噪声信号中进行自动活动检测】基于Hilbert变换和平滑技术进行自动信号分割和活动检测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

linux文件I/O之 close()、lseek()、read()、write() 函数用法

1. close() 函数 头文件和函数声明 #include <unistd.h> int close(int fd); 函数功能 关闭一个文件描述符 返回值 成功时返回 0。失败则返回 -1&#xff0c;并设置 errno 为相应的错误标志。 参数 fd&#xff1a;文件描述符 说明 像其它所有系统调用一样&…

UNet Model

论文地址 第一阶段 conv2d(33) first conv&#xff1a;5725721 → 57057064 second conv&#xff1a;57057064 → 56856864 代码 # first 33 convolutional layer self.first nn.Conv2d(in_channels, out_channels, kernel_size3, padding1) self.act1 nn.ReLU() # Seco…

渠道订货管理:品牌商建立渠道连接的纽带

当品牌商&#xff08;厂商&#xff09;渠道拓展到一定规模&#xff0c;处理不同渠道交易数据&#xff0c;面对信息流、物流、资金流链路&#xff0c;提升厂商端、经销商端、终端门店的订货体验就会变得尤为重要&#xff0c;特别是一些实力级厂商&#xff0c;渠道下沉能够掌握终…

同步代码块使用错误示范 | 用了synchronized还是出现“超取”问题

记录一下错误&#xff0c;吸取经验&#x1f914;&#x1f60b; 出问题的代码 public class Test {public static void main(String[] args) {new Thread(new Account()).start(); //&#xff01;&#xff01;new Thread(new Account()).start(); //&#xff01;&#xff01;}…

Lecoode有序数组的平方977

题目建议&#xff1a; 本题关键在于理解双指针思想 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 文章讲解&#xff1a;代码随想录 视频讲解&#xff1a; 双指针法经典题目 | LeetCode&#xff1a;977.有序数组的平方_哔哩…

​朋友圈评论截图生成,制作朋友圈网页​

朋友圈头像&#xff0c;上传自己的朋友圈头像&#xff1b;不填默认随机 网名&#xff0c;填写微信昵称&#xff1b; 内容&#xff0c;需要发布的微信正文内容&#xff1b; 截图类型&#xff0c;支持纯文字、图片&#xff08;单张、九宫格&#xff09;、分享网页/公众号文章共…

Webstorm + Egg.js 进行断点调试

Webstorm Egg.js 进行断点调试 1、在工具栏找到编辑配置&#xff0c;创建已运行Node.js 应用程序的调试配置 2、debug调试配置 3、调试 4、查看断点是否起效

【数据结构与算法】十大经典排序算法-希尔排序

&#x1f31f;个人博客&#xff1a;www.hellocode.top &#x1f3f0;Java知识导航&#xff1a;Java-Navigate &#x1f525;CSDN&#xff1a;HelloCode. &#x1f31e;知乎&#xff1a;HelloCode &#x1f334;掘金&#xff1a;HelloCode ⚡如有问题&#xff0c;欢迎指正&#…

易服客工作室:7个优质WordPress LMS线上教育系统插件比较(优点和缺点)

您是否正在为您的 WordPress 网站寻找最好的 LMS 插件&#xff1f;在线学习管理系统 (LMS) 插件允许您使用 WordPress 创建和运行类似 Udemy 的在线课程。 一个完美的 WordPress LMS 插件包括管理在线课程内容、处理订阅、运行和评分测验、接受付款等功能。 在本文中&#xf…