【语义分割—Deeplab V3+】Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation

在这里插入图片描述

Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation

摘要

在深度神经网络中,空间金字塔池模块或编码解码器结构用于语义分割任务。前者网络能够通过以多种速率和多个有效视场使用过滤器或池化操作探查传入的特征,从而对多尺度上下文信息进行编码,而后者通过逐渐恢复空间信息来捕获更清晰的对象边界。在这项工作中,我们建议结合两种方法的优点。具体来说,我们提出的模型DeepLabv3 +通过添加一个简单而有效的解码器模块来扩展(尤其是沿着对象边界的)细分结果,从而扩展了DeepLabv3。我们进一步探究Xception模型并将深度可分离卷积应用于Atrous空间金字塔池和解码器模块,从而建立了一个更快,更强大的编码器-解码器网络。我们在PASCAL VOC 2012和Cityscapes数据集上证明了所提出模型的有效性,无需任何后处理即可实现89.0%和82.1%的测试集性能。

1 介绍

语义分割的目的是为图像中的每个像素分配语义标签,这是计算机视觉中的基本主题之一。 基于完全卷积神经网络的深度卷积神经网络显示出依赖于手工制作特征的系统在基准任务上的显着改进。在这项工作中,我们考虑使用空间金字塔池模块或编码器-解码器结构进行语义分割的两种类型的神经网络,其中前者通过在不同分辨率下合并特征来捕获丰富的上下文信息。后者则能够获得清晰的物体边界。

为了在多个尺度上捕获上下文信息,DeepLabv3 应用具有不同速率的几个并行的atrous卷积(称为空洞空间金字塔池,或ASPP),而PSPNet执行不同网格尺度的池化操作。即使丰富的语义信息在最后的特征图中进行了编码,由于与网络主干内的跨步操作进行池化或卷积,与对象边界有关的详细信息也丢失了。通过应用atrous卷积来提取更密集的特征映射可以减轻这种情况。然而,考虑到现有神经网络的设计和有限的GPU内存,提取比输入分辨率小8甚至4倍的输出特征映射在计算上是禁止的。以ResNet-101为例,当应用atrous卷积提取比输入分辨率小16倍的输出特征时,最后3个残余块(9层)内的特征必须扩大。更糟糕的是,如果需要比输入小8倍的输出特征,则会影响26个残余块(78层!)。因此,如果为这种类型的模型提取更密集的输出特征,则计算密集。另一方面,编码器-解码器模型使其自身在编码器路径中更快地计算(因为没有特征被扩张)并且逐渐恢复解码器路径中的尖锐对象边界。试图结合两种方法的优点,我们建议通过结合多尺度上下文信息来丰富编解码网络中的编码器模块。

特别是,我们提出的模型,称为DeepLabv3 +,通过添加一个简单但有效的解码器模块来扩展DeepLabv3,以恢复对象边界,如图1所示。丰富的语义信息在DeepLabv3的输出中进行编码,带有atrous卷积允许根据计算资源的预算来控制编码器特征的密度。 此外,解码器模块允许详细的对象边界恢复。

在这里插入图片描述
图1. 我们建议改进DeepLabv3,它采用空间金字塔池模块(a)和编码器 - 解码器结构(b)。所提出的模型DeepLabv3 +包含来自编码器模块的丰富语义信息,而详细的对象边界由简单但有效的解码器模块恢复。编码器模块允许我们通过应用atrous卷积以任意分辨率提取特征。

由于最近深度可分离卷积的成功,对于语义分割的任务我们也通过调整Xception模型来探索这种操作,并在速度和准确性方面表现出改进,并将atrous可分离卷积应用于ASPP和解码器模块。最后,我们证明了所提出的模型在PASCAL VOC 2012语义分割基准测试中的有效性,并且在没有任何后处理的情况下在测试集上获得了89.0%的性能,从而创造了一种新的最新技术。

