【卷积神经网络】卷积层详解【数学+python代码】

news2024/9/26 1:17:39

1、简介

学习目标:

  • 掌握卷积计算过程
  • 掌握特征图大小计算方法
  • 掌握PyTorch卷积层API

基本概念:
在计算机视觉领域,往往我们输入的图像都很大,使用全连接网络的话,计算的代价较高。

另外图像也很 难保留原有的特征 ,导致图像处理的准确率不高。

卷积神经网络(Convolutional Neural Network)是含有 卷积层 的神经网络;

卷积层的作用就是用来自动学习、提取图像的特征

CNN网络主要有三部分构成:卷积层、池化层和全连接层构成;

卷积层负责提取图像中的局部特征;
池化层用来大幅降低参数量级(降维);
全连接层类似人工神经网络的部分,用来输出想要的结果。

关于卷积层的python的API,提取表格如下:

API参数说明
nn.Conv2din_channels输入通道数,如 RGB 图像有 3 个通道,RGBA 图像有 4 个通道。
out_channels输出通道数,即卷积核的数量,决定输出特征图的深度。
kernel_size卷积核的大小,可以是单个整数(如 3 表示 3x3)或元组(如 (3, 3))。
stride卷积操作的步幅,默认值为 1。
padding填充方式,默认值为 0,表示不填充。
torch.tensordata输入数据,通常是一个数组或图像数据。
permutedims重新排列张量的维度顺序,如 permute(2, 0, 1) 将 (H, W, C) 变为 (C, H, W)。
unsqueezedim在指定位置插入一个维度,如 unsqueeze(0) 在第 0 维度插入一个新维度。
squeezedim删除指定位置的单维度,如 squeeze(0) 删除第 0 维度。
detach分离张量,使其不再跟踪梯度。
numpy将 PyTorch 张量转换为 NumPy 数组。

接下来,学习卷积核的计算过程,即:卷积核如何提取特征

2、卷积计算

  1. input 表示输入的图像
  2. filter 表示 卷积核,也叫做 滤波器
  3. input 经过 filter 的得到输出为最右侧的图像,该图叫做 特征图

那么, 它是如何进行计算的呢?卷积运算本质上就是在滤波器和输入数据的局部区域间做点积

左上角的点计算方法:

按照上面的计算方法可以得到最终的特征图为:

3、Padding

通过上面的卷积计算过程,我们发现最终的特征图比原始图像小很多,如果想要保持经过卷积后的图像大小不变, 可以在原图周围添加 padding(填充) 来实现。
这里通过添加一圈“0”来保证大小一致

以下是关于填充的详细解释:
1. 填充的目的:

  • 保持输入尺寸:在卷积操作中,不添加填充会导致输出特征图的尺寸减小。填充可以帮助保持输入图像和输出特征图的尺寸一致。
  • 中心像素处理:填充允许卷积核在图像边缘处理时仍然有足够的邻域像素,从而更好地处理边界特征。
  • 对齐:在构建深度网络时,填充可以确保不同层之间的特征图尺寸对齐,从而简化网络设计。

2. 填充的类型:
a. Valid Padding(无填充):
这种模式下,不对输入进行填充,卷积核只在原始输入图像内滑动。这会导致输出特征图的尺寸小于输入图像。
输出尺寸公式((输入尺寸 - 核尺寸) / 步长) + 1
b. Same Padding(相同填充):
这种模式下,填充使得卷积核可以完全覆盖输入图像,即输出特征图的尺寸与输入图像相同。
为了实现这一点,通常在输入图像的边界周围添加适当数量的零。
输出尺寸公式输入尺寸 / 步长
3. 填充的实现:
a. 零填充(Zero Padding):
最常见的填充方法是在输入图像的边界添加零值。这种方法简单易行,并且效果良好。
b. 镜像填充(Mirror Padding):
边界填充的像素是输入图像边界像素的镜像。这种方法有时可以减少边界效应,提高特征提取的效果。
c. 常数填充(Constant Padding):
用一个常数值填充输入图像的边界,可以是零以外的其他值。
d. 复制填充(Replication Padding):
边界填充的像素是输入图像边界最近的像素的复制。这种方法可以在某些情况下保留更多的图像特征。
5. 公式:
假设输入尺寸为 n × n n \times n n×n,卷积核尺寸为 k × k k \times k k×k,步长为 s s s,填充大小为 p p p
则输出特征图的尺寸为: [ 输出尺寸 = ( n + 2 p − k s ) + 1 ] [ \text{输出尺寸} = \left(\frac{n + 2p - k}{s}\right) + 1 ] [输出尺寸=(sn+2pk)+1]
6. 总结:
填充是卷积神经网络中一个关键的技术细节,它不仅影响输出特征图的尺寸,还影响卷积核对边界区域特征的提取效果。通过适当的填充,可以使卷积操作更灵活、更有效地提取图像特征。

