【基于 PyTorch 的 Python 深度学习】6 视觉处理基础:卷积神经网络(1)

前言

文章性质:学习笔记 📖

学习资料:吴茂贵《 Python 深度学习基于 PyTorch ( 第 2 版 ) 》【ISBN】978-7-111-71880-2

主要内容:根据学习资料撰写的学习笔记,该篇主要介绍了卷积神经网络的卷积层部分。

预:从全连接层到卷积层

使用多层感知机网络来处理图像存在的不足

1)把图像展平为向量,极易丢失图像的部分固有属性;

2)使用全连接层极易导致参数量呈指数级增长。

图像最具代表性的两个特征:

1)平移不变性:不管检测对象出现在图像中的哪个位置,神经网络的前面几层应该对相同的图像区域具有相似的反应。

2)局部性:神经网络的前面几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远的区域的关系。最终,在后续神经网络中,整个图像级别上可以集成这些局部特征用于预测。

一、卷积神经网络

卷积神经网络(Convolutional Neural Network, CNN)是一种前馈神经网络,由一个或多个卷积层和顶端的全连接层组成,同时包括关联权重和池化层等。图 6-1 是一个典型的卷积神经网络架构。

import torch
import torch.nn as nn
import torch.nn.functional as Fdevice = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")class CNNNet(nn.Module):def __init__(self):super(CNNNet, self).__init__()self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5, stride=1)self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)self.conv2 = nn.Conv2d(in_channels=16, out_channels=36, kernel_size=3, stride=1)self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)self.fc1 = nn.Linear(1296, 128)self.fc2 = nn.Linear(128, 10)def forward(self, x):x = self.pool1(F.relu(self.conv1(x)))x = self.pool2(F.relu(self.conv2(x)))# print(x.shape)x = x.view(-1, 36*6*6)x = F.relu(self.fc2(F.relu(self.fc1(x))))return xnet = CNNNet().to(device)

二、卷积层

卷积层是卷积神经网络的核心层,而卷积又是卷积层的核心。卷积,直观理解就是两个函数的一种运算,也被称为 卷积运算

卷积核窗口从输入张量的左上角开始,从左到右、从上到下滑动。当卷积核窗口滑动到新的位置时,包含在该窗口中的部分张量与卷积核张量按元素相乘,再将得到的张量求和得到一个单一的标量值。 

说明:输入矩阵 \left ( X_{w}, X_{h} \right ) 与卷积核  \left ( K_{w}, K_{h} \right ) 运算后的输出矩阵的形状为 \left ( X_{w}-K_{w}+1, X_{h}-K_{h}+1 \right )

用 PyTorch 代码实现卷积运算过程:

import torch"""定义卷积运算函数"""
def cust_conv2d(X, K):# 获取卷积核形状h, w = K.shape# 初始化输出值 YY = torch.zeros((X.shape[0]-h+1, X.shape[1]-w+1))# 实现卷积运算for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i:i+h, j:j+w]*K).sum()return Y"""定义输入及卷积核"""
X = torch.tensor([[1.0, 1.0, 1.0, 0.0, 0.0], [0.0, 1.0, 1.0, 1.0, 0.0],[0.0, 0.0, 1.0, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0, 0.0], [0.0, 1.0, 1.0, 0.0, 0.0]])
K = torch.tensor([[1.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 1.0]])print(cust_conv2d(X, K))

1、卷积核

卷积核 也称为 过滤器 ,是整个卷积过程的核心,比较简单的卷积核有垂直卷积核 Horizontal Filter、水平卷积核 Vertical Filter、索贝尔卷积核 Sobel Filter 等。这些卷积核能够检测图像的水平边缘、垂直边缘,增强图像中心区域权重等。

卷积核的作用:检测垂直边缘,检测水平边缘,以及检测其他边缘特征。

关于如何确定卷积核:卷积核类似于标准神经网络中的权重矩阵 WW 需要通过梯度下降算法反复迭代所得。同样,在深度学习中,卷积核也需要通过模型训练所得。卷积神经网络的主要目的是计算出这些卷积核的数值。确定得到这些卷积核后,卷积神经网络的浅层网络也就实现了对图像所有边缘特征的检测。

