Restormer: Efficient Transformer for High-Resolution Image Restoration

news2024/11/14 5:55:04

Abstract

由于卷积神经网络(CNN)在从大规模数据中学习可概括的图像先验方面表现良好,因此这些模型已广泛应用于图像恢复和相关任务。最近,另一类神经架构 Transformer 在自然语言和高级视觉任务上表现出了显着的性能提升。虽然 Transformer 模型弥补了 CNN 的缺点(即有限的感受野和对输入内容的不适应性),但其计算复杂度随空间分辨率呈二次方增长,因此无法应用于大多数涉及高分辨率图像的图像恢复任务。在这项工作中,我们通过在构建块(多头注意力和前馈网络)中进行几个关键设计,提出了一种高效的 Transformer 模型,使其可以捕获远程像素交互,同时仍然适用于大图像。我们的模型名为 Restoration Transformer (Restormer),在多项图像恢复任务上取得了最先进的结果,包括图像去雨、单图像运动去模糊、散焦去模糊(单图像和双像素数据)以及图像去噪(高斯灰度/彩色去噪、真实图像去噪)。源代码和预训练模型可在 https://github.com/swz30/Restormer 获取。

1. Introduction

图像恢复是通过从降级输入中消除降级(例如噪声、模糊、雨滴)来重建高质量图像的任务。由于不适定的性质,这是一个极具挑战性的问题,通常需要强大的图像先验才能进行有效的恢复。由于卷积神经网络(CNN)在从大规模数据中学习可概括的先验方面表现良好,因此与传统的恢复方法相比,它们已成为更好的选择。

CNN 的基本操作是“卷积”,它提供局部连接和平移等方差。虽然这些特性为 CNN 带来了效率和泛化性,但它们也引起了两个主要问题。 (a) 卷积算子的感受野有限,因此无法对远程像素依赖性进行建模。 (b) 卷积滤波器在推理时具有静态权重,因此不能灵活地适应输入内容。为了解决上述缺点,一种更强大、更动态的替代方案是自注意力(SA)机制[17,77,79,95],它通过所有其他位置的加权和来计算给定像素的响应。

自注意力是 Transformer 模型 [34, 77] 的核心组成部分,但具有独特的实现,即针对并行化和有效表示学习进行优化的多头 SA。 Transformers 在自然语言任务 [10,19,49,62] 和高级视觉问题 [11,17,76,78] 上表现出了最先进的性能。尽管 SA 在捕获长距离像素交互方面非常有效,但其复杂性随空间分辨率呈二次方增长,因此无法应用于高分辨率图像(图像恢复中的常见情况)。最近,为图像恢复任务定制 Transformer 的努力还很少[13,44,80]。为了减少计算负载,这些方法要么在每个像素周围大小为 8×8 的小空间窗口上应用 SA [44, 80],要么将输入图像划分为大小为 48×48 的非重叠块并在每个块上计算 SA独立地[13]。然而,限制 SA 的空间范围与捕获真实的远程像素关系的目标是矛盾的,尤其是在高分辨率图像上。

在本文中,我们提出了一种用于图像恢复的高效 Transformer,它能够对全局连接进行建模,并且仍然适用于大图像。具体来说,我们引入了一个多 Dconv 头“转置”注意力(MDTA)块(第 3.1 节)来代替具有线性复杂度的普通多头 SA [77]。它跨特征维度而不是空间维度应用 SA,即,MDTA 不是显式地建模成对像素交互,而是计算跨特征通道的互协方差,以从(关键和查询投影)输入特征获取注意力图。我们的 MDTA 块的一个重要特征是在特征协方差计算之前进行局部上下文混合。这是通过使用 1×1 卷积对跨通道上下文进行像素级聚合以及使用高效深度卷积对局部上下文进行通道级聚合来实现的。该策略提供了两个关键优势。首先,它强调空间局部上下文,并在我们的管道中引入卷积运算的互补优势。其次,它确保在计算基于协方差的注意力图时隐式建模像素之间的上下文全局关系。