4、Stride

Stride:步幅

按照步长为1来移动卷积核,计算特征图如下所示:

如果我们把 Stride 增大为2,也是可以提取特征图的,如下图所示:

Stride 在卷积操作中的作用:

  1. 影响输出尺寸:步幅会直接影响输出特征图的尺寸。较大的步幅会减少特征图的尺寸,因为滤波器每次移动时会跳过更多的像素。例如,在二维卷积中,如果输入图像的大小为 N × N N \times N N×N,滤波器的大小为 F × F F \times F F×F,步幅为 S S S,那么输出特征图的大小为: 输出宽度 = ⌊ N − F S + 1 ⌋ \text{输出宽度} = \left\lfloor \frac{N - F}{S} + 1 \right\rfloor 输出宽度=SNF+1

  2. 计算效率:较大的步幅可以减少计算量,因为需要处理的特征图像素变少了。这对于计算资源有限的情况或者需要加速推理的场景很有帮助。

  3. 信息损失:使用较大的步幅可能会导致输入图像中一些细节信息被忽略,因为滤波器在图像上跳过了更多的像素。这在某些任务中可能会降低模型的精度。

例子说明:
假设有一个 6 × 6 6 \times 6 6×6 的输入图像,一个 3 × 3 3 \times 3 3×3 的滤波器,步幅为 2。
卷积过程如下:

  • 滤波器首先覆盖输入图像的左上角,从 (0,0) 到 (2,2) 的区域。
  • 然后滤波器向右移动 2 个像素,覆盖从 (0,2) 到 (2,4) 的区域。
  • 接着,滤波器继续向右移动,直到覆盖完一行。
  • 然后滤波器向下移动 2 个像素,开始处理下一行。

这个过程会生成一个较小的输出特征图,因为每次滤波器移动的步长较大。
具体应用:

  • 图像识别:在卷积神经网络中,stride 经常用来控制特征图的尺寸。通过调整步幅,可以在保留重要特征的同时减少特征图的尺寸,从而降低计算复杂度。
  • 目标检测:在目标检测中,步幅的选择可以影响检测的精度和速度。较小的步幅可以捕捉到更多的细节,但计算量较大;较大的步幅可以加快检测速度,但可能会丢失一些细节信息。

总结:
Stride 是卷积神经网络中的一个重要参数,通过控制滤波器在输入图像上的移动步长,影响输出特征图的尺寸、计算效率和信息保留。
合理选择步幅是模型设计中的一个关键步骤,需要根据具体应用场景进行调整。

5、多通道卷积计算

实际中的图像都是多个通道组成的,我们怎么计算卷积呢?

计算方法如下:

  1. 当输入有多个通道(Channel), 例如 RGB 三个通道, 此时要求卷积核需要拥有相同的通道数
  2. 每个卷积核通道与对应的输入图像的各个通道进行卷积
  3. 将每个通道的卷积结果按位相加得到最终的特征图

如下图所示:

多通道卷积计算详解:
在卷积神经网络(CNN)中,多通道卷积是一个常见且重要的概念。它主要用于处理具有多个通道的输入数据,例如彩色图像的 RGB 三个通道。
1. 多通道卷积的概念:
假设我们有一个多通道输入图像,其大小为 H × W × D in H \times W \times D_{\text{in}} H×W×Din

其中 H H H 是图像的高度, W W W 是图像的宽度, D in D_{\text{in}} Din 是输入图像的通道数。

滤波器的大小为 F × F × D in F \times F \times D_{\text{in}} F×F×Din

其中 F F F 是滤波器的宽度和高度, D in D_{\text{in}} Din 与输入图像的通道数相同。

