Datawhale AI 夏令营-Task3

夏令营2期-deepfake音视频-baseline

一. 主要任务和相关知识点

主要任务

聚焦于数据增强方法,学会各种数据变换操作。数据增强不仅是深度学习训练过程中的重要环节,而且在参赛时也是提高模型精度的重要策略。通过对训练数据进行多样化的变换,我们可以模拟更真实的世界场景,从而帮助模型更好地泛化,这在提升模型在未见数据上的表现方面起着至关重要的作用。

  1. 提高方案精度效果,了解上分具体操作

  2. 学习不同的数据增强技术。

  3. 实施数据增强并评估其对模型性能的影响。

  4. 研究多模态学习理论和方法。

  5. 实现一个多模态分类模型,结合不同模态的特征。

相关知识点

  1. 数据集增强:通过对原有的真实图像和合成图像进行各种变换,以生成更多样化和丰富的训练样本。

  2. 多模态模型:指的是能够处理和生成多种模态数据(如图像、文本、音频等)的人工智能模型

实操代码地址:https://www.kaggle.com/code/finlay/deepfake-ffdv-ch3

二. 数据增强基础

数据增强在深度学习中是一种常用的技术,用于增加样本的多样性,提高模型的泛化能力。在deepfake领域,数据增强也发挥了重要的作用。

1. 数据增强的目的

  通过人工方式增加训练数据的多样性,从而提高模型的泛化能力,使其能够在未见过的数据上表现得更好。

以下是一些深度假脸生成中常见的数据增强技术

1. 镜像翻转:将真实人脸图片进行水平翻转,生成对称的新样本。这样可以增加样本的多样性,并减少模型对左右方向的依赖。

2. 高斯模糊:通过加入高斯噪声或对图像进行高斯模糊,可以增加样本的模糊度和模糊程度的范围。这有助于模型更好地处理模糊的人脸。

3. 图像旋转和缩放:随机旋转和缩放图像,可以增加样本的多样性,并且使模型对于不同的旋转和缩放变换更具鲁棒性。

4. 增加噪声:在真实人脸图像中添加不同类型和强度的噪声,如高斯噪声、椒盐噪声等,可以增加样本的多样性和鲁棒性。

5. 梯度扰动:通过对图像的像素梯度进行扰动,可以生成具有不同纹理和颜色变化的新样本。这有助于模型更好地处理不同纹理和颜色的人脸。

6. 图像合成:通过将不同的人脸部分进行合成,例如将一个人的眼睛、鼻子和嘴巴替换到另一个人的脸上,可以生成具有更多特定特征的新样本。

这些数据增强技术可以通过对真实人脸图像进行变换和合成来生成更多多样的深度假脸样本,帮助训练模型更好地学习和生成逼真的假脸图像。

2. 数据增强的作用

  1. 增加训练数据量:通过数据增强,可以生成更多的训练样本,从而增加模型的训练数据量。较大的训练数据集可以提升模型的泛化能力,减少过拟合。

  2. 改善模型的鲁棒性:数据增强可以引入更多的变化和噪声,使模型更加鲁棒,能够更好地处理不同的输入情况。例如,在图像分类任务中,可以使用随机翻转、旋转、缩放等操作,使模型对于不同角度、大小和位置的物体有更好的识别能力。

  3. 提升模型的抗干扰能力:通过数据增强,可以模拟真实世界中的各种干扰和噪声,从而提高模型的抗干扰能力。例如,在语音识别任务中,可以模拟不同的噪声环境,让模型更好地适应各种噪声情况。

  4. 扩展模型的应用范围:通过数据增强,可以生成更多种类的样本,从而扩展模型的应用范围。例如,在图像生成任务中,可以使用随机裁剪、旋转、变换颜色等操作,生成更多样式的图像。

总而言之,数据增强能够提高模型的泛化能力、鲁棒性和抗干扰能力,从而使模型在不同场景下具有更好的性能表现。