前馈网络(FN)是 Transformer 模型 [77] 的另一个构建块,它由两个完全连接的层组成,其间具有非线性。在这项工作中,我们用门控机制 [16] 重新表述了常规 FN [77] 的第一个线性变换层,以改善通过网络的信息流。该门控层被设计为两个线性投影层的逐元素乘积,其中一个由 GELU 非线性激活[27]。我们的门控 Dconv FN (GDFN)(第 3.2 节)也基于类似于 MDTA 模块的本地内容混合,以同样强调空间上下文。 GDFN 中的门控机制控制哪些互补特征应向前流动,并允许网络层次结构中的后续层专门关注更精细的图像属性,从而产生高质量的输出。

除了上述架构新颖性之外,我们还展示了 Restormer 渐进式学习策略的有效性(第 3.3 节)。在此过程中,网络在早期 epoch 中接受小补丁和大批量训练,并在后期 epoch 中接受逐渐大的图像补丁和小批量训练。这种训练策略有助于 Restormer 从大图像中学习上下文,并随后在测试时提供质量性能改进。我们进行了全面的实验,并在 16 个基准数据集上展示了 Restormer 的最先进性能,适用于多种图像恢复任务,包括图像去雨、单图像运动去模糊、散焦去模糊(在单图像和双像素数据上)和图像去噪(针对合成数据和真实数据);参见图 1。此外,我们提供了广泛的消融来显示架构设计和实验选择的有效性。

这项工作的主要贡献总结如下:

• 我们提出了Restormer,一种编码器-解码器Transformer,用于在高分辨率图像上进行多尺度局部-全局表示学习,而不将它们分解到局部窗口中,从而利用遥远的图像上下文。

• 我们提出了一个多Dconv 头转置注意(MDTA)模块,它能够聚合局部和非局部像素交互,并且足够有效地处理高分辨率图像。

• 一种新的门控Dconv前馈网络(GDFN),它执行受控特征转换,即抑制信息量较少的特征,并仅允许有用的信息进一步通过网络层次结构。

2. Background

Image Restoration.

近年来,数据驱动的 CNN 架构 [7,18,92,93,105,107] 已被证明优于传统的恢复方法 [26,36,53,75]。在卷积设计中,基于编码器-解码器的 UNet 架构 [3,14,39,80,90,93,99] 由于其分层多尺度表示同时保持计算效率而被主要研究用于恢复。类似地,由于特别关注学习残差信号,基于跳跃连接的方法已被证明对于恢复是有效的[24,48,92,106]。空间和通道注意模块也被纳入以选择性地关注相关信息[43,92,93]。我们建议读者参考 NTIRE 挑战报告 [2,5,30,57] 和最近的文献综述 [8,42,73],其中总结了图像恢复的主要设计选择。

Vision Transformers.

Transformer 模型最初是为自然语言任务中的序列处理而开发的[77]。它已适用于许多视觉任务,例如图像识别[17,76,88]、分割[78,83,108]、对象检测[11,50,109]。视觉变换器 [17, 76] 将图像分解为一系列补丁(局部窗口)并学习它们的相互关系。这些模型的显着特征是学习图像块序列之间的远程依赖性的强大能力以及对给定输入内容的适应性[34]。由于这些特性,Transformer 模型也被研究用于低级视觉问题,例如超分辨率 [44,85]、图像着色 [37]、去噪 [13, 80] 和去雨 [80]。然而,Transformers 中 SA 的计算复杂度会随着图像块的数量呈二次方增加,从而阻碍了其在高分辨率图像中的应用。因此,在需要生成高分辨率输出的低级图像处理应用中,最近的方法通常采用不同的策略来降低复杂性。一种潜在的补救措施是使用 Swin Transformer 设计 [44] 在局部图像区域 [44, 80] 中应用自注意力。然而,这种设计选择限制了局部邻域内的上下文聚合,违背了在卷积上使用自注意力的主要动机,因此不太适合图像恢复任务。相比之下,我们提出了一个 Transformer 模型,它可以学习远程依赖关系,同时保持计算效率。

3. Method

我们的主要目标是开发一种高效的 Transformer 模型,可以处理用于恢复任务的高分辨率图像。为了缓解计算瓶颈,我们在多头 SA 层和多尺度分层模块中引入了关键设计,该模块的计算要求比单尺度网络[44]更少。我们首先展示 Restormer 架构的整体流程(见图 2)。然后我们描述了所提出的 Transformer 块的核心组件:(a)多 Dconv 头转置注意力(MDTA)和(b)门控 Dconv 前馈网络(GDFN)。最后,我们提供了有关有效学习图像统计的渐进式训练方案的详细信息。