在多通道卷积中,每个滤波器不仅在空间上进行卷积操作,还会跨越输入图像的所有通道。
滤波器的每个通道会对应地与输入图像的每个通道进行卷积,然后将所有通道的卷积结果相加,形成单个输出特征图。
2. 计算步骤:
下面是详细的多通道卷积计算步骤:
输入与滤波器:

  • 输入图像大小为 H × W × D in H \times W \times D_{\text{in}} H×W×Din
  • 滤波器大小为 F × F × D in F \times F \times D_{\text{in}} F×F×Din
  • 假设我们有 N filters N_{\text{filters}} Nfilters 个滤波器

计算过程:

  1. 每个滤波器与输入图像的每个通道进行卷积:对于每个滤波器的每个通道 d d d d = 1 , 2 , . . . , D in d = 1, 2, ..., D_{\text{in}} d=1,2,...,Din),我们执行以下操作: conv ( I d , K d ) \text{conv}(I_d, K_d) conv(Id,Kd)其中, I d I_d Id 是输入图像的第 d d d 个通道, K d K_d Kd 是滤波器的第 d d d 个通道。
  2. 对通道进行求和:将上述卷积结果对所有通道进行求和,得到一个单通道输出特征图: O = ∑ d = 1 D in conv ( I d , K d ) O = \sum_{d=1}^{D_{\text{in}}} \text{conv}(I_d, K_d) O=d=1Dinconv(Id,Kd)
  3. 多滤波器操作:对于每个滤波器重复以上步骤,得到 N filters N_{\text{filters}} Nfilters 个输出特征图。最终的输出特征图大小为 H out × W out × N filters H_{\text{out}} \times W_{\text{out}} \times N_{\text{filters}} Hout×Wout×Nfilters,其中 H out H_{\text{out}} Hout W out W_{\text{out}} Wout 由输入图像大小、滤波器大小和步幅决定。

3. 数学表示:
假设输入图像大小为 H × W × D in H \times W \times D_{\text{in}} H×W×Din,滤波器大小为 F × F × D in F \times F \times D_{\text{in}} F×F×Din,步幅为 S S S,填充为 P P P,输出特征图的大小为 H out × W out H_{\text{out}} \times W_{\text{out}} Hout×Wout,则:
H out = ⌊ H − F + 2 P S ⌋ + 1 H_{\text{out}} = \left\lfloor \frac{H - F + 2P}{S} \right\rfloor + 1 Hout=SHF+2P+1
W out = ⌊ W − F + 2 P S ⌋ + 1 W_{\text{out}} = \left\lfloor \frac{W - F + 2P}{S} \right\rfloor + 1 Wout=SWF+2P+1
输出特征图的深度为滤波器的个数,即 N filters N_{\text{filters}} Nfilters
4. 示例:
假设输入图像大小为 6 × 6 × 3 6 \times 6 \times 3 6×6×3(RGB 图像),滤波器大小为 3 × 3 × 3 3 \times 3 \times 3 3×3×3,步幅为 1,没有填充(即 P = 0 P=0 P=0),有 2 个滤波器。
则输出特征图的大小为:
H out = ⌊ 6 − 3 + 2 ⋅ 0 1 ⌋ + 1 = 4 H_{\text{out}} = \left\lfloor \frac{6 - 3 + 2 \cdot 0}{1} \right\rfloor + 1 = 4 Hout=163+20+1=4
W out = ⌊ 6 − 3 + 2 ⋅ 0 1 ⌋ + 1 = 4 W_{\text{out}} = \left\lfloor \frac{6 - 3 + 2 \cdot 0}{1} \right\rfloor + 1 = 4 Wout=163+20+1=4
输出特征图的深度为 2。所以,最终输出特征图的大小为 4 × 4 × 2 4 \times 4 \times 2 4×4×2
5. 总结:
多通道卷积在处理多维数据(如彩色图像)时非常重要。
通过对每个通道进行卷积并累加结果,可以捕捉到更多的信息和特征。
这种计算方法在卷积神经网络中被广泛应用,尤其是在图像分类和目标检测等任务中。

6、多卷积核的卷积计算

上面的例子里我们只使用一个卷积核进行特征提取, 实际对图像进行特征提取时, 我们需要使用多个卷积核进行特征提取。
这个多个卷积核可以理解为从不同到的视角、不同的角度对图像特征进行提取。
那么,当使用多个卷积核时,应该怎么进行特征提取呢?

堆叠特征图:

  • 生成的特征图在深度维度上堆叠,形成一个单一的输出张量。
  • 在这个例子中,输出张量的维度是 3x3x2,其中 3x3 是空间尺寸,2 是深度,等于使用的 滤波器数量

