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

深度学习--图像分割UNet介绍及代码分析

UNet介绍

  • 参考
  • UNet网络介绍
    • 整体架构
    • UNet过程
      • 输入
      • 编码器(下采样)
      • 中间特征表示
      • 解码器(上采样)
      • 输出
  • 代码详解
    • unetUP和Unet关系
    • 上采样模块——unetUp
    • 用于图像分割的卷积神经网络(CNN)架构模块——Unet
      • 类的定义
      • 初始化方法
      • 上采样模块
      • 额外的上采样卷积层(仅用于ResNet50)
      • 最终卷积层
      • 前向传播方法
      • 冻结和解冻骨干网络
  • 完整代码

参考

U-Net: Convolutional Networks for Biomedical Image Segmentation 输入文章名自行查询
参考博客

UNet网络介绍

整体架构

在这里插入图片描述

U-net 架构(以最低分辨率为 32x32 像素为例),每个蓝色框对应一个多通道特征图。通道数显示在框的顶部。x-y 大小位于框的左下边缘。白框表示复制的特征图。箭头表示不同的操作。
深蓝色箭头:利用3×3的卷积核对图片进行卷积后,通过ReLU激活函数输出特征通道;
灰色箭头:对左边下采样过程中的图片进行裁剪复制;
红色箭头:通过最大池化对图片进行下采样,池化核大小为2×2;
绿色箭头:反卷积,对图像进行上采样,卷积核大小为2×2;
青色箭头:使用1×1的卷积核对图片进行卷积。
因为网络形状像U,故被称为U-net
参考博客(网络结构很清晰,推荐)

UNet过程

输入

U-Net 的输入是一幅单通道的图像,通常大小为 572x572 像素,由于在不断valid卷积过程中,会使得图片越来越小,为了避免数据丢失,在图像输入前都需要进行镜像扩大。

编码器(下采样)

  • U-Net 的编码器部分输入图像通过卷积层进行特征提取,这些卷积层通常使用 3x3 的卷积核,逐步提取图像特征并缩小空间维度。
  • 然后,通过池化层(通常是最大池化)将图像的空间维度减小,例如从 572x572 缩小到 286x286。
  • 这个过程会重复多次,每次都会减小图像的空间维度和增加特征通道数。

中间特征表示

  • 在编码器的最后一层,我们获得了一个中间特征表示,通常是一个高维的特征张量。
  • 这个特征表示包含了图像的抽象特征,可以用于后续的分割任务。

解码器(上采样)

  • U-Net 的解码器部分将中间特征表示还原到原始的空间维度,并逐步增加分辨率。
  • 首先,通过上采样操作将特征张量的空间维度扩大,例如从 286x286 扩大到 572x572。
  • 然后,通过卷积层进行特征融合,将低级和高级特征结合起来。
  • 最后,输出通道数为 64 的卷积层将特征映射到最终的分割结果。

输出

  • U-Net 的输出是一个分割图像,大小与输入图像相同(通常为 572x572 像素),这幅分割图像被分成不同的区域,其中不同区域被分配不同的标签或类别。
  • 分割图像中的每个像素都被分类到不同的类别中,即可以准确地知道图像中的每个像素属于哪个结构或区域。这个分割图像可以用于识别生物医学图像中的不同结构,例如肿瘤、器官等。

代码详解

unetUP和Unet关系

  1. unetUp:

    • unetUp 是一个自定义的 PyTorch 模块(nn.Module),用于实现 U-Net 模型中的上采样部分。
    • 它接受两个输入特征张量 inputs1inputs2,并将它们进行上采样、特征融合和卷积操作,最终输出一个特征张量。
    • 在 U-Net 中,unetUp 负责将低分辨率的特征图上采样到与高分辨率特征图相同的尺寸,以便进行特征融合。
  2. Unet:

    • Unet 是整个 U-Net 模型的主体部分,它由多个 unetUp 模块组成。
    • 根据选择的 backbone(可以是 VGG 或 ResNet-50),Unet 使用不同的主干网络提取特征。
    • Unet 的前向传播过程包括多次特征融合,上采样和卷积操作,最终生成语义分割结果。