【代码实操】取图 6-7 为例,给定输入 X 及 输出 Y ,根据卷积运算,通过多次迭代,可以得到卷积核的近似值。

import torch
from torch import nn"""定义输入和输出"""
X = torch.tensor([[10., 10., 10., 0.0, 0.0, 0.0], [10., 10., 10., 0.0, 0.0, 0.0], [10., 10., 10., 0.0, 0.0, 0.0],[10., 10., 10., 0.0, 0.0, 0.0], [10., 10., 10., 0.0, 0.0, 0.0], [10., 10., 10., 0.0, 0.0, 0.0]])
Y = torch.tensor([[0.0, 30., 30., 0.0], [0.0, 30., 30., 0.0], [0.0, 30., 30., 0.0], [0.0, 30., 30., 0.0]])"""训练卷积层"""
conv2d = nn.Conv2d(1, 1, kernel_size=(3, 3), bias=False)
# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度)
X = X.reshape((1, 1, 6, 6))
Y = Y.reshape((1, 1, 4, 4))
lr = 0.001# 定义损失函数
loss_fn = nn.MSELoss()
for i in range(400):Y_pre = conv2d(X)loss = loss_fn(Y_pre, Y)conv2d.zero_grad()loss.backward()# 迭代卷积核conv2d.weight.data[:] -= lr * conv2d.weight.gradif (i+1) % 100 == 0:print(f'epoch {i+1}, loss: {loss.item():.4f}')"""查看卷积核"""
print(conv2d.weight.data.reshape((3, 3)))

2、步幅

步幅 strides 就是卷积核在输入矩阵中每次移动的格数,在图像中就是跳过的像素个数。

在小窗口移动过程中,卷积核的值始终保持不变,即卷积核的值在整个过程中是共享的,称其为 共享变量 。卷积神经网络采用参数共享的方法大大降低了参数的数量。在用 PyTorch 实现时,strides 参数格式为单个整数或两个整数的元组。

3、填充

当输入图像与卷积核不匹配或卷积核超过图像边界时,可以采用边界填充的方法,即对图像尺寸进行扩展,扩展区域补零。补零填充 zero padding 对于图像边缘部分的特征提取是很有帮助的,可以防止信息丢失。

根据是否扩展可将填充方式分为 SameValid 两种。采用 Same 时,对图像扩展并补零;采用 Valid 时,不对图像进行扩展。在实际训练过程中,通常选择 Same 方式,因为使用这种方式不会丢失信息。

假设填充零的圈数为 p ,输入数据大小为 n ,卷积核大小为 f ,步幅大小为 s ,则有:p=\frac{f-1}{2},卷积后的大小:\frac{n+2p-f}{s}+1 。

4、多通道上的卷积

前面对卷积在输入数据、卷积核的维度上进行了扩展,但输入数据、卷积核都是单一的。从图像的角度来说,二者都是灰色的,没有考虑彩色图像的情况。在实际应用中,输入数据往往是多通道的,如彩色图像是 3 通道,即 R 、G 、B 通道。

(1)多输入通道

3 通道图像 的卷积运算和单通道图像的卷积运算基本一致,对于 3 通道的 RGB 图像,其对应的卷积核算子同样也是 3 通道的。例如图 6-14 中的输入图像是 3×5×5 的,3 个维度分别表示 通道数 channel高度 height宽度 width 。卷积过程就是将每个单通道与对应的卷积核进行卷积运算,然后将 3 通道的和相加,得到输出图像的一个像素值。

用 PyTorch 代码实现卷积运算过程:

import torch"""定义卷积运算函数"""
def cust_conv2d(X, K):# 获取卷积核形状h, w = K.shape# 初始化输出值 YY = torch.zeros((X.shape[0]-h+1, X.shape[1]-w+1))# 实现卷积运算for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i:i+h, j:j+w]*K).sum()return Y"""定义多输入通道卷积运算函数"""
def conv2d_multi_in(X, K):h, w = K.shape[1], K.shape[2]value = torch.zeros(X.shape[0]-h+1, X.shape[1]-w+1)for x, k in zip(X, K):value = value + cust_conv2d(x, k)return value"""定义输入数据"""
X = torch.tensor([[[1., 0., 1., 0., 2.], [1, 1, 3, 2, 1], [1, 1, 0, 1, 1], [2, 3, 2, 1, 3], [0, 2, 0, 1, 0]],[[1., 0., 0., 1., 0.], [2, 0, 1, 2, 0], [3, 1, 1, 3, 0], [0, 3, 0, 3, 2], [1, 0, 3, 2, 1]],[[2., 0., 1., 2., 1.], [3, 3, 1, 3, 2], [2, 1, 1, 1, 0], [3, 1, 3, 2, 0], [1, 1, 2, 1, 1]]])
K = torch.tensor([[[0., 1., 0.], [0, 0, 2], [0, 1, 0]],[[2., 1., 0.], [0, 0, 0], [0, 3, 0]],[[1., 0., 0.], [1, 0, 0], [0, 0, 2]]])print(conv2d_multi_in(X, K))

(2)多输出通道

为了实现更多边缘检测,可以增加更多 卷积核组 。不同卷积核组卷积得到不同的输出,个数由卷积核组决定。

(3)1×1 卷积核

1×1 卷积核 在很多经典网络结构中都有使用,例如 Inception 网络、ResNet 网络、YOLO 网络和 Swin-Transformer 网络等。

在网络中增加 1×1 卷积核的主要作用:

增加或降低通道数:如果卷积的输入输出都只是一个二维数据,那么 1×1 卷积核意义不大,它完全不考虑像素与周边其他像素之间的关系。但如果卷积的输入输出是多维矩阵,则可以通过 1×1 卷积核不同的通道数,增加或降低卷积后的通道数。

增加非线性:1×1 卷积核利用后接的非线性激活函数,可以在保持特征图尺度不变的前提下大幅增加非线性特性,使网络更深,同时提升网络的表达能力。

跨通道信息交互:使用 1×1 卷积核可以增加或降低通道数,也可以组合来自不同通道的信息。

图 6-17 为通过 1×1 卷积核改变通道数的示例:

用 PyTorch 代码实现卷积运算过程:

import torch"""生成输入及卷积核数据"""
X = torch.tensor([[[1, 2, 3], [4, 5, 6], [7, 8, 9]],[[1, 1, 1], [1, 1, 1], [1, 1, 1]],[[2, 2, 2], [2, 2, 2], [2, 2, 2]]])
K = torch.tensor([[[[1]], [[2]], [[3]]],[[[4]], [[1]], [[1]]],[[[5]], [[3]], [[3]]]])print(K.shape)  # torch.Size([3, 3, 1, 1])"""定义卷积运算函数"""
def cust_conv2d(X, K):# 获取卷积核形状h, w = K.shape# 初始化输出值 YY = torch.zeros((X.shape[0]-h+1, X.shape[1]-w+1))# 实现卷积运算for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i:i+h, j:j+w]*K).sum()return Y"""定义多输入通道卷积运算函数"""
def conv2d_multi_in(X, K):h, w = K.shape[1], K.shape[2]value = torch.zeros(X.shape[0]-h+1, X.shape[1]-w+1)for x, k in zip(X, K):value = value + cust_conv2d(x, k)return value"""定义卷积函数"""
def conv2d_multi_in_out(X, K):return torch.stack([conv2d_multi_in(X, k) for k in K])print(conv2d_multi_in_out(X, K))

5、激活函数

卷积神经网络与标准的神经网络类似,为了保证非线性,也需要使用 激活函数 ,即在卷积运算后,把输出值另加偏移量输入激活函数,作为下一层的输入。

常用的激活函数有 torch.nn.functional.sigmoid、torch.nn.functional.relu、torch.nn.functional.softmax、torch.nn.functional.tanh、torch.nn.functional.dropout 等。类对象方式的激活函数有 torch.nn.Sigmoid、torch.nn.ReLU、torch.nn.Softmax、torch.nn.Tanh、torch.nn.Dropout 等。

6、卷积函数

卷积函数 是构建神经网络的重要支架,通常 PyTorch 的卷积运算是通过 nn.Conv2d 来完成的。