在卷积神经网络(CNN)中,多卷积核(filter)的卷积是关键的操作,它通过对输入数据应用多个卷积核来提取丰富的特征。
下面详细说明多卷积核卷积计算的步骤和原理。
1. 多卷积核卷积的概念:
假设我们有一个输入图像,其大小为 H × W × D in H \times W \times D_{\text{in}} H×W×Din,其中 H H H 是图像的高度, W W W 是图像的宽度, D in D_{\text{in}} Din 是输入图像的通道数。我们有 N filters N_{\text{filters}} Nfilters 个卷积核,每个卷积核的大小为 F × F × D in F \times F \times D_{\text{in}} F×F×Din,其中 F F F 是卷积核的宽度和高度, D in D_{\text{in}} Din 是输入图像的通道数。
每个卷积核都会与输入图像进行卷积操作,生成一个特征图,最终的输出是多个特征图的集合。
2. 计算步骤:
输入与卷积核:

  • 输入图像大小为 H × W × D in H \times W \times D_{\text{in}} H×W×Din
  • 每个卷积核大小为 F × F × D in F \times F \times D_{\text{in}} F×F×Din
  • N filters N_{\text{filters}} Nfilters 个卷积核
  • 步幅(stride)为 S S S
  • 填充(padding)为 P P P

计算过程:

  1. 每个卷积核与输入图像的每个通道进行卷积:对于第 k k k 个卷积核的每个通道 d d d d = 1 , 2 , . . . , D in d = 1, 2, ..., D_{\text{in}} d=1,2,...,Din),我们执行以下操作: conv ( I d , K k , d ) \text{conv}(I_d, K_{k,d}) conv(Id,Kk,d)其中, I d I_d Id 是输入图像的第 d d d 个通道, K k , d K_{k,d} Kk,d 是第 k k k 个卷积核的第 d d d 个通道。
  2. 对通道进行求和:将上述卷积结果对所有通道进行求和,得到一个单通道输出特征图: O k = ∑ d = 1 D in conv ( I d , K k , d ) O_k = \sum_{d=1}^{D_{\text{in}}} \text{conv}(I_d, K_{k,d}) Ok=d=1Dinconv(Id,Kk,d)
  3. 多卷积核操作:对于每个卷积核重复以上步骤,得到 N filters N_{\text{filters}} Nfilters 个输出特征图。最终的输出特征图大小为 H out × W out × N filters H_{\text{out}} \times W_{\text{out}} \times N_{\text{filters}} Hout×Wout×Nfilters,其中 H out H_{\text{out}} Hout W out W_{\text{out}} Wout 由输入图像大小、卷积核大小、步幅和填充决定。

3. 数学表示:
假设输入图像大小为 H × W × D in H \times W \times D_{\text{in}} H×W×Din,卷积核大小为 F × F × D in F \times F \times D_{\text{in}} F×F×Din,步幅为 S S S,填充为 P P P,输出特征图的大小为 H out × W out H_{\text{out}} \times W_{\text{out}} Hout×Wout,则:
H out = ⌊ H − F + 2 P S ⌋ + 1 H_{\text{out}} = \left\lfloor \frac{H - F + 2P}{S} \right\rfloor + 1 Hout=SHF+2P+1
W out = ⌊ W − F + 2 P S ⌋ + 1 W_{\text{out}} = \left\lfloor \frac{W - F + 2P}{S} \right\rfloor + 1 Wout=SWF+2P+1
输出特征图的深度为卷积核的个数,即 N filters N_{\text{filters}} Nfilters
4. 示例:
假设输入图像大小为 6 × 6 × 3 6 \times 6 \times 3 6×6×3(RGB 图像),卷积核大小为 3 × 3 × 3 3 \times 3 \times 3 3×3×3,步幅为 1,没有填充(即 P = 0 P=0 P=0),有 2 个卷积核。则输出特征图的大小为:
H out = ⌊ 6 − 3 + 2 ⋅ 0 1 ⌋ + 1 = 4 H_{\text{out}} = \left\lfloor \frac{6 - 3 + 2 \cdot 0}{1} \right\rfloor + 1 = 4 Hout=163+20+1=4
W out = ⌊ 6 − 3 + 2 ⋅ 0 1 ⌋ + 1 = 4 W_{\text{out}} = \left\lfloor \frac{6 - 3 + 2 \cdot 0}{1} \right\rfloor + 1 = 4 Wout=163+20+1=4
输出特征图的深度为 2。所以,最终输出特征图的大小为 4 × 4 × 2 4 \times 4 \times 2 4×4×2
5. 总结:
多卷积核卷积在处理多维数据(如彩色图像)时非常重要。通过对每个通道进行卷积并累加结果,可以捕捉到更多的信息和特征。这种计算方法在卷积神经网络中被广泛应用,尤其是在图像分类和目标检测等任务中。