Overall Pipeline.

给定一个退化图像 I ∈ RH×W×3,Restormer 首先应用卷积来获得低级特征嵌入 F0 ∈RH×W×C;其中H×W表示空间维度,C是通道数。接下来,这些浅层特征 F0 经过 4 级对称编码器-解码器并转换为深层特征 Fd ∈ RH×W×2C。每个级别的编码器-解码器包含多个 Transformer 块,其中块的数量从上到下逐渐增加以保持效率。从高分辨率输入开始,编码器分层减小空间尺寸,同时扩展通道容量。解码器采用低分辨率潜在特征 Fl ∈ R H 8 ×W 8 ×8C 作为输入,并逐步恢复高分辨率表示。对于特征下采样和上采样,我们分别应用像素不洗牌和像素洗牌操作[69]。为了协助恢复过程,编码器特征通过跳跃连接与解码器特征连接[66]。级联操作之后是 1×1 卷积,以减少除顶部通道之外的所有级别的通道(减半)。在第 1 级,我们让 Transformer 块将编码器的低级图像特征与解码器的高级特征聚合。它有利于保留恢复图像中的精细结构和纹理细节。接下来,深层特征 Fd 在高空间分辨率下的细化阶段进一步丰富。正如我们将在实验部分(第 4 节)中看到的那样,这些设计选择带来了质量改进。最后,对细化后的特征应用卷积层,生成残差图像 R ∈ RH×W×3,将退化图像添加到残差图像中,得到恢复图像:ˆI = I +R。接下来,我们介绍 Transformer 块的模块。

3.1. Multi-Dconv Head Transposed Attention

Transformer 中的主要计算开销来自自注意力层。在传统的 SA [17, 77] 中,键查询点积交互的时间和内存复杂度随着输入的空间分辨率呈二次方增长,即对于 W×H 像素的图像,O(W2H2)。因此,在大多数涉及高分辨率图像的图像恢复任务中应用SA是不可行的。为了缓解这个问题,我们提出了具有线性复杂度的MDTA,如图2(a)所示。关键要素是跨通道而不是空间维度应用 SA,即计算跨通道的互协方差,以生成隐式编码全局上下文的注意力图。作为 MDTA 的另一个重要组成部分,我们引入深度卷积来强调局部上下文,然后再计算特征协方差以生成全局注意力图。

3.2. Gated-Dconv Feed-Forward Network

为了转换特征,常规前馈网络(FN)[17,77]对每个像素位置分别且相同地进行操作。它使用两个 1×1 卷积,一个用于扩展特征通道(通常通过因子 γ=4),第二个用于将通道减少回原始输入维度。在隐藏层中应用非线性。在这项工作中,我们提出了对 FN 的两个基本修改来改进表示学习:(1) 门控机制,(2) 深度卷积。我们的 GDFN 的架构如图 2(b)所示。门控机制被表述为线性变换层两个平行路径的逐元素乘积,其中之一通过 GELU 非线性激活[27]。与 MDTA 一样,我们还在 GDFN 中包含深度卷积,以对空间相邻像素位置的信息进行编码,这对于学习局部图像结构以实现有效恢复非常有用。给定一个输入张量 X ∈ R^{\hat{H}\hat{W}\times\hat{H}\hat{W}},GDFN 的公式为:

其中\odot表示逐元素乘法,φ表示GELU非线性,LN是层归一化[9]。总体而言,GDFN 控制着我们管道中各个层级的信息流,从而允许每个级别专注于与其他级别互补的细节。也就是说,与 MDTA(专注于利用上下文信息丰富特征)相比,GDFN 提供了独特的作用。由于与常规 FN [17] 相比,所提出的 GDFN 执行更多操作,因此我们降低了扩展率 γ,以便具有相似的参数和计算负担。

3.3. Progressive Learning