(1)nn.Conv2d 函数

nn.Conv2d (in_channels: int,out_channels: int,kernel_size: Union[int, Tuple[int, int]],stride: Union[int, Tuple[int, int]] = 1,padding: Union[int, Tuple[int, int]] = 0,dilation: Union[int, Tuple[int, int]] = 1,groups: int = 1,bias: bool = True,padding_mode: str = 'zeros',
)

 主要参数说明:

参数说明
in_channels(int)输入信号的通道
out_channels(int)卷积产生的通道
kernel_size(int or tuple)卷积核的尺寸
stride(int or tuple, optional)卷积步长
padding(int or tuple, optional)输入的每一条边补充 0 的层数
dilation(int or tuple, optional)卷积核元素之间的间距
groups(int, optional)控制输入和输出之间的连接
bias(bool, optional)如果 bias=True 则添加偏置
padding_mode可选模式:zeros、reflect、replicate、circular

说明:当 group=1 时,输出是所有的输入的卷积;当 group=2 时,相当于有并排的两个卷积层,每个卷积层计算输入通道的一半,并且产生的输出是输出通道的一半,随后将这两个输出连接起来。 在 bias 中,参数 kernel_size、stride、padding、dilation 可以是整型数值 int ,此时卷积的 height 和 width 值相同,也可以是 tuple 数组,第一维度表示 height 值,第二维度表示 width 值。

(2)输出形状

卷积函数 nn.Conv2d 参数中输出形状的计算公式:

Input:(N, C_{in}, H_{in}, W_{in})

Output:(N, C_{out}, H_{out}, W_{out})

H_{out}=\frac{H_{in}+2\times padding[0]-dilation[0]\times (kernel\, size[0]-1)-1}{stride[0]}+1

 W_{out}=\frac{W_{in}+2\times padding[1]-dilation[1]\times (kernel\, size[1]-1)-1}{stride[1]}+1

weight:(out_channels, in_channels/groups, kernel_size[0], kernel_size[1])

import torch
import torch.nn as nn"""当 groups=1 时"""
conv = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=1, groups=1)
conv.weight.data.size()  # torch.Size([12, 6, 1, 1])
print(conv.weight.data.size())"""当 groups=2 时"""
conv = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=1, groups=2)
conv.weight.data.size()  # torch.Size([12, 3, 1, 1])
print(conv.weight.data.size())"""当 groups=3 时"""
conv = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=1, groups=3)
conv.weight.data.size()  # torch.Size([12, 2, 1, 1])
print(conv.weight.data.size())

7、转置卷积

转置卷积 Transposed Convolution 在某些文献中也称为反卷积 Deconvolution 或部分跨越卷积 Fractionally-strided Convolution 。

通过卷积的正向传播的图像通常会越来越小,类似于下采样。卷积的反向传播实际上就是一种转置卷积,类似于上采样。

我们先来简单回顾卷积的正向传播,假设卷积操作的输入大小 n 为 4 ,卷积核大小 f 为 3 ,步幅 s 为 1 ,填充 p 为 0 。 

对于上述卷积运算,我们将 3×3 卷积核展平为 [4,16] 的稀疏矩阵 C

我们再将 4×4 的输入特征展平为 [16,1] 的矩阵 X ,那么 Y = CX 将是 [4,1] 的输出特征矩阵,将其重新排列成 2×2 的输出特征。

那么反向传播时又会如何呢?假设损失函数为 L ,则反向传播时,可以利用链式法则得到对 L 关系的求导:

\frac{\partial L}{\partial x_{j}}=\sum_{i}\frac{\partial L}{\partial y_{i}}\frac{\partial y_{i}}{\partial x_{j}}=\sum_{i}\frac{\partial L}{\partial y_{i}}C_{i,j}=\frac{\partial L}{\partial y}C_{*,j}=C_{*,j}^{T}\frac{\partial L}{\partial y}

由此,可得 X=C^{T}Y ,即反卷积就是要对这个矩阵运算过程进行逆运算。转置卷积主要用于生成式对抗网络 GAN 。

PyTorch 中二维转置卷积的格式为:

torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')

8、特征图与感受野

输出的卷积层有时被称为 特征图 Feature Map ,因为它可以被视为一个输入映射到下一层的空间维度的转换器。在 CNN 中,对于某一层的任意元 x ,其 感受野 Receptive Field 是指在正向传播期间可能影响 x 计算的所有元素(来自所有先前层)。

感受野的覆盖率可能大于某层输入的实际区域大小。感受野的定义是卷积神经网络每一层输出的特征图上的像素点在输入图像上映射的区域大小。再通俗点的解释是,感受野是特征图上的一个点对应输入图上的区域。

由图可知,经过几个卷积层后,特征图逐渐变小,一个特征所表示的信息量变多,如 s_{3} 表示了 x_{1} 、x_{2} 、x_{3}  、x_{4}  、x_{5} 的信息。

9、全卷积网络

利用卷积神经网络进行图像分类或回归任务时,我们通常会在卷积层之后接上若干个全连接层,将卷积层产生的特征图映射成一个固定长度的特征向量。因为最终都期望得到整个输入图像属于哪类对象的概率值,如图 6-22 所示,AlexNet 的 ImageNet 模型输出一个 1000 维的向量表示输入图像属于每一类的概率(经过 softmax 归一化)。

与通常用于分类或回归任务的卷积神经网络不同,全卷积网络 Fully Convolutional Network 可以接收任意尺寸的输入图像,将上图中的 3 个全连接层改成卷积核尺寸为 1×1,通道数为向量长度的卷积层。然后,采用转置卷积运算对最后一个卷积层的特征图进行上采样,使其恢复到与输入图像相同的尺寸,从而可以对每个像素都产生一个预测,同时保留原始输入图像中的空间信息。接着在上采样的特征图上进行逐像素分类,最后逐个像素计算分类的损失,相当于每一个像素对应一个训练样本。这样整个网络都使用卷积层,没有全连接层,这也许就是全卷积网络名称的由来。该网络的输出类别预测与输入图像在像素级别上具有一一对应关系,其通道维度的输出为该位置对应像素的类别预测,如图 6-23 所示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/325128.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity ui 同屏

一共有三个摄像机,上屏,下屏 和 类似照相机的ccamera 类似照相机的ccamera的设置: 下屏摄像机设置: 下屏交互的Canvas设置: 新建一个canvas,下面放上rawimage: 如果下屏不想显示的内容&#xf…

2024蓝桥杯RSA-Theorem

方法1:直接使用工具yafu解题 yafu的使用方法 安装:解压后直接使用即可,在文件包内,执行命令终端,输入命令行 1、如果数比较小,进入该文件的目录后可以直接使用: yafu-x64 factor(n) 如果是powershell&…

Maven 的仓库、周期和插件

优质博文:IT-BLOG-CN 一、Maven 仓库 在Maven的世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构建。Maven在某个统一的位置存储所有项目的共享的构建,这个统一的位置,我们就称之为仓库。任何的构建都有唯一…

计算机视觉——基于改进UNet图像增强算法实现