总之,我们的贡献是:

  • 我们提出了一种新颖的编码器-解码器结构,它采用DeepLabv3作为功能强大的编码器模块和简单而有效的解码器模块。

  • 在我们提出的编码器 - 解码器结构中,可以通过atrous卷积任意控制提取的编码器特征的分辨率,以折中精度和运行时间,这对于现有的编码器解码器模型是不可能的。

  • 我们将Xception模型用于分割任务,并将深度可分离卷积应用于ASPP模块和解码器模块,从而产生更快更强的编码器-解码器网络。

  • 我们提出的模型在PASCAL VOC 2012数据集上获得了新的最新性能。我们还提供设计选择和模型变体的详细分析。

  • 我们公开提供基于Tensorflow的模型实现。

2 相关工作

基于完全卷积网络(FCNs)的模型已证明在几个细分基准上有显着改进。提出了几种利用上下文信息细分的模型变体,包括那些采用多尺度输入(即图像金字塔)的模型变体或采用概率图形模型的模型(例如具有有效推理算法的DenseCRF)。在这项工作中,我们主要讨论使用空间金字塔池和编码器-解码器结构的模型。

空间金字塔池化:诸如PSPNet或DeepLab之类的模型在多个网格比例下(包括图像级池化)执行空间金字塔池化,或应用不同速率的几个并行atrous卷积(称为Atrous空间金字塔池或ASPP)。这些模型通过利用多尺度信息在多个分割基准上取得了很好的效果。

编码器-解码器:编码器-解码器网络已成功应用于许多计算机视觉任务,包括人体姿态估计,物体检测和语义分割。通常,编码器-解码器网络包含(1)逐渐减少特征图并捕获更高语义信息的编码器模块,以及(2)逐渐恢复空间信息的解码器模块。基于这个想法,我们建议使用DeepLabv3作为编码器模块,并添加一个简单而有效的解码器模块,以获得更清晰的分割。

深度可分卷积:深度可分卷积或group卷积,是一种强大的操作,可降低计算成本和参数数量,同时保持类似(或稍好一些)的性能。这个操作已经被许多最近的神经网络设计采用。特别是,我们探索了Xception模型,类似于COCO2017检测挑战的提交,并在语义分割任务的准确性和速度方面表现出改进。

3 方法

在本节中,我们简要介绍了atrous卷积和深度可分卷积。 然后我们回顾一下DeepLabv3,它在讨论附加到编码器输出的建议解码器模块之前用作我们的编码器模块。我们还提出了一个改进的Xception模型,它通过更快的计算进一步提高了性能。

3.1 具有Atrous卷积的编码器-解码器

Atrous卷积:Atrous卷积是一种功能强大的工具,可让我们精确控制由深度卷积神经网络计算的特征的分辨率并调整过滤器的视场以捕获多尺度信息,从而对标准卷积操作进行了概括。在二维信号的情况下,对于每个位置,输出特征图 y y y和卷积滤波器 w w w,在输入特征图 x x x上进行粗略的卷积,如下所示:

y [ i ] = ∑ k x [ i + r ⋅ k ] w [ k ] y[i] = \sum_{k}x[i+r\cdot k]w[k] y[i]=kx[i+rk]w[k]

其中,atrous rate r r r决定了我们对输入信号进行采样的步幅。注意,标准卷积是速率 r = 1 r = 1 r=1的特殊情况。通过改变rate值自适应地修改滤波器的视野。

深度可分卷积:深度可分卷积,将标准卷积分解为深度卷积后再进行点向卷积(即1×1卷积),大大降低了计算复杂度。具体地,深度卷积针对每个输入通道独立地执行空间卷积,而采用点向卷积以组合来自深度卷积的输出。在深度可分卷积的TensorFlow实现中,在深度卷积(即空间卷积)中支持了atrous卷积。在这项工作中,我们将得到的卷积称为atrous可分卷积,并发现atrous可分离卷积显着降低了所提出模型的计算复杂度,同时保持了相似(或更好)的性能。

