【OpenVINOSharp】 基于C#和OpenVINO2023.0部署Yolov8全系列模型
基于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™ 是不可或缺的部署工具首选。
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实现原理。
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
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_ptr
是CoreStruct
结构体指针,在读取模型后,后续所有操作都是基于该结构体实现的;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包即可使用。
3 获取和转换Yolov8模型
3.1 安装ultralytics
为了更好的管理python库,此处采用conda安装ultralytics环境,使用CMD窗口输入如以下指令,进行环境创建并安装ultralytics依赖项:
conda create -n ultralytics python==3.10
conda activate ultralytics
pip install ultralytics
3.2 导出yolov8模型
Ultralytics支持直接导出预训练模型,并且可以直接导出onnx格式的模型,以Yolov8-det模型为例,直接导出yolov8s.onnx文件,在命令行中输入以下命令
yolo export model=yolov8s.pt format=onnx
通过上述命令可以获得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
上图为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,可以看到模型的输入和输出:
模型的输入节点为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模型的推理结果:
4.2 Yolov8-cls预测结果
用Netron软件打开yolov8s-cls.onnx,可以看到模型的输入和输出:
模型的输入节点为images
,数据类型为float32
,输入为[1,3,224,224]
大小的张量,代表输入为一个224×224
大小的图片,图片加载模型前需要对数据进行归一化处理。
模型的输出节点为output0
,数据类型为float32
,输出为[1,1000]
的张量,其中1000
代表1000个分类情况的置信值,后续直接通过最大值索引和类别标签判断结果。
下图为Yolov8-cls模型的推理结果:
4.3 Yolov8-seg预测结果
用Netron软件打开yolov8s-seg.onnx,可以看到模型的输入和输出:
模型的输入节点与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模型的推理结果:
4.4 Yolov8-pose预测结果
用Netron软件打开yolov8s-pose.onnx,可以看到模型的输入和输出:
图 18 Yolov8-pose模型节点
模型的输入节点与Yolov8一致。模型的输出节点为
output0
,数据类型为
float32
,输出为
[1,56,8400]
的张量,
56
指人体的预测框
(cx,cy,w,h,score)
和人体17个关键点
(x,y,score)
的预测结果,
5+17×3=56
。
下图为Yolov8-pose模型的推理结果:
相关文章:

【OpenVINOSharp】 基于C#和OpenVINO2023.0部署Yolov8全系列模型
基于C#和OpenVINO2023.0部署Yolov8全系列模型 1 项目简介1.1 OpenVINOTM 2 OpenVinoSharp2.1 OpenVINOTM 2023.0安装配置2.2 C 动态链接库2.3 C#构建Core推理类2.4 NuGet安装OpenVinoSharp 3 获取和转换Yolov8模型3.1 安装ultralytics3.2 导出yolov8模型3.3 安装OpenVINOTM Pyt…...
121. 买卖股票的最佳时机
题目描述 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的…...
FDO(Feedback-Driven Optimization) LTO(Link-Time Optimization)
反馈驱动优化(Feedback-Driven Optimization,FDO)和链接时优化(Link-Time Optimization,LTO)是两种重要的编译器优化技术。下面我们详细介绍这两种技术: 反馈驱动优化 (FDO): FDO 是…...

低成本无刷高速吹风机单片机方案
高速吹风机的转速一般是普通吹风机的5倍左右。一般来说,吹风机的电机转速一般为2-3万转/分钟,而高速吹风机的电机转速一般为10万转/分钟左右。高转速增加了高风速。一般来说,吹风机的风力只有12-17米/秒,而高速吹风机的风力可以达…...