from PIL import Image, ImageEnhance
import os
import random
import shutil
def augment_image(image_path, save_path):
    img = cv2.imread(image_path)
    image_name = os.path.basename(image_path)  # 获取图片名称
    split_result = image_name.split('.')
    name = split_result[:-1]
    extension = split_result[-1]
    # cv2.imshow("1",img)
    # cv2.waitKey(5000)
    # 旋转
    rotated_90 = rotate(img, 90)
    cv2.imwrite(save_path +  "".join(name) + '_r90.'+ extension, rotated_90)
    rotated_180 = rotate(img, 180)
    cv2.imwrite(save_path +  "".join(name) + '_r180.'+ extension, rotated_180)
    flipped_img = flip(img)
    cv2.imwrite(save_path +  "".join(name) + '_fli.'+ extension, flipped_img)
 
    # 增加噪声
    # img_salt = SaltAndPepper(img, 0.3)
    # cv2.imwrite(save_path + img_name[0:7] + '_salt.jpg', img_salt)
    img_gauss = addGaussianNoise(img, 0.3)
    cv2.imwrite(save_path +  "".join(name) + '_noise.'+ extension,img_gauss)
 
    #变亮、变暗
    img_darker = darker(img)
    cv2.imwrite(save_path +  "".join(name) + '_darker.'+ extension, img_darker)
    img_brighter = brighter(img)
    cv2.imwrite(save_path +  "".join(name) + '_brighter.'+ extension, img_brighter)
 
    blur = cv2.GaussianBlur(img, (7, 7), 1.5)
    #      cv2.GaussianBlur(图像,卷积核,标准差)
    cv2.imwrite(save_path +  "".join(name) + '_blur.'+ extension,blur)
target_num = 2000  # 目标增强图片数量
image_folder = 'D:/plantsdata/data/train/'  # 图片文件夹路径
save_folder = 'D:/plantsdata/data/train_with_augmentation/'  # 保存增强后的图片的文件夹路径
# 获取所有类别的文件夹路径
class_folders = os.listdir(image_folder)
 
# 遍历类别文件夹
for class_folder in class_folders:
    if not os.path.isdir(os.path.join(image_folder, class_folder)):
         continue
    target_subfolder = os.path.join(save_folder,class_folder)
    os.makedirs(target_subfolder, exist_ok=True)
    image_list = os.listdir(os.path.join(image_folder, class_folder))
    # 获取当前文件夹中所有图片的路径
    images = []
    for file_name in image_list:
        images.append(os.path.join(image_folder, class_folder, file_name))
    num_images = len(images)
    print(num_images)
    print(target_num)
    if num_images < target_num:
        for image_path in images:
            with Image.open(image_path) as img:
                name = os.path.basename(image_path)
                target_path = os.path.join(target_subfolder, name)
                shutil.copy(image_path, target_path)
        i = num_images
        j = 0
        random_image = random.sample(image_list,k=num_images)
        while i<target_num and j<=num_images-1:
            image_path = os.path.join(image_folder, class_folder, random_image[j])
            target_path = target_subfolder + '/'
            augment_image(image_path, target_path)
            i+=7
            j+=1
            print(i)
    else:
        # 随机选择2000张图片
        selected_images = random.sample(images,k=2000)
        # 将选中的图片复制到目标文件夹
        for image_path in selected_images:
            with Image.open(image_path) as img:
                name = os.path.basename(image_path)
                target_path = os.path.join(target_subfolder, name)
                shutil.copy(image_path, target_path)

数据增强将文件夹中的每个类别的文件夹中的图片数据首先复制到目标文件夹,如果大于2000张随机挑选2000张图片复制,不够的画在进行数据增强,目标每个类别2000张,如果类别文件夹的图片数量太小,那就缩小目标数目,或者在找些图片.

3. 过度数据增强

在深度伪造技术(deepfake)中,过度数据增强是指过度使用合成图像或视频数据来训练一个模型,以使其能够生成更真实的伪造内容。这种方法可能导致模型过度拟合,无法准确地识别和处理真实的数据。

过度数据增强可能导致以下问题

1. 生成过于真实的伪造内容:如果模型过度拟合于合成数据,它可能会生成非常逼真的伪造内容。这可能让人很难分辨出真实和伪造的图像或视频。

2. 无法处理真实的数据:由于模型过度依赖于合成数据,它可能无法正确处理真实的数据。这意味着它可能误分类真实的数据,或者无法生成逼真的伪造内容。