DeepLabv3作为编码器:DeepLabv3采用了atrous卷积来提取由任意分辨率的深度卷积神经网络计算的特征。在这里,我们将输出步幅表示为输入图像空间分辨率与最终输出分辨率的比率(在全局池化或完全连接层之前)。对于图像分类的任务,最终特征图的空间分辨率通常比输入图像分辨率小32倍,因此 o u t p u t s t r i d e = 32 output stride=32 outputstride=32。对于语义分割的任务,可以采用输出 o u t p u t s t r i d e = 16 output stride=16 outputstride=16(或8)通过移除最后一个(或两个)块中的步幅并相应地应用atrous卷积来进行更密集的特征提取(例如,我们分别对 o u t p u t s t r i d e = 8 output stride=8 outputstride=8的最后两个块应用 r a t e = 2 rate = 2 rate=2 r a t e = 4 rate = 4 rate=4)。此外,DeepLabv3拓展了Atrous空间金字塔池化模块,该模块通过应用具有不同rates的atrous卷积和图像级特征来探测多尺度的卷积特征。在我们提出的编码器-解码器结构中,我们使用原始deeplabv3中logits之前的最后一个特征映射作为编码器输出。请注意,编码器输出要素图包含256个通道和丰富的语义信息。此外,可以通过应用atrous卷积以任意分辨率提取特征。

提出的解码器:DeepLabv3的编码器功能通常用 o u t p u t s t r i d e = 16 output stride=16 outputstride=16计算。这些特征被双线性上采样16倍,这可以被认为是一个最初的解码器模块。但是,这个最初的解码器模块可能无法成功恢复对象分割细节。因此,我们提出了一个简单而有效的解码器模块,如图2所示。编码器特征首先进行双线性上采样4倍,然后与具有相同功能的网络主干中具有相同空间分辨率(例如,在ResNet-101中跨步之前的Conv2)的低级特征连接起来。由于相应的低级特征通常包含大量通道(例如256或512),因此我们可能会对低级特征进行另一次1×1卷积以减少通道数量,这可能会超出丰富编码器功能的重要性(我们的模型中只有256个通道),使训练更加困难。在连接之后,我们应用几个3×3的卷积来细化特征,然后进行另一个简单的双线性上采样4倍。我们在第4节使用 o u t p u t s t r i d e = 16 output stride= 16 outputstride=16作为编码器模块在速度和精度之间取得最佳平衡。当使用 o u t p u t s t r i d e = 8 output stride = 8 outputstride=8作为编码器模块时,以额外的计算复杂性为代价,性能略有提高。
在这里插入图片描述
图2. 我们提出的DeepLabv3 +采用编码器解码器结构扩展了DeepLabv3。 编码器模块通过在多个尺度上应用atrous卷积来编码多尺度上下文信息,而简单但有效的解码器模块沿着对象边界细化分割结果。

3.2 修正对齐Xception

Xception模型在ImageNet上展示了具有快速计算能力的图像分类结果。最近,MSRA团队修改了Xception模型(称为Aligned Xception),并进一步推动了对象检测任务的性能。在这些发现的推动下,我们以相同的方向努力使Xception模型适应语义图像分割的任务。特别是,我们在MSRA的修改之上做了一些更改,即(1)与更深的Xception相似,不同之处在于我们不修改入口流网络结构以实现快速计算和内存效率,(2)所有最大值池化操作被带有步长的深度可分离卷积替换,这使我们能够应用atrous可分离卷积以任意分辨率提取特征映射(另一种选择是将atrous算法扩展到最大池化操作),以及(3)额外的批量归一化和在每次3×3深度卷积之后添加ReLU激活,类似于MobileNet设计。修改后的Xception结构如图3所示。

在这里插入图片描述
图3。 Xception模型修改如下:(1)更多层(与MSRA的修改相同,但Entry流中的更改除外),(2)所有最大池化操作都由具有跨步的深度可分离卷积替换,以及(3) 在每次3×3深度卷积之后添加额外批量标准化和ReLU,类似于MobileNet。

4 实验评估

我们采用ResNet-101或修改后的对齐Xception,它们在ImageNet-1k数据集上预先训练,通过atrous卷积提取密集特征图。我们的实施基于TensorFlow并公开发布。

所提出的模型在PASCAL VOC 2012语义分割基准上进行评估,其中包含20个前景对象类和一个背景类。 原始数据集包含1464(训练),1449(验证)和1456(测试)像素级注释图像。 我们通过额外的注释来扩充数据集,从而生成10582(训练增强)训练图像。性能是根据21个类别(mIOU)平均的像素交叉结合来衡量的。

简而言之,我们采用相同的学习率计划(即“poly”策略和相同的初始学习率0.007),crop大小513×513,当 o u t p u t s t r i d e = 16 output stride=16 outputstride=16时微调批量标准化参数,以及训练期间的随机比例数据增加。请注意,我们还在建议的解码器模块中包含批量标准化参数。 我们提出的模型是端到端训练的,没有对每个组件进行分段预训练。