上采样模块——unetUp

这段代码定义了一个名为 unetUp 的类,它是一个用于UNet架构中的上采样模块。这个模块的作用是将低分辨率特征图上采样并与高分辨率特征图结合,以生成更高分辨率的输出。

# 定义unetUp类,unetUp类继承自nn.Module,是PyTorch中所有神经网络模块的基类。
class unetUp(nn.Module):
# 初始化方法
in_size 和 out_size 是输入和输出通道的数量。
self.conv1 和 self.conv2 是两个二维卷积层,卷积核大小为3,填充为1。
self.up 是一个最近邻插值的上采样层,放大倍数为2。
self.relu 是一个ReLU激活函数。def __init__(self, in_size, out_size):super(unetUp, self).__init__()self.conv1 = nn.Conv2d(in_size, out_size, kernel_size=3, padding=1)self.conv2 = nn.Conv2d(out_size, out_size, kernel_size=3, padding=1)self.up = nn.UpsamplingNearest2d(scale_factor=2)self.relu = nn.ReLU(inplace=True)
# 前向传播方法
# inputs1 和 inputs2 是前向传播时的输入张量。
# torch.cat([inputs1, self.up(inputs2)], 1) 将 inputs1 和上采样后的 inputs2 在通道维度上拼接。
# outputs = self.conv1(outputs) 对拼接后的张量进行第一次卷积。
# outputs = self.relu(outputs) 对卷积结果应用ReLU激活函数。
# outputs = self.conv2(outputs) 对激活后的张量进行第二次卷积。
# outputs = self.relu(outputs) 再次应用ReLU激活函数。最终返回处理后的 outputs。
# 这段代码的主要功能是将低分辨率特征图上采样并与高分辨率特征图结合,经过两次卷积和激活函数处理后,生成更高分辨率的输出特征图。def forward(self, inputs1, inputs2):outputs = torch.cat([inputs1,self.up(inputs2)],1)outputs = self.conv1(outputs)outputs = self.relu(outputs)outputs = self.conv2(outputs)outputs = self.relu(outputs)return outputs

用于图像分割的卷积神经网络(CNN)架构模块——Unet

下面这段代码定义了一个名为 Unet 的类,它是一个用于图像分割的卷积神经网络(CNN)架构。这个类可以使用不同的骨干网络(backbone),如VGG16或ResNet50,并包含上采样模块以生成高分辨率的输出。以下是对代码的详细解释:

类的定义

class Unet(nn.Module):

Unet 类继承自 nn.Module,这是PyTorch中所有神经网络模块的基类。

初始化方法

def __init__(self, num_classes=21, pretrained=False, backbone='vgg'):super(Unet, self).__init__()if backbone == 'vgg':self.vgg = VGG16(pretrained=pretrained)in_filters = [192, 384, 768, 1024]elif backbone == "resnet50":self.resnet = resnet50(pretrained=pretrained)in_filters = [192, 512, 1024, 3072]else:raise ValueError('Unsupported backbone - `{}`, Use vgg, resnet50.'.format(backbone))out_filters = [64, 128, 256, 512]
  • num_classes 是输出类别的数量。
  • pretrained 指示是否使用预训练的权重。
  • backbone 指定使用的骨干网络,可以是VGG16或ResNet50。
  • 根据选择的骨干网络,初始化相应的网络并设置输入过滤器的数量。
  • in_filters(输入通道数):在卷积神经网络(CNN)中,in_filters 表示输入图像的通道数或特征图的数量。在输入层,如果是灰度图片,那就只有一个 feature map;如果是彩色图片,一般就是 3 个 feature map(对应红、绿、蓝通道)。在其他层,每个卷积核(也称为过滤器)与上一层的每个 feature map 做卷积,产生下一层的一个 feature map。因此,如果有 N 个卷积核,下一层就会产生 N 个 feature map。
  • out_filters(输出通道数):在卷积神经网络中,out_filters 表示卷积核的数量或输出的特征图数量。卷积核的个数决定了下一层的 feature map 数量。每个卷积核可以提取一种特征,并生成一个新的特征图。在多层卷积网络中,下一层的卷积核的通道数等于上一层的 feature map 数量。如果通道数不相等,就无法继续进行卷积操作。