基于 CNN 的恢复模型通常在固定大小的图像块上进行训练。然而,在小裁剪补丁上训练 Transformer 模型可能不会对全局图像统计数据进行编码,从而在测试时在全分辨率图像上提供次优性能。为此,我们进行渐进式学习,其中网络在早期训练时期在较小的图像块上进行训练,在后期训练时期在逐渐增大的图像块上进行训练。通过渐进式学习在混合大小的补丁上训练的模型在测试时表现出增强的性能,其中图像可以具有不同的分辨率(图像恢复中的常见情况)。渐进式学习策略的行为方式与课程学习过程类似,其中网络从更简单的任务开始,逐渐转向学习更复杂的任务(需要保留精细图像结构/纹理)。由于对大补丁的训练需要更长的时间,因此我们随着补丁大小的增加而减少批量大小,以保持每个优化步骤与固定补丁训练的时间相似。

4. Experiments and Analysis

我们在基准数据集和四个图像处理任务的实验设置上评估了所提出的 Restormer:(a)图像去雨,(b)单图像运动去模糊,(c)散焦去模糊(在单图像和双像素数据上),以及( d) 图像去噪(针对合成数据和真实数据)。补充材料中提供了有关数据集、训练协议和其他视觉结果的更多详细信息。在表格中,所评估方法的最佳和次佳质量分数被突出显示并带有下划线。

Implementation Details.

我们为不同的图像恢复任务训练单独的模型。在所有实验中,除非另有说明,我们使用以下训练参数。我们的 Restormer 采用 4 级编码器-解码器。从level-1到level-4,Transformer块的数量为[4,6,6,8],MDTA中的注意力头为[1,2,4,8],通道数量为[48,96, 192、384]。细化阶段包含 4 个块。 GDFN中的通道扩展因子是γ=2.66。我们使用 AdamW 优化器(β1=0.9,β2=0.999,权重衰减 1e−4)和 L1 损失训练模型进行 300K 次迭代,初始学习率 3e−4 通过余弦退火逐渐降低到 1e−6 [51]。对于渐进式学习,我们开始使用补丁大小 128×128 和批量大小 64 进行训练。补丁大小和批量大小对更新为 [(1602,40), (1922,32), (2562,16), (3202, 8), (3842,8)] 迭代 [92K, 156K, 204K, 240K, 276K]。对于数据增强,我们使用水平和垂直翻转

4.1. Image Deraining Results

4.2. Single-image Motion Deblurring Results

4.3. Defocus Deblurring Results

4.4. Image Denoising Results

4.5. Ablation Studies

对于消融实验,我们仅在大小为 128×128 的图像块上训练高斯颜色去噪模型,进行 100K 次迭代。在 Urban100 [29] 上进行测试,并针对具有挑战性的噪声水平 σ=50 进行分析。 FLOP 和推理时间是根据图像大小 256×256 计算的。表 7-10 显示我们的贡献带来了质量性能改进。接下来,我们分别描述每个组件的影响。

Improvements in multi-head attention.

表 7c 表明,我们的 MDTA 比基线(表 7a)提供了 0.32 dB 的有利增益。此外,通过深度卷积将局部性引入 MDTA 可以提高鲁棒性,因为删除局部性会导致 PSNR 下降(参见表 7b)。

Improvements in feed-forward network (FN)

表 7d 显示 FN 中控制信息流的门控机制比传统 FN [77] 产生 0.12 dB 增益。与多头注意力一样,在 FN 中引入局部机制也带来了性能优势(见表 7e)。我们通过结合门控深度卷积进一步增强 FN。对于噪声水平 50,我们的 GDFN(表 7f)实现了比标准 FN [77] 0.26 dB 的 PSNR 增益。总体而言,我们的 Transformer 模块的贡献导致比基线显着增益 0.51 dB。

Design choices for decoder at level-1

为了将编码器特征与级别 1 的解码器聚合,我们在串联操作后不使用 1×1 卷积(将通道减少一半)。它有助于保留来自编码器的精细纹理细节,如表 8 所示。这些结果进一步证明了在细化阶段添加 Transformer 块的有效性。

Impact of progressive learning.

表 9 显示,渐进式学习提供了比固定补丁训练更好的结果,同时训练时间相似。

Deeper or wider Restormer?

表 10 显示,在相似的参数/FLOPs 预算下,深窄模型比宽浅模型的性能更准确。然而,由于并行化,更宽的模型运行得更快。在本文中,我们使用深窄 Restormer。

5. Conclusion