3. 增加模型的复杂性:过度数据增强会增加模型的复杂性和参数量,使其更难训练和优化。这可能导致性能下降或训练时间延长。

为了避免过度数据增强的问题,可以采取以下策略

1. 多样化的数据集:使用多样化的真实数据集来训练模型,包括不同的人脸、场景和环境。这样可以提供更广泛的训练样本,使模型更能应对真实的数据。

2. 限制合成数据的使用:合成数据可以用来增强训练数据,但不应构成主要的训练数据集。应确保真实数据的比例较大,以确保模型能够准确地处理和生成真实的内容。

3. 正则化和优化:使用正则化技术和模型优化方法来减少过度拟合的风险。这包括使用正则化项、早停和交叉验证等技术来避免模型对训练数据过度拟合。

总之,过度数据增强可能会导致深度伪造技术的性能和鲁棒性问题。为了确保模型能够处理真实的数据并生成逼真的伪造内容,需要采取适当的训练策略和正则化方法。

三. 图像数据增强方法

在深度伪造(Deepfake)中,图像数据增强方法可以用于提高生成图像的质量和多样性。以下是一些常用的图像数据增强方法:

1. 图像旋转和翻转:通过随机旋转图像角度或水平翻转图像,在不改变主要信息的情况下增加样本的多样性。

2. 图像缩放和裁剪:通过随机缩放或裁剪图像,改变图像的尺寸和组合,增加不同比例和位置的图像样本。

3. 图像平移和扭曲:通过随机平移和扭曲图像,改变图像的位置和形状,增加不同位置和形态的图像样本。

4. 增加噪声:通过在图像中添加随机噪声,如高斯噪声、椒盐噪声等,增加图像的真实性和鲁棒性。

5. 调整亮度和对比度:通过调整图像的亮度、对比度和色彩平衡等参数,改变图像的显示效果,增加样本的差异。

6. 图像变换和滤波:通过应用不同的图像变换和滤波器,如图像模糊、锐化、边缘检测等,改变图像的纹理和细节,增加样本的多样性。

7. 随机遮挡和遮蔽:通过随机生成遮挡物或遮蔽部分图像,模拟实际场景下的遮挡情况,增加图像样本的复杂性。

这些方法可以单独或组合使用,根据具体的应用场景和需求进行选择和调整,以增加深度伪造模型的性能和鲁棒性。

自动增强方法

指通过使用算法和技术来提高Deepfake的质量和逼真度。以下是几种常见的自动增强方法:

  1. 对抗生成网络(GAN):GAN是Deepfake中常用的技术。通过训练一个生成器和一个判别器,生成器生成虚假视频,而判别器则用于区分真实视频和虚假视频。生成器和判别器通过博弈的方式相互学习,使得生成的视频越来越接近真实视频。

  2. Attention机制:Attention机制是一种在深度学习模型中引入的注意力机制。在Deepfake中,使用Attention机制可以将模型的注意力集中在重要的特征上,从而增强视频的质量和真实感。

  3. 数据增强:数据增强是一种通过对训练数据进行变换和扩充来增加训练集大小和多样性的方法。在Deepfake中,可以使用各种数据增强技术,如旋转、缩放、平移等来增加数据的多样性,进而提高模型的泛化能力和生成效果。

  4. 上下文感知方法:上下文感知方法是指通过分析图像或视频的上下文信息来改善Deepfake的结果。例如,可以使用语义分割模型来理解图像中的语义信息,并根据这些信息对生成的视频进行调整和优化。

  5. 长期记忆机制:长期记忆机制是一种在深度学习模型中引入的记忆单元,用于捕捉长期依赖关系。在Deepfake中,使用长期记忆机制可以提供更好的时间一致性和连续性,使生成的视频更加自然和逼真。

这些自动增强方法可以结合使用,以提高Deepfake生成的视频的质量和真实度。然而,需要注意的是,Deepfake技术也有许多潜在的风险和问题,如滥用、欺诈和隐私侵犯等,因此必须谨慎使用和监管。、

方法解释

MixUpxuagxu

将两张图片按照一定透明程度混合成一张新的图片

