当前位置: 首页 > news >正文

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…...

电子课程开发中的典型误区

创建一个有效的电子课程需要仔细的规划和执行&#xff0c;但常见的错误可能会破坏其成功。以下是开发人员应该避免的一些典型陷阱&#xff1a; 1.缺乏明确的目标 如果没有明确的学习目标&#xff0c;课程可能会缺乏重点&#xff0c;让学习者不确定自己应该实现什么。明确、可衡…...

Docker 逃逸突破边界

免责声明 本博客文章仅供教育和研究目的使用。本文中提到的所有信息和技术均基于公开来源和合法获取的知识。本文不鼓励或支持任何非法活动&#xff0c;包括但不限于未经授权访问计算机系统、网络或数据。 作者对于读者使用本文中的信息所导致的任何直接或间接后果不承担任何…...

残差连接,就是当某一偏导等于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 是一家德国的全球性汽车零部件供应商&#xff0c;主要为全球汽车制造商提供机电一体化系统和组件&#xff0c;涵盖车门、座椅调节系统、空调系统以及电动驱动装置等。Brose 以其高质量的创新产品闻名&#xff0c;在全球拥有多个研发和生产基地&#xff0c;是全球第五大家…...

从科举到高考,人才选拔制度的变革与发展

一、引言 在人类历史的长河中&#xff0c;人才选拔机制始终是推动社会进步与文明传承的关键环节。古代科举制度与现代高考制度&#xff0c;分别在各自的时代背景下承担着筛选人才的重任&#xff0c;二者虽皆关乎教育与人才进阶之路&#xff0c;却有着诸多本质性的区别与独特的…...

利用Docker一键发布Nginx-Tomcat-MySQL应用集群

Docker简介&#xff0c;可以看上一篇文章&#xff1a; 为什么互联网公司离不开Docker容器化&#xff0c;它到底解决了什么问题&#xff1f;-CSDN博客 Docker体系结构 docker核心就是镜像和容器&#xff1a; 镜像就是应用程序的安装文件&#xff0c;包含了所有需要的资源&…...

关于数据库数据国际化方案

方案一&#xff1a;每个表设计一个翻译表 数据库国际化的应用场景用到的比较少&#xff0c;主要用于对数据库的具体数据进行翻译&#xff0c;在需要有大量数据翻译的场景下使用&#xff0c;举个例子来说&#xff0c;力扣题目的中英文切换。参考方案可见&#xff1a; https://b…...

【系统架构设计师】高分论文:论信息系统的安全与保密设计

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 摘要正文摘要 本人所在工作单位承担了我市城乡智慧建设工程综合管理平台项目的开发工作。我有幸参与了本项目,并担任架构师一职,全面负责项目的需求分析和系统设计等工作。城乡智慧建设工程综合管理平台项目包括…...

使用Tauri创建桌面应用

当前是在 Windows 环境下 1.准备 系统依赖项 Microsoft C 构建工具WebView2 (Windows10 v1803 以上版本不用下载&#xff0c;已经默认安装了) 下载安装 Rust下载安装 Rust 需要重启终端或者系统 重新打开cmd&#xff0c;键入rustc --version&#xff0c;出现 rust 版本号&…...

【docker】docker compose多容器部署

Docker Compose 的详细讲解与实际应用 什么是 Docker Compose&#xff1f; Docker Compose 是一个工具&#xff0c;用于定义和运行多容器 Docker 应用。 通过一个 docker-compose.yml 文件&#xff0c;可以同时启动多个服务&#xff0c;简化多容器管理。 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&#xff1a;“zhangsan”&#xff0c; age&#xff1a;25 } 如果是这样的话 第一行读到的内容就是 { 显然 一个 { 并不是一个…...

Elasticsearch在liunx 中单机部署

下载配置 1、下载 官网下载地址 2、上传解压 tar -zxvf elasticsearch-XXX.tar.gz 3、新建组和用户 &#xff08;elasticsearch 默认不允许root账户&#xff09; #创建组 es groupadd es #新建用户 useradd ryzhang -g es 4、更改文件夹的用户权限 chown -R ryzhang …...

深入探索 HarmonyOS 的 Navigation 组件:灵活的页面管理与动态导航

在移动应用开发中&#xff0c;页面的跳转和导航一直是核心功能之一。对于 HarmonyOS 开发者来说&#xff0c;Navigation 组件提供了一个强大的工具来实现灵活的页面管理和导航体验。今天&#xff0c;我们将深入探讨如何使用 HarmonyOS 中的 Navigation 组件来管理页面跳转、工具…...

【CUDA】CUDA Hierarchy

【CUDA】CUDA 基本概念和 Hierarchy CUDA 编程基础&#xff1a;Host 和 Device 工作流程 首先简单介绍CUDA 编程的基本概念&#xff1a;讲解 Host&#xff08;CPU&#xff09;与 Device&#xff08;GPU&#xff09;的区别、内存管理以及 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、依赖的兼容问题&#xff1a;Docker允许开发中将应用、依赖、函数库、配置一起打包&#xff0c;形成可移植镜像Docker应用运行在容器中&#xff0c;使用沙箱机制&#xff0c;相互隔离。 2、如何解决开发、测试、生产环境有差异的问题&#xff1a;Docker镜像…...

【C#】书籍信息的添加、修改、查询、删除

文章目录 一、简介二、程序功能2.1 Book类属性&#xff1a;方法&#xff1a; 2.2 Program 类 三、方法&#xff1a;四、用户界面流程&#xff1a;五、程序代码六、运行效果 一、简介 简单的C#控制台应用程序&#xff0c;用于管理书籍信息。这个程序将允许用户添加、编辑、查看…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...