7、特征图大小

输出特征图的大小与以下参数息息相关:

  1. size: 卷积核/过滤器大小,一般会选择为奇数,比如有 11, 33, 55
  2. Padding:零填充的方式
  3. Stride:步长

那计算方法如下图所示:

  1. 输入图像大小:W x W
  2. 卷积核大小:F x F
  3. Stride:S
  4. Padding:P
  5. 输出图像大小: N x N

N = W − F + 2 P S + 1 N = \frac{W - F + 2P}{S} + 1 N=SWF+2P+1
以下图为例:

  1. 图像大小:5 x 5
  2. 卷积核大小:3 x 3
  3. Stride:1
  4. Padding:1
  5. (5 - 3 + 2) / 1 + 1 = 5, 即得到的特征图大小为: 5 x 5

8、PyTorch 卷积层 API

我们接下来对下面的图片进行特征提取:
image.png
先写一个展示图像的函数:
image.png

8.1、单个多通道卷积核

图示:
image.png
代码:
image.png
实现效果:
image.png

8.2、多个多通道卷积核

图示:
image.png

注意:这里的卷积核不是平行的,而是链式的!

代码:
image.png
实现效果:
image.png

8.3、完整代码

# -*- coding: utf-8 -*-
# @Author: CSDN@逐梦苍穹
# @Time: 2024/8/2 2:35

import torch  # 导入 PyTorch 库,用于深度学习
import torch.nn as nn  # 导入 PyTorch 的神经网络模块
import matplotlib.pyplot as plt  # 导入 Matplotlib 库,用于数据可视化


# 显示图像的函数
def show(img):
    # 输入形状: (Height, Width, Channel)
    plt.imshow(img)  # 显示图像
    plt.axis('off')  # 关闭坐标轴
    plt.show()  # 展示图像


# 1. 单个多通道卷积核的测试函数
def test01():
    # 读取图像, 形状: (640, 640, 4)
    img = plt.imread('images/img_RGBA.png')  # 读取图像文件
    show(img)  # 显示原始图像
    # TODO 构建卷积层
    # 由于 out_channels 为 1, 相当于只有一个4通道卷积核
    conv = nn.Conv2d(in_channels=4, out_channels=1, kernel_size=3, stride=1, padding=1)  # 定义一个 2D 卷积层
    # 输入形状: (BatchSize, Channel, Height, Width)
    # TODO img形状: torch.Size([4, 640, 640])
    img = torch.tensor(img).permute(2, 0, 1)  # 将图像数据转换为张量,并调整维度顺序
    # img 形状: torch.Size([1, 4, 640, 640])
    # TODO 增加一个批次维度
    img = img.unsqueeze(0)
    # TODO 输入卷积层, new_img 形状: torch.Size([1, 1, 640, 640])
    new_img = conv(img)  # 将图像输入卷积层
    # new_img 形状: torch.Size([640, 640, 1])
    new_img = new_img.squeeze(0).permute(1, 2, 0)  # 去掉批次维度并调整维度顺序
    show(new_img.detach().numpy())  # 显示处理后的图像