4.1 解码器设计选择

我们首先将“DeepLabv3 特征图”定义为DeepLabv3计算的最后一个特征图(即包含ASPP特征,图像级特征等的特征)和 [ k × k , f ] [k×k, f] [k×k,f]作为内核大小为 k × k k×k k×k f f f滤波器的卷积运算。

当使用 o u t p u t s t r i d e = 16 output stride = 16 outputstride=16时,基于ResNet-101的DeepLabv3在训练和评估期间对logits进行双线性上采样16。 这种简单的双线性上采样可以被认为是一种naive的解码器设计,在PASCAL VOC2012上设置的性能达到77.21%并且比在训练期间不使用这种解码器好1.2%(即,下采样groundtruth 在训练中)。 为了改善这个原始的基线,我们提出的模型“DeepLabv3 +”在编码器输出的顶部添加了解码器模块,如图2所示。在解码器模块中,我们考虑三个不同设计选择的位置,即(1) 1×1卷积用于减少来自编码器模块的低级特征映射的通道,(2)用于获得更清晰分割结果的3×3卷积,以及(3)应使用哪些编码器低级特征。

在这里插入图片描述
表1. 用于减少来自编码器模块的低级特征映射的通道的解码器1×1卷积的效果。 我们将解码器结构中的其他组件固定为使用 [ 3 × 3 , 256 ] [3×3, 256] [3×3,256]和Conv2(striding前)的VOC 2012 val set的性能。

为了评估1×1卷积在解码器模块中的效果,我们采用 [ 3 × 3 , 256 ] [3×3, 256] [3×3,256]及来自ResNet-101网络主干的Conv2特征,即res2x残差块中的最后一个特征图(具体来说,我们在跨步之前使用特征图)。 如表格1所示,将低级特征映射的通道从编码器模块减少到48或32导致更好的性能。 因此我们采用 [ 1 × 1 , 48 ] [1×1, 48] [1×1,48]减少通道。

然后,我们为解码器模块设计3×3卷积结构,并在表2中报告结果。我们发现在使用DeepLabv3特征图连接Conv2特征图(在跨步之前)之后,使用两个3×3卷积的256个滤波器比使用简单的一个或三个卷积更有效。将滤波器的数量从256更改为128或将内核大小从3×3更改为1×1会降低性能。我们还试验了在解码器模块中利用Conv2和Conv3特征映射的情况。在这种情况下,解码器特征图以步长2逐渐上采样,首先与Conv3连接,然后与Conv2连接,并且每个将由 [ 3 × 3 , 256 ] [3×3, 256] [3×3,256]操作。然后整个解码过程类似于UNet / SegNet设计。但是,我们没有观察到显着的改善。因此,最后,我们采用了非常简单但有效的解码器模块:DeepLabv3特征映射和通道缩减的Conv2特征映射的串联由两个 [ 3 × 3 , 256 ] [3×3, 256] [3×3,256]操作。请注意,我们提出的DeepLabv3 +模型的 o u t p u t s t r i d e = 4 output stride = 4 outputstride=4。在GPU资源有限的情况下,我们不再追求更密集的输出特征映射(即 o u t p u t s t r i d e < 4 output stride<4 outputstride<4)。

在这里插入图片描述
表2. 固定[1×1,48]以减少编码器特征通道时解码器结构的影响。 我们发现使用Conv2(striding前)特征图和两个额外的[3×3,256]操作是最有效的。 VOC 2012 val set的性能。

4.2 ResNet-101作网络主干

为了在准确性和速度方面比较模型变体,我们在表3中报告了mIOU和Multiply-Adds。在提议的DeepLabv3 +模型中使用ResNet-101作为网络主干。由于atrous的卷积,我们能够使用单个模型在训练和评估过程中获得不同分辨率的特征。

在这里插入图片描述
表3. 使用ResNet 101作为特征提取器时,PASCAL VOC 2012 val设置的推理策略。 训练OS:训练期间使用的输出步幅。 eval OS:评估期间使用的输出步幅。 解码器:采用所提出的解码器结构。 MS:评估期间的多尺度输入。 翻转:添加左右翻转输入。