上采样模块

# upsampling
self.up_concat4 = unetUp(in_filters[3], out_filters[3])
self.up_concat3 = unetUp(in_filters[2], out_filters[2])
self.up_concat2 = unetUp(in_filters[1], out_filters[1])
self.up_concat1 = unetUp(in_filters[0], out_filters[0])
  • 定义四个上采样模块,每个模块将低分辨率特征图上采样到更高分辨率并与高分辨率特征图结合。
  • self.up_concat4, self.up_concat3, self.up_concat2 , self.up_concat1 是上采样操作的一部分。它们分别将不同层的特征图级联在一起,以获得更丰富的特征表示

额外的上采样卷积层(仅用于ResNet50)

if backbone == 'resnet50':self.up_conv = nn.Sequential(# 使用双线性插值(nn.UpsamplingBilinear2d)将特征图的大小放大两倍nn.UpsamplingBilinear2d(scale_factor=2), # 通过两个卷积层对特征图进行处理,以获得更好的特征表示nn.Conv2d(out_filters[0], out_filters[0], kernel_size=3, padding=1),# 使用 nn.ReLU() 激活函数来确保非线性变换nn.ReLU(),nn.Conv2d(out_filters[0], out_filters[0], kernel_size=3, padding=1),nn.ReLU(),)
else:self.up_conv = None
  • 如果使用ResNet50作为骨干网络,定义一个额外的上采样卷积层。

最终卷积层

# self.final 是一个卷积层,用于生成最终的输出。它将高分辨率的特征图映射到类别数(num_classes)
self.final = nn.Conv2d(out_filters[0], num_classes, 1)
  • 定义一个最终的卷积层,将输出通道数转换为类别数。

前向传播方法

定义模型的前向传播过程,将输入数据通过网络的各层进行计算,最终生成输出。

def forward(self, inputs):
# 根据 self.backbone 的值,选择不同的模型(VGG 或 ResNet-50)进行前向传播。# 通过卷积层和池化层对输入数据进行处理,得到特征图 feat1、feat2、feat3、feat4 和 feat5if self.backbone == "vgg":[feat1, feat2, feat3, feat4, feat5] = self.vgg.forward(inputs)elif self.backbone == "resnet50":[feat1, feat2, feat3, feat4, feat5] = self.resnet.forward(inputs)
# 通过上采样操作将这些特征图进行级联,得到更高分辨率的特征图 up4、up3、up2 和 up1up4 = self.up_concat4(feat4, feat5)up3 = self.up_concat3(feat3, up4)up2 = self.up_concat2(feat2, up3)up1 = self.up_concat1(feat1, up2)
# 如果存在上采样卷积层 self.up_conv,则对 up1 进行进一步处理if self.up_conv != None:up1 = self.up_conv(up1)
# 通过 self.final 层获得最终的输出final = self.final(up1)return final
  • 根据选择的骨干网络,获取不同层的特征图。
  • 使用上采样模块逐层上采样并结合特征图。
  • 如果定义了额外的上采样卷积层,则应用该层。
  • 最终通过一个卷积层生成输出。

冻结和解冻骨干网络

def freeze_backbone(self):if self.backbone == "vgg":for param in self.vgg.parameters():param.requires_grad = Falseelif self.backbone == "resnet50":for param in self.resnet.parameters():param.requires_grad = Falsedef unfreeze_backbone(self):if self.backbone == "vgg":for param in self.vgg.parameters():param.requires_grad = Trueelif self.backbone == "resnet50":for param in self.resnet.parameters():param.requires_grad = True
  • freeze_backbone 方法用于冻结骨干网络的参数,使其在训练过程中不更新。
  • unfreeze_backbone 方法用于解冻骨干网络的参数,使其在训练过程中可以更新。

冻结或解冻神经网络模型的特定层–更好地进行迁移学习或微调

  1. 迁移学习

    • 在迁移学习中,使用一个预训练的神经网络模型(通常在大规模数据集上进行训练)来解决新的任务。
    • 通过冻结模型的底层层(例如卷积层),可以保留其在原始任务上学到的特征表示,然后在新任务上进行微调。
    • 这样做有助于避免在新任务上过拟合,并且可以加快训练速度。
  2. 微调

    • 微调是指在预训练模型的基础上继续训练,以适应新任务的特定数据。
    • 解冻底层层,允许其权重在新任务上进行调整,以更好地适应新数据。
    • 通常,我们只微调模型的一部分,而不是整个模型,以避免丢失预训练模型的有用特征。

完整代码

import torch
import torch.nn as nnfrom nets.resnet import resnet50
from nets.vgg import VGG16class unetUp(nn.Module):def __init__(self, in_size, out_size):super(unetUp, self).__init__()self.conv1 = nn.Conv2d(in_size, out_size, kernel_size=3, padding=1)self.conv2 = nn.Conv2d(out_size, out_size, kernel_size=3, padding=1)self.up = nn.UpsamplingNearest2d(scale_factor=2)self.relu = nn.ReLU(inplace=True)def forward(self, inputs1, inputs2):outputs = torch.cat([inputs1,self.up(inputs2)],1)outputs = self.conv1(outputs)outputs = self.relu(outputs)outputs = self.conv2(outputs)outputs = self.relu(outputs)return outputs
class Unet(nn.Module):def __init__(self, num_classes = 2, pretrained = False, backbone = 'vgg'):super(Unet, self).__init__()if backbone == 'vgg':self.vgg = VGG16(pretrained=pretrained)in_filters = [192, 384, 768, 1024]elif backbone == 'resnet50'self.resnet = resnet50(pretrained=pretrained)in_filters = [192, 512, 1024, 3072]else:raise ValueError('Unsupported backbone -`{}`, Use vgg, resnet50.'.format(backbone))out_filters = [64, 128, 256, 512]#???self.up_concat4 = unetUp(in_filters[3], out_filters[3])self.up_concat3 = unetUp(in_filters[2], out_filters[2])self.up_concat2 = unetUp(in_filters[1], out_filters[1])self.up_concat1 = unetUp(in_filters[0], out_filters[0])if backbone == 'resnet50':self.up_conv = nn.Sequential(nn.UpsamplingNearest2d(scale_factor=2),nn.Conv2d(out_filters[0],out_filters[0], kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(out_filters[0], out_filters[0], kernel_size=3, padding=1),nn.ReLU(),)else:self.up_conv = Noneself.final = nn.Conv2d(out_filters[0], num_classes, 1)self.backbone = backbonedef forward(self, inputs):if self.backbone == "vgg":[feat1, feat2, feat3, feat4, feat5] = self.vgg.forward(inputs)elif self.backbone == "resnet50":[feat1, feat2, feat3, feat4, feat5] = self.resnet.forward(inputs)up4 = self.up_concat4(feat4, feat5)up3 = self.up_concat3(feat3, up4)up2 = self.up_concat2(feat2, up3)up1 = self.up_concat1(feat1, up2)if self.up_conv != None:up1 = self.up_conv(up1)final = self.final(up1)return finaldef freeze_backbone(self):if self.backbone == "vgg":for param in self.vgg.parameters():param.requires_grad = Falseelif self.backbone == "resnet50":for param in self.resnet.parameters():param.requires_grad = Falsedef unfreeze_backbone(self):if self.backbone == "vgg":for param in self.vgg.parameters():param.requires_grad = Trueelif self.backbone == "resnet50":for param in self.resnet.parameters():param.requires_grad = True

相关文章:

深度学习--图像分割UNet介绍及代码分析

UNet介绍 参考UNet网络介绍整体架构UNet过程输入编码器(下采样)中间特征表示解码器(上采样)输出 代码详解unetUP和Unet关系上采样模块——unetUp用于图像分割的卷积神经网络(CNN)架构模块——Unet类的定义初…...

接了一个2000块的小活,大家进来看看值不值,附源码

如题,上周的一天,朋友圈的一个旧友找到了我,说让我帮他开发一个小工具,虽然活不大,但没个几年的全栈经验还不一定能接下来,因为麻雀虽小,涉及的内容可不少: 需求分析 原型设计 详细…...

基于MindFormers实现GPT2模型的推理

前言 针对MindFormers的安装,可参考本专栏里的另一篇博客 安装MindFormers(昇腾910)-CSDN博客 pipeline方式 from mindformers import pipeline from mindformers import GPT2LMHeadModel, GPT2Config, GPT2Tokenizer tok GPT2Tokenizer…...

探索腾讯云AI代码助手:智能编程的新时代

智能编程的新时代 前言开发环境介绍腾讯云 AI 代码助手使用实例生成文档解释代码生成测试修复代码人工智能技术对话 智能编程获得的帮助与提升对腾讯云AI代码助手的建议结语 前言 hello,大家好我是恒川,今天我来给大家安利一款非常好用的AI 代码助手&…...

MySQL 之 MHA 高可用架构详解

这个是在内部分享做的一个 Keynote 动画,用来演示 MHA 高可用架构及发生故障时的 Failover。动画如下: 数据库相关分享之 MySQL 的 MHA 架构详解 引言 MySQL 数据库在企业和应用中扮演着举足轻重的角色,其稳定性和可靠性对于业务的连续运行至…...

WangEditor自定义新元素,并解决自定义元素中换行无法消除样式的问题

一、背景概述 项目有自定义样式模板的需求,WangEditor没有。若直接把样式的html插入WangEditor中,无法解析,且会被自动过滤。因此,需要基于WangEditor提供的API进行二次开发。 例如,需要新增以下样式: 该…...

VBA Excel口算题

口算题函数 利用随机数写个20以内加减法口算题函数 Function Kousuan()Dim intOne As IntegerDim intTwo As IntegerDim strFlg As StringDim intFlg As IntegerDim strRtn As StringintFlg Application.WorksheetFunction.RandBetween(0, 1)strFlg "-"If intFlg…...

C++理解临时对象的来源

当程序员之间进行交谈时&#xff0c;他们经常把仅仅需要一小段时间的变量称为临时变量。例如在下面这段swap(交换)例程里&#xff1a; template<class T> void swap(T& object1, T& object2) { T temp object1; object1 object2; object2 temp; } 通常把t…...

C++协助完成返回值优化

一个返回对象的函数很难有较高的效率&#xff0c;因为传值返回会导致调用对象内的构造和析构函数(参见条款M19)&#xff0c;这种调用是不能避免的。问题很简单&#xff1a;一个函数要么为了保证正确的行为而返回对象要么就不这么做。如果它返回了对象&#xff0c;就没有办法摆脱…...

2024年睿抗机器人开发者大赛(RAICOM)国赛题解

目录 RC-u1 大家一起查作弊 分数 15 RC-u2 谁进线下了&#xff1f;II 分数 20 RC-u3 势均力敌 分数 25 RC-u4 City 不 City 分数 30 RC-u5 贪心消消乐 分数 30 RC-u1 大家一起查作弊 分数 15 简单模拟题&#xff0c;对于多行读入使用while(getline(cin…...

声明式UI语法

一、ArkTS的基本组成 Entry // 装饰器 Component // 装饰器 struct Hello { // 自定义组件State myText: string World;build() { // UI描述Column() { // 系统组件Text(Hello ${this.myText}).fontSize(50)Divider()Button(Click me).onClick(() > { // 事件方法t…...

JDBC连接数和1521连接数之间的区别和联系(Java Database Connectivity)

JDBC&#xff08;Java Database Connectivity&#xff09;连接数和1521连接数之间的区别和联系如下&#xff1a; 区别 概念不同&#xff1a; JDBC连接数&#xff1a;指通过JDBC技术建立的数据库连接数。JDBC是Java中的一套API&#xff0c;用于连接和操作关系数据库。JDBC连接数…...

Leetcode - 136双周赛

目录 一&#xff0c;3238. 求出胜利玩家的数目 二&#xff0c;3239. 最少翻转次数使二进制矩阵回文 I 三&#xff0c;3240. 最少翻转次数使二进制矩阵回文 II 四&#xff0c;3241. 标记所有节点需要的时间 一&#xff0c;3238. 求出胜利玩家的数目 本题直接暴力求解&#x…...

SQLite ORDER BY 语句

SQLite ORDER BY 语句 SQLite 的 ORDER BY 语句用于对查询结果进行排序。排序可以是升序&#xff08;ASC&#xff09;或降序&#xff08;DESC&#xff09;。默认情况下&#xff0c;如果不指定排序方式&#xff0c;ORDER BY 会以升序对结果进行排序。 语法 SQLite ORDER BY 语…...

MTK Android12 系统中应用加载 .so 文件的问题分析

在本篇博客中,我将详细总结在 Android 12 系统上进行的几个实验,包括如何加载自定义 JAR 文件、如何解压和确认 .so 文件,以及如何验证系统报错提示。本文将介绍使用 PathClassLoader 和 DexClassLoader 动态加载类的实验,分析系统报错信息,并最终得出结论。 推荐:《Andr…...

bpmn简单使用(制作流程图)

1、先下载依赖&#xff0c;下面是我下载的版本 "bpmn-io/properties-panel": "^3.23.0", "bpmn-js": "^17.9.1", "bpmn-js-properties-panel": "^5.6.1", "camunda-bpmn-moddle": "^7.0.1",…...

【算法模板】算竞技巧:Python对拍数据生成

在计算机编程竞赛中&#xff0c;对拍&#xff08;Testlib&#xff09;是一种验证程序正确性的方法。它通常用于检查一个程序的输出是否与另一个程序的输出一致&#xff0c;以确保程序的正确性。 对拍程序 【算法模板】算竞技巧&#xff1a;对拍全解_算法竞赛对拍-CSDN博客 #i…...

计算机基本理论与程序运行原理概述

目录 计算机的基本表示方法 计算机的组成 程序运行的原理 指令执行的流水线 编译原理 个人理解 面试题总结 计算机的基本表示方法 计算机系统使用高、低电平来表示逻辑1和0。数据在计算机中的存储、传输和处理均以二进制形式进行。数据通过总线作为电信号进行传输&…...

SpringBoot中的server.context-path

目录 一、问题引入 二、代码片段展示 2.1.接口层 2.2.application.properties 三、问题分析 3.1.server.context-path 作用 3.2.正确展示 四、HTTP请求响应码简介 4.1.响应码参考来源 4.2.源码示例 4.2.1.源码总述 4.2.2.正常情况——2XX: generally "OK&…...

AI绘画绘画 Stable Diffusion ,从零开始轻松变现,AI绘画副业创收指南,一天一个AI帮你赚钱小技巧!

大家好&#xff0c;我是灵魂画师向阳 通过长达几个月的AI绘画Stable Diffusion 系统教程&#xff0c;相信大家已经对AI绘画有了一个大概的认知。最近就有很多粉丝总是问我&#xff0c;AI绘画学会后如何进行变现&#xff0c;或者是做副业呢&#xff1f; 那今天我就分享一些目前…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...