源码中,每次只有10%的概率启用

MixUp是一种数据增强技术,其原理是通过将两个不同的图像及其标签按照一定的比例混合,从而创建一个新的训练样本。这种方法可以增加训练数据的多样性,提高模型的泛化能力,并减少过拟合的风险。MixUp方法中混合比例是一个超参数,通常称为alphaalpha是一个在0到1之间的值,表示混合的比例。例如,alpha=0.5意味着两个图像各占新图像的一半。

MixUp的混合过程包括以下步骤:

  1. 从训练集中随机选择两个图像和它们的标签。

  2. 将这两个图像按照alpha的比例混合,得到一个新的图像。

  3. 将这两个标签按照相同的alpha比例混合,得到一个新的标签。

MixUp方法具有以下几个优点

  1. 增加数据多样性:通过混合不同的图像和标签,MixUp可以创建更多样化的训练样本,帮助模型学习到更加鲁棒的特征表示。

  2. 减少过拟合:MixUp可以减少模型对特定训练样本的依赖,从而降低过拟合的风险。

  3. 提高泛化能力:MixUp可以帮助模型学习到更加泛化的特征表示,从而提高模型在未见过的数据上的表现。\

Cutmix

CutMix是一种数据增强技术,它通过将一个图像的一部分剪切并粘贴到另一个图像上来创建新的训练样本。同时,它也会根据剪切区域的大小来调整两个图像的标签。

CutMix方法中,剪切和粘贴操作是关键步骤。具体来说,剪切和粘贴过程包括以下步骤:

  1. 从训练集中随机选择两个图像和它们的标签。

  2. 随机选择一个剪切区域的大小和位置。

  3. 将第一个图像的剪切区域粘贴到第二个图像上,得到一个新的图像。

  4. 根据剪切区域的大小,计算两个图像的标签的加权平均值,得到一个新的标签。

Mosaic

Mosaic是一种深度伪造(deepfake)技术,可以用于在视频中模糊或隐藏身份。它的名称来自于马赛克(mosaic),因为它可以通过对人脸或其他敏感信息进行像素化或模糊处理来保护隐私。

Mosaic的原理是通过将图像或视频中的特定区域与一个用于隐藏信息的模糊层进行合并。这个模糊层可以选择不同的模糊程度,从而实现不同水平的像素化或模糊效果。Mosaic还可以对特定的区域进行跟踪,以确保模糊层始终与隐私区域保持一致。

Mosaic是一种非常强大的工具,可以用于保护隐私和隐藏身份。它可以用于在深度伪造视频中模糊人脸,以防止个人身份的暴露。此外,Mosaic还可以用于模糊或隐藏其他敏感信息,如车牌号码、信用卡信息等。

然而,Mosaic也有一些局限性。首先,它只能模糊或隐藏特定的区域,而无法改变整个视频的内容。其次,虽然Mosaic可以对特定区域进行跟踪,但仍可能出现失真或不完全模糊的情况。因此,在使用Mosaic技术时,仍需谨慎考虑其局限性和潜在的不足之处。

4张图像使用随机缩放随机裁剪随机排布的方式拼接成一张图片

Copy paste

直接复制粘贴,但是数据集必须要求实例分割的数据标签

Random affine

仿射变换,即旋转,缩放,平移,错切

Albumentations

滤波、直方图均衡化以及改变图片质量等

是一个第三方包,安装了这个包就会启动。pip列表中是默认不去安装。

Augment HSV(Hue, Saturation,Value)

随机调整色度、饱和度、明度

Random horizontal flip

按一定比例,将图片按水平方向翻转

四. 音频数据增强方法

在Deepfake中,音频数据增强方法用于改善语音生成的质量和真实性。以下是一些常用的音频数据增强方法:

1. 音频合成:使用自然语言处理模型和语音合成模型生成与人脸视频同步的语音。这可以通过将深度学习的文本到语音合成模型与Deepfake模型结合来实现。

2. 声音平衡:通过调整音频的声音平衡来使其更加自然和真实。这可以通过调整音频的音量、音调和音频的频谱分布来实现。

3. 去噪:使用降噪算法或模型来减少音频中的噪声。这可以通过使用噪声抑制算法或降低音频信号中的噪声来实现。