我们提出了一种图像恢复 Transformer 模型 Restormer,它在处理高分辨率图像方面具有计算效率。我们为 Transformer 模块的核心组件引入了关键设计,以改进特征聚合和转换。具体来说,我们的 multiDconv 头部转置注意力(MDTA)模块通过跨通道而不是空间维度应用自注意力来隐式模拟全局上下文,因此具有线性复杂度而不是二次复杂度。此外,所提出的门控 DConv 前馈网络(GDFN)引入了门控机制来执行受控特征转换。为了将 CNN 的优势融入到 Transformer 模型中,MDTA 和 GDFN 模块都包含用于编码空间局部上下文的深度卷积。对 16 个基准数据集的大量实验表明,Restormer 在众多图像恢复任务中实现了最先进的性能。

代码解读

MDTA

##########################################################################
## Multi-DConv Head Transposed Self-Attention (MDTA)
class Attention(nn.Module):
    def __init__(self, dim, num_heads, bias):
        super(Attention, self).__init__()
        self.num_heads = num_heads
        self.temperature = nn.Parameter(torch.ones(num_heads, 1, 1))

        self.qkv = nn.Conv2d(dim, dim*3, kernel_size=1, bias=bias)
        self.qkv_dwconv = nn.Conv2d(dim*3, dim*3, kernel_size=3, stride=1, padding=1, groups=dim*3, bias=bias)
        self.project_out = nn.Conv2d(dim, dim, kernel_size=1, bias=bias)
        


    def forward(self, x):
        b,c,h,w = x.shape

        qkv = self.qkv_dwconv(self.qkv(x))
        q,k,v = qkv.chunk(3, dim=1)   
        
        q = rearrange(q, 'b (head c) h w -> b head c (h w)', head=self.num_heads)
        k = rearrange(k, 'b (head c) h w -> b head c (h w)', head=self.num_heads)
        v = rearrange(v, 'b (head c) h w -> b head c (h w)', head=self.num_heads)

        q = torch.nn.functional.normalize(q, dim=-1)
        k = torch.nn.functional.normalize(k, dim=-1)

        attn = (q @ k.transpose(-2, -1)) * self.temperature
        attn = attn.softmax(dim=-1)

        out = (attn @ v)
        
        out = rearrange(out, 'b head c (h w) -> b (head c) h w', head=self.num_heads, h=h, w=w)

        out = self.project_out(out)
        return out

qkv是1x1卷积,输出维度是输入三倍,qkv_dwconv是分组卷积,输出维度不变,chunk等分3个分别为q、k、v,即shape与输入x相同。

分别对q、k、v进行rearrage,多头设置进行通道数划分,q、k乘积前进行归一化,注意q、v shape为b head c h*w,v转置,则attn为b head c c,为文中所谓的通道间注意力。

GDFN

##########################################################################
## Gated-Dconv Feed-Forward Network (GDFN)
class FeedForward(nn.Module):
    def __init__(self, dim, ffn_expansion_factor, bias):
        super(FeedForward, self).__init__()

        hidden_features = int(dim*ffn_expansion_factor)

        self.project_in = nn.Conv2d(dim, hidden_features*2, kernel_size=1, bias=bias)

        self.dwconv = nn.Conv2d(hidden_features*2, hidden_features*2, kernel_size=3, stride=1, padding=1, groups=hidden_features*2, bias=bias)

        self.project_out = nn.Conv2d(hidden_features, dim, kernel_size=1, bias=bias)

    def forward(self, x):
        x = self.project_in(x)
        x1, x2 = self.dwconv(x).chunk(2, dim=1)
        x = F.gelu(x1) * x2
        x = self.project_out(x)
        return x

先是1x1,用于提取特征,注意参数ffn_expansion_factor,然后接一个3x3的dwconv,通道维度不变,按照维度划分两个x1、x2,其中一个进行gelu,project_out将维度恢复到x一样。

LayerNorm

## Layer Norm

def to_3d(x):
    return rearrange(x, 'b c h w -> b (h w) c')

def to_4d(x,h,w):
    return rearrange(x, 'b (h w) c -> b c h w',h=h,w=w)

