【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV5模型部署
【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV5模型部署
提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论
文章目录
- 【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV5模型部署
- 前言
- Windows平台搭建依赖环境
- 模型转换--pytorch转onnx
- ONNXRuntime推理代码
- 完整推理代码
- 总结
前言
本期将讲解深度学习目标检查网络YOLOV5模型的部署,对于该算法的基础知识,可以参考其他博主博文。
读者可以通过学习【OnnxRuntime部署】系列学习文章目录的C++篇* 的内容,系统的学习OnnxRuntime部署不同任务的onnx模型。
Windows平台搭建依赖环境
在【入门基础篇】中详细的介绍了onnxruntime环境的搭建以及ONNXRuntime推理核心流程代码,不再重复赘述。
模型转换–pytorch转onnx
本博文将通过Ultralytics–YOLOv5算法的口罩检测项目【参考博文:Windows11下YOLOV5口罩目标检测】,简要介绍YOLOV5模型部署。
在博文Windows11下YOLOV5口罩目标检测项目中已经通过以下命令导出了onnx模型:
python export.py --weights runs/train/exp/weights/best.pt --include onnx
【yolov5s-mask.onnx百度云链接,提取码:15v2 】直接下载使用即可。
ONNXRuntime推理代码
利用可视化工具查看onnx模型结构: 通过可视化Netron工具【在线工具】,展示模型的层次结构、参数细节等。
将onnx模型上传到在线Netron可视化工具:
简单说明下输出代表的含义::1代表batchsize;25200代表检测框的个数;7代表框的详细信息:即框中心点xy+框宽高hw+框置信度conf+框分类个数(这里是2)。
完整推理代码
需要配置mask_classes.txt文件存储人脸的分类标签,并将其放置到工程目录下(推荐)。
without-mask
mask
这里需要将yolov5s-mask.onnx放置到工程目录下(推荐),并且将以下推理代码拷贝到新建的cpp文件中,并执行查看结果。
#include "onnxruntime_cxx_api.h"
#include "cpu_provider_factory.h"
#include <opencv2/opencv.hpp>
#include <fstream>// 加载标签文件获得分类标签
std::string labels_txt_file = "./mask_classes.txt";
std::vector<std::string> readClassNames();
std::vector<std::string> readClassNames()
{std::vector<std::string> classNames;std::ifstream fp(labels_txt_file);if (!fp.is_open()){printf("could not open file...\n");exit(-1);}std::string name;while (!fp.eof()){std::getline(fp, name);if (name.length())classNames.push_back(name);}fp.close();return classNames;
}int main(int argc, char** argv) {// 预测的目标标签数std::vector<std::string> labels = readClassNames();// 测试图片cv::Mat frame = cv::imread("./mask.jpg");cv::imshow("输入图", frame);// ******************* 1.初始化ONNXRuntime环境 *******************Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "YOLOV5-onnx");// ***************************************************************// ******************* 2.设置会话选项 *******************// 创建会话Ort::SessionOptions session_options;// 优化器级别:基本的图优化级别session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);// 线程数:4session_options.SetIntraOpNumThreads(4);// 设备使用优先使用GPU而是才是CPUstd::cout << "onnxruntime inference try to use GPU Device" << std::endl;OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);OrtSessionOptionsAppendExecutionProvider_CPU(session_options, 1);// ******************************************************// ******************* 3.加载模型并创建会话 *******************// onnx训练模型文件std::string onnxpath = "./yolov5s-mask.onnx";std::wstring modelPath = std::wstring(onnxpath.begin(), onnxpath.end());Ort::Session session_(env, modelPath.c_str(), session_options);// ************************************************************// ******************* 4.获取模型输入输出信息 *******************int input_nodes_num = session_.GetInputCount(); // 输入节点输int output_nodes_num = session_.GetOutputCount(); // 输出节点数std::vector<std::string> input_node_names; // 输入节点名称std::vector<std::string> output_node_names; // 输出节点名称Ort::AllocatorWithDefaultOptions allocator; // 创建默认配置的分配器实例,用来分配和释放内存 // 输入图像尺寸int input_h = 0;int input_w = 0;// 获取模型输入信息for (int i = 0; i < input_nodes_num; i++) {// 获得输入节点的名称并存储auto input_name = session_.GetInputNameAllocated(i, allocator);input_node_names.push_back(input_name.get());// 显示输入图像的形状auto inputShapeInfo = session_.GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();int ch = inputShapeInfo[1];input_h = inputShapeInfo[2];input_w = inputShapeInfo[3];std::cout << "input format: " << ch << "x" << input_h << "x" << input_w << std::endl;}// 获取模型输出信息int nums;int nbs;int ncs;for (int i = 0; i < output_nodes_num; i++) {// 获得输出节点的名称并存储auto output_name = session_.GetOutputNameAllocated(i, allocator);output_node_names.push_back(output_name.get());// 显示输出结果的形状auto outShapeInfo = session_.GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();nums = outShapeInfo[0];nbs = outShapeInfo[1];ncs = outShapeInfo[2];std::cout << "output format: " << nums << "x" << nbs << "x" << ncs << std::endl;}// **************************************************************// ******************* 5.输入数据预处理 *******************// 原始图像的宽高int w = frame.cols;int h = frame.rows;// 原始图像与输入图像之间的缩放系数float x_factor = 0.0;float y_factor = 0.0;// 获得原始图像中宽高中的长边,最为变换正方形的边长int _max = std::max(h, w); // 将原始的矩形图像放大变换成正方形图像,默认补零cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3);cv::Rect roi(0, 0, w, h);frame.copyTo(image(roi));// 计算宽高的缩放系数,模型的输入恒定为640×640,必须强制转换成浮点数x_factor = image.cols / static_cast<float>(640); y_factor = image.rows / static_cast<float>(640);// 完成归一化:1.0 / 255.0;缩放:cv::Size(input_w, input_h);格式转换(BGR转RGB):truecv::Mat blob = cv::dnn::blobFromImage(image, 1.0 / 255.0, cv::Size(input_w, input_h), cv::Scalar(0, 0, 0), true, false);std::cout << blob.size[0] << "x" << blob.size[1] << "x" << blob.size[2] << "x" << blob.size[3] << std::endl;// ********************************************************// ******************* 6.推理准备 *******************// 占用内存大小,后续计算是总像素*数据类型大小size_t tpixels = 3 * input_h * input_w;std::array<int64_t, 4> input_shape_info{ 1, 3, input_h, input_w };// 准备数据输入auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, blob.ptr<float>(), tpixels, input_shape_info.data(), input_shape_info.size());// 模型输入输出所需数据(名称及其数量),模型只认这种类型的数组const std::array<const char*, 1> inputNames = { input_node_names[0].c_str() };const std::array<const char*, 1> outNames = { output_node_names[0].c_str()};// **************************************************// ******************* 7.执行推理 *******************std::vector<Ort::Value> ort_outputs;try {ort_outputs = session_.Run(Ort::RunOptions{ nullptr }, inputNames.data(), &input_tensor_, 1, outNames.data(), outNames.size());}catch (std::exception e) {std::cout << e.what() << std::endl;}// **************************************************// ******************* 8.后处理推理结果 *******************// 1x25200x6 获取(第一个)输出数据并包装成一个cv::Mat对象,为了方便后处理const float* pdata = ort_outputs[0].GetTensorMutableData<float>();cv::Mat det_output(nbs, ncs, CV_32F, (float*)pdata);std::vector<cv::Rect> boxes; // 目标框的坐标位置std::vector<float> confidences; // 目标框的置信度std::vector<int> classIds; // 目标框的类别得分// 剔除置信度较低的目标框,不作处理for (int i = 0; i < det_output.rows; i++) {float confidence = det_output.at<float>(i, 4);if (confidence < 0.45) {continue;}// 获得当前目标框的类别得分cv::Mat classes_scores = det_output.row(i).colRange(5, ncs);// 这里与图像分类的方式一致cv::Point classIdPoint; // 用于存储分类中的得分最大值索引(坐标)double score; // 用于存储分类中的得分最大值minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);// 处理分类得分较高的目标框if (score > 0.25){ // 计算在原始图像上,目标框的左上角坐标和宽高// 在输入图像上目标框的中心点坐标和宽高float cx = det_output.at<float>(i, 0); float cy = det_output.at<float>(i, 1);float ow = det_output.at<float>(i, 2);float oh = det_output.at<float>(i, 3);//原始图像上目标框的左上角坐标int x = static_cast<int>((cx - 0.5 * ow) * x_factor); int y = static_cast<int>((cy - 0.5 * oh) * y_factor);//原始图像上目标框的宽高int width = static_cast<int>(ow * x_factor);int height = static_cast<int>(oh * y_factor);// 记录目标框信息cv::Rect box;box.x = x;box.y = y;box.width = width;box.height = height;boxes.push_back(box);classIds.push_back(classIdPoint.x);confidences.push_back(score);}}// NMS:非极大值抑制(Non-Maximum Suppression),去除同一个物体的重复多余的目标框std::vector<int> indexes; // 剔除多余目标框后,保留的目标框的序号cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes);// 遍历筛选出的目标框for (size_t i = 0; i < indexes.size(); i++) {int idx = indexes[i]; // 获取当前目标框序号int cid = classIds[idx]; // 获取目标框分类得分// 输入/输出图像:frame;目标位置信息:boxes[idx];目标框颜色: cv::Scalar(0, 0, 255);// 边框线的厚度:4;线条类型:8;坐标点小数位数精度:0(通常为0)cv::rectangle(frame, boxes[idx], cv::Scalar(0, 0, 255), 4, 8, 0); // 在原始图片上框选目标区域// 输入/输出图像:frame;绘制文本内容:labels[cid].c_str();文本起始位置(左下角):boxes[idx].tl();// 字体类型:cv::FONT_HERSHEY_PLAIN;字体大小缩放比例:2.5;文本颜色:cv::Scalar(255, 0, 0);文本线条的厚度:3;线条类型:8putText(frame, labels[cid].c_str(), boxes[idx].tl(), cv::FONT_HERSHEY_PLAIN, 2.5, cv::Scalar(255, 0, 0), 3, 8); // 目标区域的类别}// ********************************************************// 在测试图像上加上预测的目标位置和类别cv::imshow("输入图像", frame);cv::waitKey(0);// ******************* 9.释放资源*******************session_options.release();session_.release();// *************************************************return 0;
}
图片正确识别是否带着口罩:
总结
尽可能简单、详细的讲解了C++下OnnxRuntime环境部署YOLOV5模型的过程。
相关文章:
【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV5模型部署
【深度学习】【目标检测】【OnnxRuntime】【C】YOLOV5模型部署 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【目标检测】【OnnxRuntime】【C】YOLOV5模型部署前言Windows平台搭建依赖环境模型转换--pytorch转onnxONNXRuntime推…...
vcpkg安装指定版本的库
一.vcpkg安装 使用git将vcpkg源码克隆到本地制定目录(D:\vcpkg),并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下图: 二.安…...
springboot 四层架构之间的关系整理笔记五
问题:service 和 多个serviceimpl 分层之间的逻辑关系? 好的!用班级活动的例子继续讲,假设班长(Service接口)要管理多种任务,而不同的班委(ServiceImpl实现类)负责不同场…...
记录一次交易耗时有毛刺TDSQL数据库排查过程
信息同步非常重要,解决问题前,务必从应用获取实例信息、sql关键字、问题时间段、问题描述。 处理步骤: 1、登陆赤兔,打开实例监控信息,检查CPU、内存、IO、缓冲命中率、proxy汇总请求量耗时情况,初步判断…...
爱普生晶体单元FC2012AN在5G RedCap中的应用
在 5G 技术向物联网领域深度渗透的今天,RedCap(5G 轻量化)作为衔接中高速物联网场景的关键技术,正加速推动工业、医疗、可穿戴等领域的智能化升级。爱普生 FC2012AN 低 ESR 晶体单元凭借其突破性的小尺寸、低功耗与高稳定性设计&a…...
Linux: 网络,arp的数量为什么会对交换机/路由器有性能的影响
这个问题也是非常普遍的问题。比如最近比较火的一个OVS相关的问题: ARP request packets put high pressure on the pinctrl thread in ovn-controller 另一个在工作种也遇到了相似的问题,当一个网络里发了同时发了小一百个GARP之后,路由器的gateway就会有ARP处理延迟。 A…...
javaWeb vue的简单语法
一、简介 两大核心优势: 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 D…...
Android 中隐藏标题栏和状态栏的方法
在Android开发中,隐藏标题栏和状态栏是实现全屏显示的常见需求。 一、隐藏标题栏 1、通过代码隐藏 对于继承自 AppCompatActivity 的 Activty,可在 onCreate() 方法中调用supportRequestWindowFeature 或 getSupportActionBar 方法来隐藏标题栏。 ove…...
Tof 深度相机原理
深度相机(TOF)的工作原理_tof相机原理-CSDN博客 深度剖析 ToF 技术:原理、优劣、数据纠错与工业应用全解析_tof技术-CSDN博客 飞行时间技术TOF_tof计算公式-CSDN博客 深度相机(二)——飞行时间(TOF)_飞行时间技术-C…...
boost.asio
as(async):异步 同步io: reactor (非阻塞)(需要注册一次,在等待消息时可以干别的事) 阻塞io网络模型 接口:read\accept\connect\write 接口返回时,io完成 异步…...
Python 装饰器(Decorators)
什么是装饰器? 装饰器(Decorator)本质上是一个 修改其他函数功能的函数。它的核心思想是:不修改原函数代码,动态添加新功能。比如: 记录函数执行时间 检查用户权限 缓存计算结果 自动重试失败操作 理解…...
django orm的优缺点
Django ORM(对象关系映射)是 Django 框架的核心组件之一,它通过将数据库表映射为 Python 类,简化了数据库操作。以下是其优缺点总结: 优点 开发效率高 用 Python 类定义数据模型,无需手写 SQL,…...
国产RISC-V车规芯片当前现状分析——从市场与技术角度出发
摘要 随着汽车产业的智能化、电动化转型加速,车规级芯片的战略地位日益凸显。RISC-V指令集凭借其开源、灵活、低功耗等优势,成为国产车规芯片的重要发展方向。本文从市场与技术两个维度出发,深入分析国产RISC-V车规芯片的现状。通过梳理国内…...
不落因果与不昧因果
在佛教浩瀚的哲学体系中,“因果”是贯穿修行始终的核心命题。而“不落因果”与“不昧因果”这对看似矛盾的概念,恰似明镜的两面,映照出修行者对因果法则的不同认知层次。二者虽仅一字之差,却如天堑般分隔了迷悟两岸,其…...
《论语别裁》第02章 为政(08) 诗的伟大
孔子说我整理诗三百篇的宗旨在什么地方?“一言以蔽之”——一句话,“思无邪”。人不能没有思想,只要是思想不走歪曲的路,引导走上正路就好,譬如男女之爱。如果作学问的人,男女之爱都不能要,世界…...
在学校图书馆知识库中进行论文检索报告生成
首先登录信息门户—>科研服务—>机构知识库 在成果认领页面,查看自己的成果情况。如果发现自己的有些成果未被录入,可以发邮件给管理员。 最后,进入成果管理,选择需要的成果进行检索报告的生成...
《寒门枭雄传》章回体拟目与故事设计
《寒门枭雄传》章回体拟目与故事设计 主题:寒门逆袭的制度性困境与个人成长的撕裂性代价 第一回 贩履郎寒冬逢逼债 落魄汉雪夜定从戎 地点:京口草鞋摊→北府军营 人物:刘裕、刁逵(士族豪强)、刘母 故事: …...
头歌 | Linux之用户高级管理
若未实现预期结果, 可私信我帮你解答 2025-3-28 第1关:创建/删除用户组 > /data/workspace/myshixun/case1/evaluating.sh # 写入新内容 echo "echo 创建newGroup用户组成功 创建newGroupID用户组成功 设置newGroupID用户组ID成功 删除oldGroup用户组成功…...
常用的测试用例
登录、添加、删除、查询模块是我们经常遇到的,这些模块的测试点该如何考虑 1)登录 ① 用户名和密码都符合要求(格式上的要求) ② 用户名和密码都不符合要求(格式上的要求) ③ 用户名符合要求,密码不符合要求(格式上的要求) ④ 密码符合要求…...
数据结构与算法——顺序表的实现以及增、插、删、查、印、毁
文章目录 一、前言二、顺序表的概念与结构2.1顺序表的概念2.2顺序表的结构 三、顺序表的分类3.1静态顺序表3.1.1静态顺序表的弊端 3.2动态顺序表3.2.1动态顺序表的相对利弊3.2.2动态顺序表的增容方式 四、顺序表的增、插、删、查、印、毁4.1 顺序表的增容4.2顺序表的尾插和头插…...
环境 tensorflow ERROR: No matching distribution found for ai-edge-litert
提示:环境搭建 文章目录 前言多依赖安装 前言 提示:版本 之前文章 condajupyter 环境搭建 PyTorch 2.6 cpu 环境搭建 系统 :ubuntu 22.0 python :3.8 ERROR: No matching distribution found for ai-edge-litert PyTorch: sta…...
基于深度强化学习的智能机器人路径规划技术研究
在人工智能与机器人技术飞速发展的今天,智能机器人在工业、服务、物流等领域的应用日益广泛。路径规划作为智能机器人运动的核心技术之一,直接影响机器人的工作效率和安全性。近年来,深度强化学习(Deep Reinforcement Learning, D…...
【ManiSkill】环境success条件和reward函数学习笔记
1. “PickCube-v1” info["success"]:用于指示任务是否成功完成 布尔型张量,在环境的evaluate()方法中计算并返回: "success": is_obj_placed & is_robot_static这确保了机器人不仅能将物体准确放置在目标位置&am…...
畅捷通T+与吉客云数据集成案例解析
畅捷通T与吉客云的高效数据集成案例分享 在企业信息化系统中,数据的高效流转和准确对接是确保业务顺畅运行的关键。本文将聚焦于一个具体的系统对接集成案例:如何将畅捷通T中的采购入库单(红字)数据无缝集成到吉客云中࿰…...
Vue 项目中使用$refs来访问组件实例或 DOM 元素,有哪些注意事项?
大白话Vue 项目中使用$refs来访问组件实例或 DOM 元素,有哪些注意事项? 在 Vue 项目里,$refs 是个超实用的工具,它能让你直接访问组件实例或者 DOM 元素。不过使用的时候,有一些地方可得注意,下面咱就详细…...
Docker Compose 基础知识
一. Docker Compose 引言 Docker Compose 是 Docker 官方提供的一个用于定义和运行多容器 Docker 应用程序的工具。它通过一个yaml格式的配置文件(通常命名为 docker-compose.yml ),文件中定义多个服务、网络和卷,从而简化复杂应…...
科技赋能|ZGIS综合管网智能管理平台守护地下城市生命线
地下管网作为城市公共安全的重要组成部分,担负着城市的信息传递、能源输送、排涝减灾等重要任务,是维系城市正常运行、满足群众生产生活需要的重要基础设施,是城市各功能区有机连接和运转的维系,因此,也被称为城市“生…...
EXCEL报错:无法共享此工作薄,因表包含excel表或xml映射的解决方法
在分享工作薄是,如果出现了“无法共享此工作薄,因表包含excel表或xml映射”的报错,那么有两个原因: 1.包含Excel表格,这个也是相对比较常见的原因。 首先选中表格。如果你不知道表的位置在哪,那么在Excel左…...
Go 语言标准库中path模块详细功能介绍与示例
Go语言的 path 模块提供了处理斜杠分隔路径的通用方法,适用于跨平台路径操作(如 URL 路径或 Unix 风格路径)。以下是 path 模块的核心方法及示例说明: 1. path.Base 返回路径的最后一个元素(类似 Unix 的 basename 命…...
在Vue 3 + TypeScript + Vite 项目中安装和使用 SCSS
在Vue 3 TypeScript Vite 项目中安装和使用 SCSS 1、安装 SCSS 的相关依赖 npm install sass --save-dev2、配置 Vite 对于 Vue 3,Vite 已经内置了对 SCSS 的支持,通常不需要额外的配置。但是,如果需要自定义配置,可以在路径…...
洛谷题单1-B2005 字符三角形-python-流程图重构
题目描述 给定一个字符,用它构造一个底边长 5 5 5 个字符,高 3 3 3 个字符的等腰字符三角形。 输入格式 输入只有一行,包含一个字符。 输出格式 该字符构成的等腰三角形,底边长 5 5 5 个字符,高 3 3 3 个字符…...
实现金蝶与钉钉无缝对接以高效管理银行账号信息
【资料】金蝶&钉钉—银行账号 在企业信息化管理中,数据的高效集成和实时同步至关重要。本文将分享一个实际的系统对接集成案例:如何将金蝶云星空的数据集成到钉钉平台,实现银行账号信息的无缝对接。 本次集成方案【资料】金蝶&钉钉…...
正则表达式-万能表达式
1、正则 正则表达式是一组由字母和符号组成的特殊文本, 它可以用来从文本中找 出满足你想要的格式的句子. {“basketId”: 0, “count”: 1, “prodId”: #prodId#, “shopId”: 1, “skuId”: #skuId#} #prodId# re相关的文章: https://www.cnblogs.com/Simple-S…...
ComfyUi教程之阿里的万象2.1视频模型
ComfyUi教程之阿里的万象2.1视频模型 官网Wan 2.1 特点 一、本地安装1.1克隆仓库1.2 安装依赖(1.3)下载模型(1.4)CUDA和CUDNN 二、 使用体验(2.1)官方例子(2.2)执行过程(…...
如何在一个图片上添加另外一个图片
如果你使用的windows10 系统,可以使用系统自带的画图工具 1. 打开windows搜索, 画图工具 2. 在画图软件内, ctrlc 复制图片 , ctrlv粘贴图片 3. 调整想要粘贴的图片,到上图汇总,最后保存,或者…...
【面试题】在 CSS 中,实现一个 div 中的子 div 水平垂直居中
1. 使用 Flexbox 特点:简单、直观,现代浏览器支持良好。 代码: css .parent {display: flex;justify-content: center; /* 水平居中 */align-items: center; /* 垂直居中 */height: 200px; /* 父容器需有高度 */ } .child {…...
Electron 项目开机自启动
app.setLoginItemSettings 与 auto-launch 对比分析 一、稳定性对比 1. app.setLoginItemSettings 优点:作为Electron官方API,有官方维护和支持缺点: 在某些Windows版本上存在已知问题部分Windows 10/11更新后可能失效在macOS权限更严格的…...
sql基础
本文多数内容属于个人基于网上资料的理解,如果有问题请告知修改,十分感谢 定义 百度百科:SQL (Structured Query Language) 是具有数据操纵和数据定义等多种功能的数据库语言,这种语言具有交互性特点,能为用户提供极…...
【C++数据库】SQLite3数据库连接与操作
注意:本文代码均为C++20标准下实现 一、SQLite3库安装 1.1 安装库文件 【工具】跨平台C++包管理利器vcpkg完全指南 vcpkg install sqlite3# 集成至系统目录,之前执行过此命令的无需再次执行 vcpkg integrate install1.2 验证代码 在VS2022中新建控制台项目,测试代码如下…...
数据结构——Map和Set
1. 搜索树 1. 概念 ⼆叉搜索树⼜称⼆叉排序树,它可以是⼀棵空树,或者是具有以下性质的⼆叉树: • 若它的左⼦树不为空,则左⼦树上所有节点的值都⼩于根节点的值 • 若它的右⼦树不为空,则右⼦树上所有节点的值都⼤于根节点的值…...
zsh安装以及安装配置oh-my-zsh安装zsh-autosuggestionszsh-syntax-highlighting
下面是安装 zsh 及配置 oh‑my‑zsh 的详细步骤,适用于 Linux 和 macOS 环境: 1. 安装 zsh 1.1 在 macOS 上安装 zsh macOS 通常预装了 zsh,但建议升级到最新版本。你可以通过 Homebrew 来安装最新版: brew install zsh安装完成…...
VMware 安装 Ubuntu 实战分享
VMware 安装 Ubuntu 实战分享 VMware 是一款强大的虚拟机软件,广泛用于多操作系统环境的搭建。本文将详细介绍如何在 VMware 中安装 Ubuntu,并分享安装过程中的常见问题及解决方法。 1. 安装前的准备工作 (1) 系统要求 主机操作系统:Windo…...
【SpringCloud】Eureka的使用
3. Eureka 3.1 Eureka 介绍 Eureka主要分为两个部分: EurekaServer: 作为注册中心Server端,向微服务应用程序提供服务注册,发现,健康检查等能力。 EurekaClient: 服务提供者,服务启动时,会向 EurekaS…...
Redis:List 类型 内部实现、命令及应用场景
Redis 中的 List(列表)类型是一种有序的数据结构,它可以存储多个字符串元素,并且这些元素按照插入顺序排列。可以将它理解为一个双向链表,支持在链表的两端进行快速的插入和删除操作。它允许元素重复,并且可…...
Python 字符串正则表达式详解
Python 字符串正则表达式详解 一、正则表达式核心语法 元字符含义正确示例与说明常见错误修正.匹配任意字符(换行符除外)a.b → 匹配"acb"、“a1b”不匹配换行符(需用re.S模式)^匹配字符串开头^Hello → 匹配以"H…...
重试机制之指针退避策略算法
一、目的:随着重试次数增加,逐步延长重连等待时间,避免加重服务器负担。 二、计算公式: 每次重试的延迟时间 初始间隔 (退避基数 ^ 重试次数) 通常设置上限防止等待时间过长。 const delay Math.min(initialDelay * Math.pow…...
pyqt第一个窗口程序
文章目录 官方文档相手动创建窗口程序designer创建ui布局 官方文档相 https://doc.qt.io/qtforpython-6/ 手动创建窗口程序 import sys # 导入系统模块,用于获取命令行参数和系统功能 from PySide6.QtWidgets import QApplication, QLabel # 导入Qt组件&#x…...
【蓝桥杯】单片机设计与开发,PWM
一、PWM概述 用来输出特定的模拟电压。 二、PWM的输出 三、例程一:单片机P34引脚输出1kHZ的频率 void Timer0Init(void);unsigned char PWMtt 0;void main(void) {P20XA0;P00X00;P20X80;P00XFF;Timer0Init();EA1;ET01;ET11;while(1);}void Timer0Init(void) //1…...
CSS学习笔记5——渐变属性+盒子模型阶段案例
目录 通俗易懂的解释 渐变的类型 1、线性渐变 渐变过程 2、径向渐变 如何理解CSS的径向渐变,以及其渐变属性 通俗易懂的解释 渐变属性 1. 形状(Shape) 2. 大小(Size) 3. 颜色停靠点(Color Sto…...
频谱分析仪的最大保持功能
专门应用于例如遥控器之类的,按一下,一瞬间出现的信号的测量。 把仪器连接天线,观测空间中的一些信号,比如WIFI的信号,我们可以看到仪器接收到的信号其实是一直变化的,并不是每一次扫描都能扫到我们想要的这…...