基线:表3中的第一个行块。 表明在评估期间提取更密集的特征图(即, e v a l o u t p u t s t r i d e = 8 eval output stride= 8 evaloutputstride=8)并采用多尺度输入提高了性能。 此外,添加左右翻转输入会使计算复杂性增加一倍,而性能只会略微提高。

添加解码器:表3中的第二个行块。 图3包含采用所提出的解码器结构时的结果。 当使用 e v a l o u t p u t s t r i d e = 16 eval output stride = 16 evaloutputstride=16或8时,性能从77.21%提高到78.85%或78.51%到79.35%,代价是大约20B额外的计算开销。使用多尺度和左右翻转输入时,性能得到进一步提高。

更粗略的特征图:我们还试验了 t r a i n o u t p u t s t r i d e = 32 train output stride=32 trainoutputstride=32(即,在训练期间根本没有任何atrous卷积)进行快速计算的情况。如表3中的第三行块所示。添加解码器带来2%的改进,而只需要74.20B的Multiply-Adds。然而,在我们采用 t r a i n o u t p u t s t r i d e = 16 train output stride = 16 trainoutputstride=16和不同的 e v a l o u t p u t s t r i d e eval output stride evaloutputstride值的情况下,性能总是约1%至1.5%。在训练或评估过程中,根据复杂度预算, 我们更倾向于使用 o u t p u t s t r i d e = 16 output stride = 16 outputstride=16或8。

4.3 作为网络骨干的Xception

我们进一步采用更强大的Xception作为网络骨干。 我们进行了一些更改,如第3.2节所述。

ImageNet预训练:提议的Xception网络在ImageNet-1k数据集上预先训练,使用类似的训练方法。具体来说,我们采用Nesterov动量优化器,动量= 0.9,初始学习率= 0.05,每2个周期rate衰减=0.94,权量衰减4e-5。我们使用50个GPU的异步训练,每个GPU的批量大小为32,图像大小299×299。由于目标是在ImageNet上对模型进行预训练以进行语义分割,因此我们并未对超参数进行非常困难的调整。表4为验证集上随着基线在同一训练协议下reproduced ResNet-101的单模型错误率。 我们观察到在修改的Xception中每次3×3深度卷积后没有添加额外批量标准化和ReLU时,Top1和Top5精度的性能降低0.75%和0.29%。

在这里插入图片描述

表4. ImageNet-1K验证集上的单模型错误率。

表5中报告了使用所提出的Xception作为语义分割的网络主干的结果。

在这里插入图片描述
表5. 使用修改的Xception作为特征提取器时,PASCAL VOC 2012 val设置的推理策略。 训练OS:训练期间使用的输出步幅。 eval OS:评估期间使用的输出步幅。 解码器:采用所提出的解码器结构。 MS:评估期间的多尺度输入。 翻转:添加左右翻转输入。 SC:对ASPP和解码器模块采用深度可分离卷积。 COCO:在MS-COCO上模型预训练。JFT:在JFT上模型预训练。

基线:我们首先在表5中的第一行块中不使用建议的解码器报告结果。示出了在使用ResNet-101的情况下,当 t r a i n o u t p u t s t r i d e = e v a l o u t p u t s t r i d e = 16 train output stride = eval output stride = 16 trainoutputstride=evaloutputstride=16时,使用Xception作为网络主干将性能提高约2%。 通过使用平均 o u t p u t s t r i d e = 8 output stride = 8 outputstride=8,在期间进行多尺度输入并添加左右翻转输入,也可以获得进一步的改进。请注意,我们不使用多网格方法,我们发现这不会改善性能。

添加解码器:如表5中的第二行块所示。对于所有不同的参考策略,当使用 e v a l o u t p u t s t r i d e = 16 eval output stride = 16 evaloutputstride=16时,添加解码器会带来约0.8%的改进。 使用 e v a l o u t p u t s t r i d e = 8 eval output stride = 8 evaloutputstride=8时,改进变得更少。

使用深度可分卷积:通过深度可分卷积的有效计算,我们在ASPP和解码器模块中进一步采用它。 如表5中的第三行块所示。Multiply-Adds的计算复杂度显着降低了33%至41%,同时获得了类似的mIOU性能。

