YOLOv8模型pytorch格式转为onnx格式
一、YOLOv8的Pytorch网络结构

model DetectionModel((model): Sequential((0): Conv((conv): Conv2d(3, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(1): Conv((conv): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(2): C2f((cv1): Conv((conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(320, 128, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-2): 3 x Bottleneck((cv1): Conv((conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(3): Conv((conv): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(4): C2f((cv1): Conv((conv): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-5): 6 x Bottleneck((cv1): Conv((conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(5): Conv((conv): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(6): C2f((cv1): Conv((conv): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-5): 6 x Bottleneck((cv1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(7): Conv((conv): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(8): C2f((cv1): Conv((conv): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-2): 3 x Bottleneck((cv1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(9): SPPF((cv1): Conv((conv): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): MaxPool2d(kernel_size=5, stride=1, padding=2, dilation=1, ceil_mode=False))(10): Upsample(scale_factor=2.0, mode='nearest')(11): Concat()(12): C2f((cv1): Conv((conv): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-2): 3 x Bottleneck((cv1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(13): Upsample(scale_factor=2.0, mode='nearest')(14): Concat()(15): C2f((cv1): Conv((conv): Conv2d(768, 256, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(640, 256, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-2): 3 x Bottleneck((cv1): Conv((conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(16): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(17): Concat()(18): C2f((cv1): Conv((conv): Conv2d(768, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-2): 3 x Bottleneck((cv1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(19): Conv((conv): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(act): SiLU(inplace=True))(20): Concat()(21): C2f((cv1): Conv((conv): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1))(act): SiLU(inplace=True))(m): ModuleList((0-2): 3 x Bottleneck((cv1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(cv2): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True)))))(22): PostDetect((cv2): ModuleList((0): Sequential((0): Conv((conv): Conv2d(256, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(1): Conv((conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(1-2): 2 x Sequential((0): Conv((conv): Conv2d(512, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(1): Conv((conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))))(cv3): ModuleList((0): Sequential((0): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(2): Conv2d(256, 35, kernel_size=(1, 1), stride=(1, 1)))(1-2): 2 x Sequential((0): Conv((conv): Conv2d(512, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(1): Conv((conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(act): SiLU(inplace=True))(2): Conv2d(256, 35, kernel_size=(1, 1), stride=(1, 1))))(dfl): DFL((conv): Conv2d(16, 1, kernel_size=(1, 1), stride=(1, 1), bias=False))))
)
yolov8网络从1-21层与pt文件相对应是BackBone和Neck模块,22层是Head模块。


二、转ONNX步骤
2.1 yolov8官方
"""
代码解释
pt模型转为onnx格式
"""
import os
from ultralytics import YOLO
model = YOLO("weights/best.pt")
success = model.export(format="onnx")print("导出成功!")
将pytorch转为onnx后,pytorch支持的一系列计算就会转为onnx所支持的算子,若没有相对应的就会使用其他方式进行替换(比如多个计算替换其单个)。比较常见是conv和SiLU合并成一个Conv模块进行。

其中,1*4*8400表示每张图片预测 8400 个候选框,每个框有 4 个参数边界框坐标 (x,y,w,h)。 1*35*8400类同,1和4800代表意义相同,35是类别属性包含了其置信度概率值。
最后两个输出Concat操作,得到1*39*8400。最后根据这个结果去进行后续操作。
2.2 自定义转换
所谓的自定义转换其实是在转onnx时,对1*39*8400多加了一系列自定义操作例如NMS等。
2.2.1 加载权重并优化结构
YOLOv8 = YOLO(args.weights) #替换为自己的权重
model = YOLOv8.model.fuse().eval()
2.2.2 后处理检测模块
def gen_anchors(feats: Tensor,strides: Tensor,grid_cell_offset: float = 0.5) -> Tuple[Tensor, Tensor]:"""生成锚点,并计算每个锚点的步幅。参数:feats (Tensor): 特征图,通常来自不同的网络层。strides (Tensor): 每个特征图的步幅(stride)。grid_cell_offset (float): 网格单元的偏移量,默认为0.5。返回:Tuple[Tensor, Tensor]: 锚点的坐标和对应的步幅张量。"""anchor_points, stride_tensor = [], []assert feats is not None # 确保输入的特征图不为空dtype, device = feats[0].dtype, feats[0].device # 获取特征图的数据类型和设备# 遍历每个特征图,计算锚点for i, stride in enumerate(strides):_, _, h, w = feats[i].shape # 获取特征图的高(h)和宽(w)sx = torch.arange(end=w, device=device,dtype=dtype) + grid_cell_offset # 计算 x 轴上的锚点位置sy = torch.arange(end=h, device=device,dtype=dtype) + grid_cell_offset # 计算 y 轴上的锚点位置sy, sx = torch.meshgrid(sy, sx) # 生成网格坐标anchor_points.append(torch.stack((sx, sy), -1).view(-1, 2)) # 将 x 和 y 组合成坐标点stride_tensor.append(torch.full((h * w, 1), stride, dtype=dtype, device=device)) # 生成步幅张量return torch.cat(anchor_points), torch.cat(stride_tensor) # 返回合并后的锚点和步幅class customize_NMS(torch.autograd.Function):"""继承torch.autograd.Function用于TensorRT的非极大值抑制(NMS)自定义函数。"""@staticmethoddef forward(ctx: Graph,boxes: Tensor,scores: Tensor,iou_threshold: float = 0.65,score_threshold: float = 0.25,max_output_boxes: int = 100,background_class: int = -1,box_coding: int = 0,plugin_version: str = '1',score_activation: int = 0) -> Tuple[Tensor, Tensor, Tensor, Tensor]:"""正向计算NMS输出,模拟真实的TensorRT NMS过程。参数:boxes (Tensor): 预测的边界框。scores (Tensor): 预测框的置信度分数。其他参数同样为NMS的超参数。返回:Tuple[Tensor, Tensor, Tensor, Tensor]: 包含检测框数量、框坐标、置信度分数和类别标签。"""batch_size, num_boxes, num_classes = scores.shape # 获取批量大小、框数量和类别数num_dets = torch.randint(0,max_output_boxes, (batch_size, 1),dtype=torch.int32) # 随机生成检测框数量(仅为模拟)boxes = torch.randn(batch_size, max_output_boxes, 4) # 随机生成预测框scores = torch.randn(batch_size, max_output_boxes) # 随机生成分数labels = torch.randint(0,num_classes, (batch_size, max_output_boxes),dtype=torch.int32) # 随机生成类别标签return num_dets, boxes, scores, labels # 返回模拟的结果@staticmethoddef symbolic(g,boxes: Value,scores: Value,iou_threshold: float = 0.45,score_threshold: float = 0.25,max_output_boxes: int = 100,background_class: int = -1,box_coding: int = 0,score_activation: int = 0,plugin_version: str = '1') -> Tuple[Value, Value, Value, Value]:"""计算图的符号函数,供TensorRT使用。参数:g: 计算图对象boxes (Value), scores (Value): 传入的边界框和得分其他参数是用于配置NMS的参数。返回:经过NMS处理的检测框、得分、类别标签及检测框数量。"""out = g.op('TRT::EfficientNMS_TRT',boxes,scores,iou_threshold_f=iou_threshold,score_threshold_f=score_threshold,max_output_boxes_i=max_output_boxes,background_class_i=background_class,box_coding_i=box_coding,plugin_version_s=plugin_version,score_activation_i=score_activation,outputs=4) # 使用TensorRT的EfficientNMS插件nums_dets, boxes, scores, classes = out # 获取输出的检测框数量、框坐标、得分和类别return nums_dets, boxes, scores, classes # 返回结果class Post_process_Detect(nn.Module):"""用于后处理的检测模块,执行检测后的非极大值抑制(NMS)。"""export = Trueshape = Nonedynamic = Falseiou_thres = 0.65 # 默认的IoU阈值conf_thres = 0.25 # 默认的置信度阈值topk = 100 # 输出的最大检测框数量def __init__(self, *args, **kwargs):super().__init__()def forward(self, x):"""执行后处理操作,提取预测框、置信度和类别。参数:x (Tensor): 输入的特征图。返回:Tuple[Tensor, Tensor, Tensor]: 预测框、置信度和类别。"""shape = x[0].shape # 获取输入的形状b, res, b_reg_num = shape[0], [], self.reg_max * 4# b为特征列表第一个元素的批量大小,表示处理的样本数量,# res声明一个空列表存储处理过的特征图# b_reg_num为回归框的数量#遍历特征层(self.nl表示特征层数),将每一层的框预测和分类预测拼接。for i in range(self.nl):res.append(torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)) # 特征拼接# 调用# make_anchors# 生成锚点和步幅,用于还原边界框的绝对坐标。if self.dynamic or self.shape != shape:self.anchors, self.strides = (x.transpose(0, 1) for x in gen_anchors(x, self.stride, 0.5)) # 生成锚点和步幅self.shape = shape # 更新输入的形状x = [i.view(b, self.no, -1) for i in res] # 调整特征图形状y = torch.cat(x, 2) # 拼接所有特征图boxes, scores = y[:, :b_reg_num, ...], y[:, b_reg_num:, ...].sigmoid() # 提取框和分数boxes = boxes.view(b, 4, self.reg_max, -1).permute(0, 1, 3, 2) # 变换框的形状boxes = boxes.softmax(-1) @ torch.arange(self.reg_max).to(boxes) # 对框进行softmax处理boxes0, boxes1 = -boxes[:, :2, ...], boxes[:, 2:, ...] # 分离框的不同部分boxes = self.anchors.repeat(b, 2, 1) + torch.cat([boxes0, boxes1], 1) # 合并框坐标boxes = boxes * self.strides # 乘以步幅return customize_NMS.apply(boxes.transpose(1, 2), scores.transpose(1, 2),self.iou_thres, self.conf_thres, self.topk) # 执行NMSdef optim(module: nn.Module):setattr(module, '__class__', Post_process_Detect)for item in model.modules():optim(item)item.to(args.device) #输入cpu或者gpu的卡号

自定义这里是在yolo官方得到的1*4*8400和1*35*8400进行矩阵转换2<->3,最后引入EfficientNMS_TRT插件后处理,可以有效加速NMS处理。
2.2.3 EfficientNMS_TRT插件
EfficientNMS_TRT 是 TensorRT 中的一个高效非极大值抑制 (NMS) 插件,用于快速过滤检测框。它通过优化的 CUDA 实现来执行 NMS 操作,特别适合于深度学习推理阶段中目标检测任务的后处理。支持在一个批次中对多个图像同时执行 NMS。

输出结果为num_dets, detection_boxes, detection_scores, detection_classes ,分别代表经过 NMS 筛选后保留的边界框数,每张图片保留的检测框的坐标,每张图片中保留下来的检测框的分数(由高到低),每个保留下来的边界框的类别索引。
三、结语
仅供学习使用!!!
相关文章:
YOLOv8模型pytorch格式转为onnx格式
一、YOLOv8的Pytorch网络结构 model DetectionModel((model): Sequential((0): Conv((conv): Conv2d(3, 64, kernel_size(3, 3), stride(2, 2), padding(1, 1))(act): SiLU(inplaceTrue))(1): Conv((conv): Conv2d(64, 128, kernel_size(3, 3), stride(2, 2), padding(1, 1))(a…...
电子课程开发中的典型误区
创建一个有效的电子课程需要仔细的规划和执行,但常见的错误可能会破坏其成功。以下是开发人员应该避免的一些典型陷阱: 1.缺乏明确的目标 如果没有明确的学习目标,课程可能会缺乏重点,让学习者不确定自己应该实现什么。明确、可衡…...
Docker 逃逸突破边界
免责声明 本博客文章仅供教育和研究目的使用。本文中提到的所有信息和技术均基于公开来源和合法获取的知识。本文不鼓励或支持任何非法活动,包括但不限于未经授权访问计算机系统、网络或数据。 作者对于读者使用本文中的信息所导致的任何直接或间接后果不承担任何…...
残差连接,就是当某一偏导等于0时,加上x偏导就是1,这样乘以1保证不失效
目录 残差连接,就是当某一偏导等于0时,加上x偏导就是1,这样乘以1保证不失效 残差连接中F(x)一般代表什么,将F(x)变为F(x) +x,这样不是改变了函数 本身的性质 F(x)=F(x) +x F(x)偏导若==0;偏导连乘就是0,这样就梯度消失了 F(x) +x;求偏导时x导数是1,保证不丢失F(x)…...
博泽Brose EDI项目案例
Brose 是一家德国的全球性汽车零部件供应商,主要为全球汽车制造商提供机电一体化系统和组件,涵盖车门、座椅调节系统、空调系统以及电动驱动装置等。Brose 以其高质量的创新产品闻名,在全球拥有多个研发和生产基地,是全球第五大家…...
从科举到高考,人才选拔制度的变革与发展
一、引言 在人类历史的长河中,人才选拔机制始终是推动社会进步与文明传承的关键环节。古代科举制度与现代高考制度,分别在各自的时代背景下承担着筛选人才的重任,二者虽皆关乎教育与人才进阶之路,却有着诸多本质性的区别与独特的…...
利用Docker一键发布Nginx-Tomcat-MySQL应用集群
Docker简介,可以看上一篇文章: 为什么互联网公司离不开Docker容器化,它到底解决了什么问题?-CSDN博客 Docker体系结构 docker核心就是镜像和容器: 镜像就是应用程序的安装文件,包含了所有需要的资源&…...
关于数据库数据国际化方案
方案一:每个表设计一个翻译表 数据库国际化的应用场景用到的比较少,主要用于对数据库的具体数据进行翻译,在需要有大量数据翻译的场景下使用,举个例子来说,力扣题目的中英文切换。参考方案可见: https://b…...
【系统架构设计师】高分论文:论信息系统的安全与保密设计
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 摘要正文摘要 本人所在工作单位承担了我市城乡智慧建设工程综合管理平台项目的开发工作。我有幸参与了本项目,并担任架构师一职,全面负责项目的需求分析和系统设计等工作。城乡智慧建设工程综合管理平台项目包括…...
使用Tauri创建桌面应用
当前是在 Windows 环境下 1.准备 系统依赖项 Microsoft C 构建工具WebView2 (Windows10 v1803 以上版本不用下载,已经默认安装了) 下载安装 Rust下载安装 Rust 需要重启终端或者系统 重新打开cmd,键入rustc --version,出现 rust 版本号&…...
【docker】docker compose多容器部署
Docker Compose 的详细讲解与实际应用 什么是 Docker Compose? Docker Compose 是一个工具,用于定义和运行多容器 Docker 应用。 通过一个 docker-compose.yml 文件,可以同时启动多个服务,简化多容器管理。 Docker Compose 的核心…...
JS +CSS @keyframes fadeInUp 来定义载入动画
JSCSS 更完美展现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>跳动加载指示器</title>&l…...
Seatunnel解决ftp读取json文件无法读取数组以及格式化之后的json无法解析的问题
问题原因 在JsonRead这个方法里面 在源码中使用的逻辑是读取一行 然后把这个json进行解析 但是这样存在一个问题 比如如果json的格式是这样的 { name:“zhangsan”, age:25 } 如果是这样的话 第一行读到的内容就是 { 显然 一个 { 并不是一个…...
Elasticsearch在liunx 中单机部署
下载配置 1、下载 官网下载地址 2、上传解压 tar -zxvf elasticsearch-XXX.tar.gz 3、新建组和用户 (elasticsearch 默认不允许root账户) #创建组 es groupadd es #新建用户 useradd ryzhang -g es 4、更改文件夹的用户权限 chown -R ryzhang …...
深入探索 HarmonyOS 的 Navigation 组件:灵活的页面管理与动态导航
在移动应用开发中,页面的跳转和导航一直是核心功能之一。对于 HarmonyOS 开发者来说,Navigation 组件提供了一个强大的工具来实现灵活的页面管理和导航体验。今天,我们将深入探讨如何使用 HarmonyOS 中的 Navigation 组件来管理页面跳转、工具…...
【CUDA】CUDA Hierarchy
【CUDA】CUDA 基本概念和 Hierarchy CUDA 编程基础:Host 和 Device 工作流程 首先简单介绍CUDA 编程的基本概念:讲解 Host(CPU)与 Device(GPU)的区别、内存管理以及 CUDA 运行时的工作机制。 Host&#x…...
28.100ASK_T113-PRO Linux+QT 显示一张照片
1.添加资源文件 2. 主要代码 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QImage> #include <QPixmap>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);QIm…...
GitLab使用中遇到的一些问题-记录
错误内容一 Warning: Permanently added gitlab.com (ED25519) to the list of known hosts. gitgitlab.com: Permission denied (publickey). Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. …...
【微服务】Docker
一、Docker基础 1、依赖的兼容问题:Docker允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像Docker应用运行在容器中,使用沙箱机制,相互隔离。 2、如何解决开发、测试、生产环境有差异的问题:Docker镜像…...
【C#】书籍信息的添加、修改、查询、删除
文章目录 一、简介二、程序功能2.1 Book类属性:方法: 2.2 Program 类 三、方法:四、用户界面流程:五、程序代码六、运行效果 一、简介 简单的C#控制台应用程序,用于管理书籍信息。这个程序将允许用户添加、编辑、查看…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...
基于 HTTP 的单向流式通信协议SSE详解
SSE(Server-Sent Events)详解 🧠 什么是 SSE? SSE(Server-Sent Events) 是 HTML5 标准中定义的一种通信机制,它允许服务器主动将事件推送给客户端(浏览器)。与传统的 H…...