4. 声音增强:使用音频增强算法或模型来增强音频信号的质量。这可以通过增加音频信号的幅度或增加音频信号中的音频频谱来实现。

5. 音频重建:使用音频重建算法或模型来恢复被破坏或损坏的音频信号。这可以通过重新构建音频信号的频率、相位和幅度来实现。

这些方法可以结合使用,以提高Deepfake中的音频生成质量和真实性。

Audio Data Augmentation — Torchaudio 2.3.0 documentation

音频数据增强的原理与图像数据增强类似,都是通过对原始数据进行一系列的变换操作,生成新的训练样本。这些变换模拟了真实世界中的变化,例如时间尺度、音调、噪声、房间环境等,使得模型能够学习到更加鲁棒的特征表示。

  1. 时间拉伸和压缩:改变音频的时间尺度,模拟不同的说话速度或音乐播放速度。

  2. 音调变换:改变音频的音调,模拟不同的说话人或乐器。

  3. 添加噪声:向音频中添加不同类型的噪声,如白噪声、粉红噪声等,以提高模型对噪声的抗干扰能力。

  4. 频率掩码和时间掩码:在频谱图上随机掩盖一些频率或时间区域,迫使模型学习到更加鲁棒的特征表示。

  5. 混响:模拟不同的房间环境,增加音频的丰富性。

  6. 声道分离:将多声道音频中的某些声道分离出来,训练模型对不同声道特征的学习。

  7. 音量调整:调整音频的音量,模拟不同的音量大小。

五.  动手实践

在之前的代码中我们使用PyTorch框架来加载和增强图像数据:

  1. 图像大小调整:使用transforms.Resize((256, 256))将所有图像调整到256x256像素的尺寸,这有助于确保输入数据的一致性。

  2. 随机水平翻转transforms.RandomHorizontalFlip()随机地水平翻转图像,这种变换可以模拟物体在不同方向上的观察,从而增强模型的泛化能力。

  3. 随机垂直翻转transforms.RandomVerticalFlip()随机地垂直翻转图像,这同样是为了增加数据多样性,让模型能够学习到不同视角下的特征。

  4. 转换为张量transforms.ToTensor()将图像数据转换为PyTorch的Tensor格式,这是在深度学习中处理图像数据的常用格式。

  5. 归一化transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])对图像进行归一化处理,这里的均值和标准差是根据ImageNet数据集计算得出的,用于将图像像素值标准化,这有助于模型的训练稳定性和收敛速度。

train_loader = torch.utils.data.DataLoader(
    FFDIDataset(train_label['path'].head(1000), train_label['target'].head(1000), 
            transforms.Compose([
                        transforms.Resize((256, 256)),
                        transforms.RandomHorizontalFlip(),
                        transforms.RandomVerticalFlip(),
                        transforms.ToTensor(),
                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ])
    ), batch_size=40, shuffle=True, num_workers=4, pin_memory=True
)

val_loader = torch.utils.data.DataLoader(
    FFDIDataset(val_label['path'].head(1000), val_label['target'].head(1000), 
            transforms.Compose([
                        transforms.Resize((256, 256)),
                        transforms.ToTensor(),
                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ])
    ), batch_size=40, shuffle=False, num_workers=4, pin_memory=True
)

这段代码是用 PyTorch 中的 DataLoader 类来创建训练集和验证集的数据加载器。数据加载器用于批量加载数据,方便模型训练和验证。下面是对代码中的数据加载过程的解释:

1. **train_loader**:
   - 从名为 `train_label` 的 DataFrame 中获取前1000个样本的路径和目标标签。
   - 使用 `FFDIDataset` 类来创建训练集数据集,其中包括路径和目标标签,以及一系列图像预处理操作。
   - 图像预处理操作包括将图像大小调整为 (256, 256)、随机水平翻转、随机垂直翻转、转换为张量、以及对图像进行归一化。
   - 将创建好的数据集传入 DataLoader 类中,设置批量大小为 40,打乱数据集,使用4个子进程加载数据,同时将数据存储在固定的内存中。