在这里插入图片描述
图5. 当使用训练输出时,mIOU作为对象边界周围的trimap带宽的函数stride = eval output stride = 16. BU:双线性上采样。采用所提出的解码器模块与初始双线性上采样(表示为BU)相比的定性效果。 在示例中,我们采用Xception作为特征提取器和列车输出stride = eval output stride = 16。

在COCO上进行预训练:为了与其他现有技术模型进行比较,我们进一步预先提取了我们在MS-COCO数据集上提出的DeepLabv3 +模型,这使得所有不同参考策略的性能提高了2%。

JFT上的预训练:我们还采用了已经在ImageNet-1k 和JFT-300M数据集上预训练的Xception模型,它带来了额外的0.8%到1%改进。

测试集结果:由于基准评估中未考虑计算复杂性,因此我们选择最佳性能模型并使用 o u t p u t s t r i d e = 8 output stride = 8 outputstride=8和frozen批量标准化参数进行训练。最后,我们的’DeepLabv3 +'在没有和使用JFT数据集预训练的情况下实现了87.8%和89.0%的性能。

定性结果:我们提供了图6中最佳模型的可视化结果。如图所示,我们的模型能够很好地分割对象而无需任何后处理。

在这里插入图片描述
图6. 使用我们最好的模型时,PASCAL VOC 2012 val设置的可视化结果。 最后一行显示了failure mode。

在这里插入图片描述

表6. 表现最佳的模型的PASCAL VOC 2012testset结果

4.4 沿对象边界的改进

在本小节中,我们使用trimap实验评估分割精度,以量化所提出的解码器模块在对象边界附近的准确性。具体来说,我们在val集上的’void’标签注释上应用形态学膨胀,这通常发生在对象边界周围。然后,我们计算那些在’void’标签的扩张带(称为trimap)内的像素的平均IOU。 如图4所示,与原始的双线性上采样相比,将ResNet-101和Xception网络骨干的所提出的解码器用于改善了性能。当扩张带狭窄时,改善更为显着。我们已经观察到ResNet-101和Xception在最小trimap宽度处分别有4.8%和5.4%的mIOU改进。我们还可视化使用图5中提出的解码器的效果。

4.5关于Cityscapes的实验结果

在本节中,我们在Cityscapes数据集上进行DeepLabv3+ 的实验,该数据集是包含5000张图像(分别用于训练,验证和测试集的2975、500和1525)的高质量像素级注释的大规模数据集, 20000张带有粗注释的图像。

如图7(a)所示,在DeepLabv3的基础上,采用建议的Xception模型作为网络主干(表示为X-65),其中包括ASPP模块和图像级功能,在DeepLabv3上的性能达到77.33%。 验证集。 添加建议的解码器模块可将性能显着提高到78.79%(提高1.46%)。 我们注意到,移除增强的图像级功能可将性能提高到79.14%,这表明在DeepLab模型中,图像级功能在PASCAL VOC 2012数据集上更有效。 我们还发现,在Cityscapes数据集上,在Xception的输入流程中增加更多层是有效的,与对象检测任务所做的相同。 在深层网络主干(表中表示为X-71)之上构建的模型获得了79.55%的最佳性能。

在验证集上找到最佳模型变体后,我们随后在粗略注释上进一步微调模型,以便与其他最新模型竞争。 如7(b)所示,我们的DeepLabv3 +达到了性能达到82.1%的测试集,达到了Cityscapes的最好结果。

在这里插入图片描述
表7. (a)使用train fine set训练后的Cityscapes val set上的DeepLabv3 +。(b)在Cityscapes test set上的DeepLabv3 +。该表仅列出了一些顶级型号。

5 结论

我们提出的模型“DeepLabv3 +”采用编码器解码器结构,其中DeepLabv3用于编码丰富的上下文信息,并且采用简单但有效的解码器模块来恢复对象边界。根据可用的计算资源,还可以应用atrous卷积以任意分辨率提取编码器特征。 我们还探索了Xception模型和atrous可分离卷积,使得所提出的模型更快更强。 最后,我们的实验结果表明,所提出的模型在PASCAL VOC 2012语义图像分割基准上达到最新性能。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值