使用Python爬取某查查APP端(Appium自动化篇)
1. 写在前面 某查查网站反爬虫风控还是较强的,之后会分别介绍一下PC端协议、APP端自动化、APP端接口协议三种采集方案。这里主要介绍APP端的自动化方式,APP端自动化方式需要登陆账号,协议的话需要签名授权(自动化经测试没有太多限…...
vue3实现组件可拖拽 vuedraggable
npm i -S vuedraggablenext 中文文档,里面有完整代码案例,值得一看 vue.draggable vue3 版本在工作台中的应用场景 - itxst.com...
gradio常用组件
gradio常用组件 1.gradio程序启动2.写入html相关代码3.文本框4. 回车触发事件5.选择按钮框6.下拉框7.点击按钮8.清空按钮9.监听组件10.输出流11.template 1.gradio程序启动 import gradio as gr def tab():pass with gr.Blocks() as ui:gr.Markdown("# <center>&am…...

vcode开发go
配置环境变量 go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct 创建文件夹 mkdir hello cd hello go mod help go mod help 初始化一个项目 go mod init hello 获取第三方包 go get github.com/shopspring/decimal 将依赖包下载到本地 go mod …...
聊城大学823软件工程考研
1.什么是软件工程?它目标和内容是什么? 软件工程就是用科学的知识和技术原理来定义,开发,维护软件的一门学科。 软件工程目标:付出较低开发成本;达到要求的功能;取得较好的性能;开发的软件易于移植&…...

Spring Initailizr--快速入门--SpringBoot的选择
😀前言 本篇博文是关于IDEA使用Spring Initializer快速创建Spring Boot项目的说明,希望能够帮助到您😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可…...

大数据课程I1——Kafka的概述
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Kafka的概念; ⚪ 掌握Kafka的配置与启动; 一、简介 1. 基本概念 Apache kafka 是一个分布式数据流平台。可以从如下几个层面来理解: 1. 我们可以向Kafka发布数据以及从Kafka订阅…...

视图簇 se54 sm34 se54
今天演练了一下 维护视图到视图簇的过程。 se11建表,建表之后 【使用程序】→【表维护生成器】 se54 新建视图簇 对象结构 选中其中一行 字段附属 PS:以上每一行都要设置过去 , 设置完成了 激活 sm34展示...

风丘科技将亮相 EVM ASIA 2023
风丘科技将首次亮相 EVM ASIA 2023 WINDHILL will debut EVM ASIA 2023 ——可持续移动的未来 —The Future of SUSTAINABLE Mobility EVM ASIA 2023是亚太地区电气化的国际性展会,专注于新能源汽车、充电技术及汽车零件制造等。展会致力于促进包括充电站、交通…...

腾讯云服务器S6、SA3、S5、SA2等CVM实例介绍
腾讯云服务器CVM实例标准型S6、SA3、S5、SA2等多款实例降价,最高幅度达40%,标准型S6云服务器是新一代云服务器,SA3和SA2是AMD处理器,标准型S5是次新一代的云服务器,如下图: 腾讯云服务器CVM降价 标准型S6&a…...
使用kickstart和anaconda自动化安装centos系统
使用kickstart和anaconda自动化安装centos系统 使用kickstart和anaconda自动化安装centos系统 anaconda 介绍 kickstart 介绍 实验过程 前提 1.已经安装好至少两台centos系统 2.需要实现自动安装的系统的光盘镜像 3.已安装的系统之间可以通讯(比如处于VMware中的NAT网络的…...

Delphi7通过VB6之COM对象调用PowerBASIC写的DLL功能
Delphi7通过VB6之COM对象调用PowerBASIC写的DLL功能。标题挺长,其实目标很简单,就是在Delphi7中使用PowerBASIC的MKI/CVI, MKS/CVS, MKD/CVD,并顺便加入CRC16检验函数,再进行16进制高低字节调整,方便在VB6、Delphi、La…...

中电金信:ChatGPT一夜爆火,知识图谱何以应战?
随着ChatGPT的爆火出圈 人工智能再次迎来发展小高潮 那么作为此前搜索领域的主流技术 知识图谱前路又将如何呢? 事实上,ChatGPT也并非“万能”,作为黑箱模型,ChatGPT很难验证生成的知识是否准确。并且ChatGPT是通过概率模型执行推…...
单细胞分类和预测任务
对于分类和预测任务,在生物信息学领域有一些常用的方法和工具可以使用。以下是一些常见的方法和工具: 1. 机器学习方法: 包括支持向量机(Support Vector Machine,SVM)、随机森林(Random Forest…...
那些年的Webview开发经验记录
获取网站视频真实链接 直接上工具类 直接调用即可,这个工具类会返回加载的网页中所有的链接,至于对链接怎么处理就是你们自己的事了, 亲测至今我所遇到的所有视频,它都可以捕获到其链接 import android.app.Activity; import an…...
ssh-keygen详解
ssh-keygen命令参数详解 -b BITS指定密钥长度。 -e读取私有或公共 OpenSSH 密钥文件并以 -m 选项指定的格式之一将密钥打印到标准输出。 -C添加注释。 -f FILENAME指定用来保存密钥的文件名。 -i以 -m 选项指定的格式读取未加密的私钥(或公钥)文件&…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...

图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...