# 2. 多个多通道卷积核的测试函数
def test02():
    # 读取图像, 形状: (640, 640, 4)
    img = plt.imread('images/img_RGBA.png')  # 读取图像文件
    plt.subplot(2, 2, 1)
    plt.imshow(img)  # 显示图像
    # show(img)
    # TODO 构建卷积层
    # TODO 由于 out_channels 为 3, 相当于只有 3 个4通道卷积核
    conv = nn.Conv2d(in_channels=4, out_channels=3, kernel_size=3, stride=1, padding=1)  # 定义一个 2D 卷积层
    # TODO 输入形状: (BatchSize, Channel, Height, Width)
    # img形状: torch.Size([4, 640, 640])
    img = torch.tensor(img).permute(2, 0, 1)  # 将图像数据转换为张量,并调整维度顺序
    # TODO img 形状: torch.Size([1, 4, 640, 640])
    img = img.unsqueeze(0)  # 增加一个批次维度
    # TODO 输入卷积层, new_img 形状: torch.Size([1, 3, 640, 640])
    new_img = conv(img)  # 将图像输入卷积层
    # new_img 形状: torch.Size([640, 640, 3])
    new_img = new_img.squeeze(0).permute(1, 2, 0)  # 去掉批次维度并调整维度顺序
    # TODO 打印三个特征图
    plt.subplot(2, 2, 2)
    plt.imshow(new_img[:, :, 0].unsqueeze(2).detach().numpy())  # 显示图像
    plt.subplot(2, 2, 3)
    plt.imshow(new_img[:, :, 1].unsqueeze(2).detach().numpy())  # 显示图像
    plt.subplot(2, 2, 4)
    plt.imshow(new_img[:, :, 2].unsqueeze(2).detach().numpy())  # 显示图像
    plt.show()
    # TODO 只是为了一次性显示全部图像才做了如此修改
    # show(new_img[:, :, 0].unsqueeze(2).detach().numpy())  # 显示第一个特征图
    # show(new_img[:, :, 1].unsqueeze(2).detach().numpy())  # 显示第二个特征图
    # show(new_img[:, :, 2].unsqueeze(2).detach().numpy())  # 显示第三个特征图


# 主程序入口
if __name__ == '__main__':
    test01()  # 运行单个多通道卷积核测试
    test02()  # 运行多个多通道卷积核测试

9、小结

卷积层主要用于提取图像特征,避免对复杂图像特征的手动提取,经过实践表明,基于卷积核实现的自动特征提取在很多场景下的效果要好于手动特征提取。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科技赋能生活——便携气象站

传统气象站往往庞大而复杂,需要专业人员维护,它小巧玲珑,设计精致,可以轻松放入背包或口袋,随身携带,不占空间。无论是城市白领穿梭于高楼大厦间,还是户外爱好者深入山林湖海,都能随…

numpy如何按等长分割数组

numpy如何按等长分割数组 1、效果 2、流程 1、分割数组 2、转列表3、代码 # -*- coding: utf-8 -*-""" @contact: 微---信 1257309054 @file: test.py @time: 2024/8/03 19:46 @author: LDC """ import numpy as np# 假设arr是需要分割的nump…

virtualbox7安装centos7.9配置静态ip

