当前位置: 首页 > 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 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...