1. 引言 在低光照条件下进行成像非常具有挑战性,因为光子计数低且存在噪声。高ISO可以用来增加亮度,但它也会放大噪声。后处理,如缩放或直方图拉伸可以应用,但这并不能解决由于光子计数低导致的低信噪比(SNR&#xff…

深度学习——前馈全连接神经网络

前馈全连接神经网络 1.导入需要的工具包2.数据导入与数据观察(1)读取csv的文件信息:(2)训练数据前5行(3)打印第一个图(4)观察数据中的信息(5)查看…

stm32——OLED篇

技术笔记! 一、OLED显示屏介绍(了解) 1. OLED显示屏简介 二、OLED驱动原理(熟悉) 1. 驱动OLED驱动芯片的步骤 2. SSD1306工作时序 三、OLED驱动芯片简介(掌握) 1. 常用SSD1306指令 2. …

[Kotlin]创建一个私有包并使用

1.创建Kotlin测试项目 在Android Studio或其他IDE中选择“Create New Project”。选择Kotlin和Gradle作为项目类型和构建系统。指定项目名称和位置,完成设置。 2.创建Android Library模块 官方文档:创建 Android 库 | Android Studio | Android De…

图片转word如何转换?

要将图片转换为Word文档,你可以使用以下方法之一: 以上这些方法都可以帮助你将图片中的文本转换为可编辑的Word文档,你可以根据自己的喜好和需求选择其中一种方法来操作。 使用OCR软件或在线工具:有许多OCR(Optical Ch…

2024年怎样提取小程序里的视频

在未来的2024年,我们亲眼目睹了科技的飞速发展和互联网的无限可能。在这个数字化世界中,小程序已经成为我们日常生活中不可或缺的一部分,无论是购物、学习,还是娱乐,小程序都给我们带来了前所未有的便利。然而&#xf…

【OceanBase诊断调优】—— 租户资源统计项及其查询方法

本文主要介绍 OceanBase 数据库中租户资源统计项及其查询方法。 适用版本 OceanBase 数据库 V4.1.x、V4.2.x 版本。 CPU 资源统计项 逻辑 CPU 使用率(线程处理请求的时间占比)。 通过虚拟表 __all_virtual_sysstat 在 SYS 系统租户下,查看…

棱镜七彩参编《网络安全技术 软件供应链安全要求》国家标准发布

据全国标准信息公共服务平台消息显示,《网络安全技术 软件供应链安全要求》(GB/T 43698-2024)国家标准已于2024年4月25日正式发布,并将于2024年11月1日正式实施。棱镜七彩作为主要编制单位之一参与该国家标准的编制,为…

Linux下安装mysql8.0(以rpm包安装)

前言:原文在我的博客网站中,持续更新数通、系统方面的知识,欢迎来访! Linux下安装mysql8.0(以rpm包安装)https://myweb.myskillstree.cn/125.html 目录 1、查操作系统信息 2、下载mysql 8.0.34的rpm包 …

7.STL_string(详细)

1. 什么是STL STL(standard template libaray-标准模板库):是C标准库的重要组成部分,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架。 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版…

org.springframework.jdbc.BadSqlGrammarException

Cause: java.sql.SQLSyntaxErrorException: Table ‘web.emp’ doesn’t exist 产生原因:web表找不到,所以可能数据库配置错误 spring.datasource.urljdbc:mysql://localhost:3306/web02 更改完成后运行成功

抽空学学go

2024年5月9日11:14:24 学习go 看课8小时转职Golang工程师(如果你想低成本学习Go语言)_哔哩哔哩_bilibili 文档8小时转职Golang工程师 (yuque.com) 1.安装go 2024年5月9日11:27:16 2.安装 vscode go配置环境 vs code配置go开发环境 (zhihu.com) vscode里面配置代理&#xf…

BGP综合实验

一.实验拓扑图 二.实验思路 1.划分网段配置IP地址 2.在AS 2内部配置OSPF协议,整个配置BGP协议(将R3,R6作为反射器,防止水平分割使R4、R7、R8学习不到宣告进的网段) 3.手工路由聚合,减少路由条目&#xf…

Curator分布式锁

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 分布式锁服务宕机,…

【GlobalMapper精品教程】079:投影坐标系转地理坐标系(UTM转WGS1984/2000)

文章目录 一、矢量UTM转WGS1984/20001. UTM转WGS19842. UTM转CGCS2000二、栅格UTM转WGS1984/2000一、矢量UTM转WGS1984/2000 加载配套实验数据(data079.rar)中的矢量数据,如下所示: 查看源坐标系:双击图层的,图层投影选项卡,为UTM投影,Zone48N。 设置系统坐标系:点击…

【JavaEE网络】HTTPS详解:从对称与非对称加密到证书认证

目录 HTTPSHTTPS 是什么“加密” 是什么HTTTPS 的工作过程引入对称加密引入非对称加密引入证书完整流程总结 HTTPS HTTPS 是什么 HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现…

【JVM】ASM开发

认识ASM ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。 ASM可以直接产生二进制class文件,也可以在类被加载入虚拟机之前动态改变类行为,ASM从类文件中读入信息后能够改变类行为,分析类信息&#xff…