class BiasFree_LayerNorm(nn.Module):
    def __init__(self, normalized_shape):
        super(BiasFree_LayerNorm, self).__init__()
        if isinstance(normalized_shape, numbers.Integral):
            normalized_shape = (normalized_shape,)
        normalized_shape = torch.Size(normalized_shape)

        assert len(normalized_shape) == 1

        self.weight = nn.Parameter(torch.ones(normalized_shape))
        self.normalized_shape = normalized_shape

    def forward(self, x):
        sigma = x.var(-1, keepdim=True, unbiased=False)
        return x / torch.sqrt(sigma+1e-5) * self.weight

class WithBias_LayerNorm(nn.Module):
    def __init__(self, normalized_shape):
        super(WithBias_LayerNorm, self).__init__()
        if isinstance(normalized_shape, numbers.Integral):
            normalized_shape = (normalized_shape,)
        normalized_shape = torch.Size(normalized_shape)

        assert len(normalized_shape) == 1

        self.weight = nn.Parameter(torch.ones(normalized_shape))
        self.bias = nn.Parameter(torch.zeros(normalized_shape))
        self.normalized_shape = normalized_shape

    def forward(self, x):
        mu = x.mean(-1, keepdim=True)
        sigma = x.var(-1, keepdim=True, unbiased=False)
        return (x - mu) / torch.sqrt(sigma+1e-5) * self.weight + self.bias


class LayerNorm(nn.Module):
    def __init__(self, dim, LayerNorm_type):
        super(LayerNorm, self).__init__()
        if LayerNorm_type =='BiasFree':
            self.body = BiasFree_LayerNorm(dim)
        else:
            self.body = WithBias_LayerNorm(dim)

    def forward(self, x):
        h, w = x.shape[-2:]
        return to_4d(self.body(to_3d(x)), h, w)

先将输入进行重排,b c h w转为b h*w c,对c维度进行求均值和方差,然后进行归一化,最后再重排到4维b c h w

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

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

相关文章

SpringMVC基本原理

第一章:Java web的发展历史 一.Model I和Model II 1.Model I开发模式 Model1的开发模式是:JSPJavaBean的模式,它的核心是Jsp页面,在这个页面中,Jsp页面负责整合页面和JavaBean(业务逻辑)&…

23.1 微服务理论基础

23.1 微服务基础 1. 微服务介绍2. 微服务特点3. 微服务优缺点4. 微服务两大门派5. 微服务拆分6. 微服务扩展6.1 服务扩展6.2 按需扩展7. 微服务重要模块******************************************************************************************************************

自然语言处理实验2 字符级RNN分类实验

实验2 字符级RNN分类实验 必做题: (1)数据准备:academy_titles.txt为“考硕考博”板块的帖子标题,job_titles.txt为“招聘信息”板块的帖子标题,将上述两个txt进行划分,其中训练集为70%&#xf…

超薄片式厚膜电阻

超薄片式厚膜电阻器具有许多碳电阻器特性;它们可以做得很小,而且大批量的成本非常低。同时厚膜电阻器具有高达10TW(太欧姆)的高电阻值、非常高的温度性能和高电压能力,并且本质上是无感的。它们适用于医疗、航空航天和井下&#x…

比Let‘s Encrypt更简单更齐全的免费证书申请教程

步骤一 打开JoySSL官网,注册属于你的专属账号; 永久免费SSL证书申请地址真正完全且永久免费!不用您花一分钱,SSL证书免费使用90天,并且还支持连续签发。JoySSL携手全球权威可信顶级根,自研新一代SSL证书&…

YOLOV5 部署:QT的可视化界面推理(创建UI,并编译成py文件)

1、前言 之前用YOLOV5 做了一个猫和老鼠的实战检测项目,本章将根据之前训练好的权重进行部署,搭建一个基于QT的可视化推理界面,可以检测图片和视频 本章使用的数据集和权重参照:YOLOV5 初体验:简单猫和老鼠数据集模型训练-CSDN博客 可视化界面如下: 2、安装Pyside6 本…

【Leetcode每日一题】 递归 - 合并两个有序链表(难度⭐)(35)

1. 题目解析 题目链接:21. 合并两个有序链表 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 1. 递归函数定义与功能 递归函数的主要任务是将两个有序链表合并成一个新的有序链表,并返回合并后…

面试常问:为什么 Vite 速度比 Webpack 快?

前言 最近作者在学习 webpack 相关的知识,之前一直对这个问题不是特别了解,甚至讲不出个123....,这个问题在面试中也是常见的,作者在学习的过程当中总结了以下几点,在这里分享给大家看一下,当然最重要的是…