1.背景 我大概在一年之前安装virtualbox7centos7.9的环境,但看视频说用vagrant启动的窗口可以不用第三方工具(比如xshell、secure等)连接centos7.9,于是尝鲜试了下还可以,导致系统文件格式是vmdk了(网上有vmdk转vdi的方法&#xf…

ChatGLM3-6B模型部署微调实战

准备 教程 视频教程 https://www.bilibili.com/video/BV1ce411J7nZ?p14&vd_source165c419c549bc8d0c2d71be2d7b93ccc 视频对应的资料 https://pan.baidu.com/wap/init?surlAjPi7naUMcI3OGG9lDpnpQ&pwdvai2#/home/%2FB%E7%AB%99%E5%85%AC%E5%BC%80%E8%AF%BE%E3%8…

Keil5.40因为Jlink驱动闪退问题

现象 Cannot load driver ‘C:\Keil_v5\ARM\Segger\JL2CM3.dll 原因 由于Jlink为盗版,导致闪退。 具体为JLinkARM.dll这个插件搞鬼。 这个插件的来源为 也就是我们装Jlink驱动的时候,勾选了这个选项,而导致这个毒瘤插件进入Keil&#xff…

代码题-01_顺序表_基础知识

线性表 线性表(list):零个或多个相同数据元素的有限序列 线性表是逻辑结构(元素之间一对一相邻关系)按存储方式分为 顺序表链表 顺序表 顺序表的定义 静态分配(使用数组存数据) 有溢出风险 typedef…

特定领域软件架构-系统架构师(三十七)

软件架构复用 有三个阶段: 首先构造/获取可复用的软件资产其次管理这些资产(构件库)最后针对这些需求,从这些资产中选择可复用的部分,满足需求应用系统。 特定领域软件架构 DSSA(Domain Specific softwa…

(四)activit5.23.0修复跟踪高亮显示BUG

一、先看bug 在 (三)springboot2.7.6集成activit5.23.0之流程跟踪高亮显示 末尾就发现高亮显示与预期不一样,比如上面的任务2前面的箭头没有高亮显示。 二、分析原因 具体分析步骤省略了,主要是ProcessInstanceHighlightsResour…

饿了么冰杯外卖爆涨350%,“冰+X”激发酒饮即时零售夏季增长加速

近日,饿了么联合尼尔森IQ共同发布的《2024夏季即时零售冰品酒饮消费洞察报告》显示,大暑前后冰杯外卖量同比去年增长350%,冰杯搭配啤酒等酒水饮料的外卖量也同比增长约300%。 报告综合多渠道零售数据和案例分析,剖析了冰品酒饮在…

基于51单片机的车窗控制系统proteus仿真

地址: https://pan.baidu.com/s/1w5qrAvn1cUK7ZX2GJvWBQw 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C52/AT89C51是一款经典的8位单片机,是意法半导体(STMicroelectro…

DedeCMS-V5.7.82-UTF8织梦

先进行安装 然后进入首页和管理员后台 内容要在后台进行操作 首页 后台 1.通过文件管理器上传WebShell 访问目标靶场其思路为 dedecms 后台可以直接上传任意文件,可以通过文件管理器上传php文件获取webshel 登陆到后台点击【核心】【文件式管理器】【文件上传】将…

基于深度学习的面部表情分类识别系统

:温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 面部表情识别是计算机视觉领域的一个重要研究方向, 它在人机交互、心理健康评估、安全监控等领域具有广泛的应用。近年来,随着深度学习技术的快速发展&#xf…

C++篇:入门(2)

引用 引用的概念以及定义: 在C中,引用(Reference)是一个非常重要的概念又可以称之为取别名,它允许我们创建一个已存在对象的别名。引用提供了一种机制,通过它可以直接访问另一个变量、对象或函数的值&#…

Nginx进阶-常见配置(一)

一、nginx Proxy 反向代理 1、代理原理 反向代理产生的背景: 在计算机世界里,由于单个服务器的处理客户端(用户)请求能力有一个极限,当用户的接入请求蜂拥而入时,会造成服务器忙不过来的局面&#xff0c…

【实现100个unity特效之12】Unity中的冲击波 ——如何使用ShaderGraph制作一个冲击波着色器

最终效果 文章目录 最终效果新增LitShaderGraph圆环扭曲效果优化冲击波效果屏幕全屏冲击波圆形冲击波最终连线图代码控制补充源码完结 新增LitShaderGraph 圆环扭曲效果 让我们从一个UV节点开始 创建一个Vector2变量RingSpawnPosition表示冲击波生成位置,在X和Y上将其默认值…

springboot实现前后端调用axios异步请求(后端单体服务器static部分)

目的:让页面调用controller,将数据加载到页面中(只不过这个前端页面我们直接就是放到了static里面了)。 第一步:导入文件 所需要的文件见本文最后“文件获取”: (1)文件如下&…

汇昌联信拼多多运营怎么样?

汇昌联信拼多多运营怎么样?在探讨汇昌联信在拼多多平台的运营情况时,首先需要明确的回答是:汇昌联信在拼多多的运营表现是积极的,并取得了一定的成效。接下来,我们将从五个不同的角度深入分析其运营策略及效果。 一、产品多样性与…

Centos7挂载数据盘

查看当前服务器有哪些磁盘 fdisk -l 2.格式化 mke2fs -t ext4 /dev/vdc 3.挂载数据盘 mkdir /sdxinfang mount /dev/vdc /sdxinfang/ 为了避免每次开机都要重新挂载,直接设置系统挂载信息,这样开机会自动挂载 vim /etc/fstab 在文件末尾增加以下内容&…

Axure八大优质Web端系统框架模版

在当今数字化转型的浪潮中,Axure作为一款强大的原型设计工具,以其快速、直观和易用的特点,成为了众多设计师和产品经理的首选。本文将详细介绍六套基于Axure制作的智慧系统原型框架模版,包括智慧园区、智慧社区、智慧乡村、智慧驾…

4个好用的 CSS 伪类 :not()、:has()、 :is()、:where()

文章目录 (1):not()(2):has()(3):is()(4):where()(5):where()与:is() 的区别 (1):not() :not 伪类:用于选择不满足给定条…