2. **val_loader**:
   - 从名为 `val_label` 的 DataFrame 中获取前1000个样本的路径和目标标签。
   - 使用 `FFDIDataset` 类来创建验证集数据集,包括路径和目标标签,以及图像预处理操作。
   - 图像预处理操作包括将图像大小调整为 (256, 256)、转换为张量、以及对图像进行归一化。
   - 将创建好的数据集传入 DataLoader 类中,设置批量大小为 40,不打乱数据集,使用4个子进程加载数据,同时将数据存储在固定的内存中。

这段代码的作用是准备训练集和验证集的数据加载器,以便后续在训练和验证模型时使用。确保数据加载器的设置与模型的输入要求相匹配,以保证顺利进行训练和验证过程。

六. 思考拓展

实现一个多模态分类模型可以使用以下步骤:

1. 收集和预处理数据:收集不同模态的特征数据,并对数据进行预处理,确保数据是可用的。预处理步骤可以包括数据清洗、去除噪声、标准化或归一化等。

2. 特征融合:将不同模态的特征进行融合,可以使用多种方法,如特征串联、特征叠加、特征加权等。融合后的特征可以用于后续模型训练。

3. 模型选择:选择适合多模态数据的分类模型。常见的模型包括神经网络模型(如多层感知机、卷积神经网络、循环神经网络等)、支持向量机、决策树等。选择合适的模型需要考虑数据的特性和任务的要求。

4. 模型训练和调优:使用融合后的特征数据训练选择的模型,并对模型进行调优。可以使用交叉验证、调参等技术来提高模型的性能。

5. 模型评估:使用测试数据集评估模型的性能,可以选择合适的评估指标,如准确率、精确率、召回率、F1值等。

6. 模型应用:使用训练好的模型进行预测和分类任务。

需要注意的是,对于多模态数据的处理和模型选择,需要根据具体任务和数据的特性进行调整和优化。同时,也可以使用特征选择、集成学习等方法来进一步提升模型性能。

多模态分类模型通常包含以下几个关键组件

  1. 输入层:用于接收不同模态的输入数据。每个模态的输入可以有不同的形式和表示,比如图像可以用像素表示,文本可以用词袋模型或词嵌入表示。

  2. 模态嵌入层:将不同的模态表示转换成统一的嵌入表示。这可以通过神经网络(比如卷积神经网络)或者其他特征提取方法来实现。

  3. 融合层:将多个模态的嵌入表示结合起来,生成一个综合的表示。常用的方法包括拼接、加权平均等。

  4. 分类层:利用综合的表示进行分类任务,可以是多分类或二分类。一般可以使用全连接神经网络进行分类,也可以使用其他分类方法。

多模态分类模型的训练可以使用监督学习方法,通过最小化分类误差或交叉熵损失来优化模型参数。训练数据可以同时包含不同模态的输入和对应的标签。

import numpy as np
import torch
import torchvision.models as models
import torchvision.transforms as transforms
from PIL import Image

# 加载预训练的模型
model = models.resnet50(pretrained=True)

# 图像预处理和转换
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

# 文本特征提取函数
def extract_text_features(text):
    # 在这里实现文本特征提取的逻辑
    pass

# 模态融合函数
def fuse_modalities(image_features, text_features):
    # 在这里实现模态融合的逻辑
    pass

# 多模态分类函数
def classify(image, text):
    # 图像特征提取
    image = Image.open(image)
    image = transform(image)
    image = torch.unsqueeze(image, 0)
    image_features = model(image)

    # 文本特征提取
    text_features = extract_text_features(text)

    # 模态融合
    fused_features = fuse_modalities(image_features, text_features)

    # 模型预测
    # 在这里实现分类模型的预测逻辑
    pass

# 示例用法
image_path = 'path/to/image.jpg'
text = 'This is an example sentence.'
classify(image_path, text)

上面的示例代码使用了PyTorch框架和ResNet-50模型来提取图像特征。

七. 附言

部分内容引用:

『数据增强』yolov5 数据增强 与 红外数据增强_yolov5数据增强-CSDN博客

Docs

深度学习进行数据增强(实战篇)_我理解的是划分完数据集后只对train数据集进行增强就行,但是这个划分比例不就冲突-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值