PostgreSQL从入门到精通教程 - 第46讲:poc-tpch测试

PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。 第46讲&#…

【计算机网络】概述

文章目录 一、Internet 因特网1.1 网络、互联网、因特网1.2 因特网的组成 二、三种交换方式2.1 电路交换 (Circuit Switching)2.2 *分组交换 (Packet Switching)2.3 报文交换 (Message Switching) 三、计算…

基于Verilog的简易CPU设计

前言 本篇文章将简单讲解CPU之间各部分的功能及接线,并提供Verilog模拟CPU的各个组成部分。该CPU可以完成一些操作,如:加减法,与或,指令跳转等,最后提供testbench用于测试该CPU的工作情况是否符合预期。 C…

雷卯推荐基于USB 快充(USB-PD) 浪涌保护器件

USB PD 从2010年USB BC1.2 :单一5V 1.5A,到2021 年USB PD 3.1,支持电压 5V、9V、15V 和 20V,28V、36V 和 48V, 充电功率同步提升至240W。应用范围从从手机、平板电脑、笔记本电脑,逐渐向显示器、服务器、电机驱动和通信…

企业架构设计方法与实践中的架构治理演进、架构评估方法、架构成熟度模型

企业架构设计方法与实践中的架构治理演进、架构评估方法、架构成熟度模型。 架构治理演进: 架构治理是指通过设立和执行一套政策和程序,来管理和控制一个组织的架构活动。架构治理演进是一个持续的过程,需要根据组织的实际情况进行定期审查和调整。 在演进过程中,重点需要…

Python学习01 python开发的准备工作 1.Python解释器的下载 2.Pycharm集成开发环境的安装

0.按照步骤,快速进行python的开发准备工作 1. Python解释器的下载 下载地址 https://www.python.org/ 选择对应你的系统的安装包 2.记得勾选这里将python加入你的路径中 3.有如下四个程序表明安装成功 4.点击上图中的第二个程序打开窗口检查解释器能否正常工作 输…

Flutter 多语言自动化本地化生成器

Flutter 多语言自动化本地化生成器 这是一个为Flutter设计的插件,通过从Excel表格提取的CSV文件自动生成Dart本地化文件,以简化应用程序本地化的流程。这个工具通过自动化创建多语言资源文件,简化了开发人员和翻译人员的工作流程。 特点 默…

MQTT.fx实现(MQTT Client)连接物联网平台(ThingsCloud )

目录 概述 1 ThingsCloud平台介绍 2 ThingsCloud创建项目 2.1 创建项目 2.2 创建数据类型 2.3 创建设备类型 3 发布和订阅主题 3.1 发布Topic 3.2 订阅主题Topic 4 使用MQTT.fx 测试ThingsClond 4.1 使用MQTT.fx连接ThingsClond 4.2 MQTT.fx 订阅ThingsCloud Messag…

Unity资源热更新----AssetBundle

13.1 资源热更新——AssetBundle1-1_哔哩哔哩_bilibili Resources 性能消耗较大 Resources文件夹大小不能超过2个G 获取AssetBundle中的资源 打包流程 选择图片后点击 创建文件夹,Editor优先编译 打包文件夹位置 using UnityEditor; using UnityEngine; public cla…

探索编程新纪元:Code GeeX、Copilot与通义灵码的智能辅助之旅

在人工智能技术日新月异的今天,编程领域的革新也正以前所未有的速度推进。新一代的编程辅助工具,如Code GeeX、Copilot和通义灵码,正在重塑开发者的工作流程,提升编程效率,并推动编程教育的普及。本文将深入探讨这三款…

已解决Keil报错unknown type name “u8“或/u16/u32

出现问题如下所示,提示错误unknown type name “u8“ 解决方法: 在头文件中加入如下即可解决 typedef uint8_t u8; 这个错误通常表示编译器无法识别“u8”这个类型名。在C/C中,通常使用“uint8_t”来表示8位无符号整数类型。如果代码中…

django-q轻量级定时任务制定

django-q ,celery,apschedule都可以作为python的选型,但是django-q更轻量级,可以定制想要的任务,通过消息中间件,来实现不太高并发的实现 官网介绍地址 django-q官网地址 本次测试的是python3.12版本 首先需要安装dja…