阅读Skeleton-Based Action Recognition with Multi-Stream Adaptive Graph Convolutional Networks

前言:最近在阅读论文源码,发现2s-GCN中的源码中有两个net。其中agcn是2s-GCN的源码,aagcn(attention&adaptive)则是本文的源码。说实话,改进不大,但当时看了半天,和原论文对不上,之后在github的issue上作者也进行了解释。


Abstract

图卷积网络(GCNs)将CNNs推广到更一般的非欧氏结构,在基于骨架的动作识别中取得了显著的性能。然而,以往基于GCN的模型仍然存在一些问题。首先,在所有模型层和输入数据上对图的拓扑结构进行启发式设置和固定。这可能不适用于GCN模型的层次结构和动作识别任务中数据的多样性。第二,骨骼数据的二阶信息,即骨骼的长度和方向,很少被研究,这对于人类动作识别来说自然是更具informative 和辨别性的。在这项工作中,作者提出了一种新的多流注意增强自适应图卷积神经网络(MS-AAGCN),用于基于骨架的动作识别。作者模型中的图拓扑可以基于端到端的输入数据统一地或单独地学习。这种数据驱动的方法增加了模型的灵活性,使其更具通用性,以适应不同的数据样本。此外,通过一个时空通道注意模块进一步增强了自适应图卷积层,使模型更加关注重要的关节、帧和特征。此外,在多流框架下,对关节和骨骼的信息以及它们的运动信息进行了同步建模,提高了识别精度。在NTU-RGBD和Kinetics-Skeleton这两个大型数据集上的大量实验表明,作者模型的性能 state-of-the-art,具有显著的优势。
作者创新:增加了attention和adaptive机制,构建了MS-AAGCN;同时将关节点和骨架作为图网络构成。-(个人理解)

Introduction

大致意思是说基于骨架的识别优越性,引出ST-GCN的非欧几里得空间的优越性。列出三个ST-GCN的缺点:

  • ST-GCN中使用的骨架图是基于人体的自然连通性进行启发式预定义的。因此,不能保证它对于动作识别任务是最优的。
  • 神经网络是分层的,不同的层包含不同的语义层次。然而,ST-GCN中应用的图的拓扑结构在所有层上都是固定的,缺乏对不同层中包含的多级语义进行建模的灵活性和能力。
  • 对于不同动作类的所有样本,一个固定的图结构可能不是最优的。

  为了解决上述问题,author提出了一种新的自适应图卷积层。它参数化了两种自适应图的卷积。一种是全局图,它是基于从数据集中提取的知识,通过学习图的邻接矩阵而得到的。学习过程使用基于任务的损失。因此,所得到的图形拓扑比以往基于人体的图形更适合于动作识别任务。另一个称为独立图,根据图顶点之间的特征相似度构建边。由于数据样本是多样的,模块可以为每个输入捕获一个独特的结构。利用门控机制将这两类图进行融合,可以自适应地调整它们在模型层中的重要性。需要注意的是,这两个图在不同的层上都是单独优化的,因此它可以更好地适应神经网络的层次结构。总之,这种数据驱动的方法增加了模型的灵活性,使其更具通用性,以适应不同的数据样本。
  此外,由于注意机制在许多任务中已经被证明是有效的和必要的,因此有必要对其进行研究,以实现基于骨架的动作识别。从空间的角度来看,某种行为通常与关节的一个关键子集相关联,并以其为特征。从时间的角度来看,动作流可能包含多个阶段,其中不同的子阶段或帧对于最终识别具有不同的重要性。从特征角度看,卷积特征映射的多个通道包含多个层次的语义。对于不同的操作和数据样本,每个通道扮演不同的角色。这些观察结果启发我们设计一个时空通道(STC)注意模块来自适应地重新校准不同数据样本的关节、帧和通道的激活。该模块被插入到每个图形卷积层中,虽然参数量小,但性能得到了提高。
  在以前的方法中,另一个值得注意的问题是附加到每个顶点的特征向量只包含关节的二维或三维坐标。我们称之为骨架数据的一阶信息。但是,表示两个关节之间骨骼特征的二阶信息没有被利用。通常情况下,骨骼的长度和方向对于动作识别来说自然更具信息性和辨别性。在这项工作中,我们将骨骼信息表示为从其源关节指向其目标关节的向量。此外,由于光流场在基于RGB的动作识别的时间流中已经被证明是一种有用的模式,对于骨骼数据,我们建议提取两个连续帧之间关节和骨骼的坐标差作为运动信息,以帮助建模行动。最后,将关节信息和骨骼信息以及它们的运动信息集成在一个多流框架中。所有的数据流都使用相同的架构,并且四个数据流的softmax分数被融合以产生最终的预测。
  此外,由于RGB数据包含比骨骼更丰富的外观信息,作者提供了与RGB模式的比较,并提出了一种骨骼引导裁剪策略来融合这两种模式。融合后的模型在NTU-RGBD数据集的CV和CS基准中的精度分别达到99%和96%,大大超过了其他方法。
  总体而言,本文的主要工作有四个方面:
(1)提出了一种自适应的图形卷积网络,以端到端的方式自适应地学习图形的拓扑结构,能够更好地适应动作识别任务、gcn的层次结构和不同的骨架样本。
(2) 提出了一种STC注意模块,并将其嵌入到每一个图形卷积层中,可以帮助模型学习有选择地关注区分性的关节、帧和信道。
(3) 本文首先将骨骼数据的二阶信息(bones)与一阶信息(joints)结合起来,使识别性能得到显著提高。我们进一步提取关节和骨骼的运动信息,并将这四种模式整合到一个多流框架中。
(4) 在两个基于骨架的大规模动作识别数据集上验证了该算法的有效性。与baseline STGCN相比,NTU-RGBD数据集的CV和CS benchmarks分别提高了+7.9%和+8.5%。将其与骨架引导的裁剪RGB数据相结合,得到了+2.8%和+6.1%的额外改进。
  论文是对前人工作若干方面的扩展。首先,author对所提出的全局图和个别图的合成方案进行优化,并引入一个选通机制来自适应地调整这两个图的重要性。其次,author提出了一个STC注意模块,它可以有效地帮助模型注意重要的关节、框架和特征。第三,我们将之前的模型扩展到一个多流框架,该框架集成了关节和骨骼的运动模式。author提供更广泛的实验、更全面的讨论和可视化,以证明所提出的模块和数据模式的有效性和必要性。采用这些设计的模型在基于骨架识别的NTU-RGBD数据集的交叉视图和交叉主题基准上分别达到了+1.1%和+1.5%的精度提高。最后,author提出了一种有效的姿态引导裁剪策略,将骨骼与RGB模式融合,表现出良好的性能。ablation study 显示了算法的效果。

Related Work

介绍了现阶段的相关工作。

GRAPH CONVOLUTIONAL NETWORKS

A.Graph construction

  一帧中的原始骨架数据总是由一系列向量表示。每个矢量表示相应人体关节的二维或三维坐标。一个完整的动作包含多个帧,对于不同的样本具有不同的长度。我们使用时空图来模拟这些关节之间的空间和时间维度的结构化信息。这里,空间维度是指同一帧中的关节,时间维度是指所有帧上的相同关节。
  图1中的左子图示出了构造的4个时空骨架图的示例,其中关节表示为顶点,它们在人体中的自然连接表示为空间边(图1中的橙色线,左)。对于时间维度,两个连续帧中的对应关节与图1(左)中绿线所示的时间边缘连接。将每个关节的坐标矢量设置为对应顶点的属性。由于图是内在的,并且是基于人体的自然连通性而构建的,我们称之为 human-body-based图。
在这里插入图片描述

B. Graph convolution

  图结构如上定义,对于空间维度。顶点 v i v_i vi上的图卷积操作表示为: f o u t = ∑ v i ∈ B i 1 Z i j f i n ( v j ) ⋅ w ( l i ( v j ) ) f_{out}=\sum_{v_i\in \mathcal{\Beta}_i}\frac{1}{Z_{ij}}f_{in}(v_j)\cdot w(l_i(v_j)) fout=viBiZij1fin(vj)w(li(vj))其中 f f f代表特征映射, v v v表示图的顶点。 B i \mathcal{\Beta}_i Bi表示 v i v_i vi卷积的采样区域,定义为目标顶点( v i v_i vi)的1-distance邻接顶点( v j v_j vj)。 w w w是类似于传统卷积运算的加权函数,它基于给定的输入提供一个权重向量。注意,卷积的权重向量的数目是固定的,而 B i \mathcal{\Beta}_i Bi中的顶点数目是可变的。因此,需要一个映射函数 l i l_i li将所有相邻的顶点映射到一个固定编号的子集中,每个子集都与一个唯一的权重向量相关联。图1中的右图显示了这种映射策略,其中×表示骨架的重心。 B i \mathcal{\Beta}_i Bi是曲线包围的采样区域。具体来说,该策略根据经验将内核大小设置为3,并自然地将 B i \mathcal{\Beta}_i Bi分为3个子集: S i 1 S_{i1} Si1是顶点本身(图1右侧的红色圆圈); S i 2 S_{i2} Si2是向心子集,它包含更接近重心的相邻顶点(绿点); S i 3 S_{i3} Si3是离心子集,它包含相邻的顶点离重心较远的顶点(蓝点)。 Z i j Z_{ij} Zij代表 S i k S_{ik} Sik集合中的基数,包含 v j v_j vj。它旨在平衡每个子集的贡献。

C. Implementation

  空间图卷积的实现并不简单。Concretely,网络的特征映射是张量 f ∈ R C × T × N f\in \mathbb{R}^{C\times T\times N} fRC×T×N,其中N表示顶点数,T表示时间长度,C表示通道数。为了在代码中实现GCN,上述等式替换为 f o u t = ∑ k K v W k ( f i n A k ) f_{out}=\sum^{K_v}_kW_k(f_{in}A_k) fout=kKvWk(finAk)其中 K v K_v Kv表示空间维度的内核大小。使用上面设计的映射策略, K v K_v Kv设置为3. A k = Λ k − 1 2 A ˉ k Λ k − 1 2 A_k= \Lambda_k^{-\frac{1}{2}}\bar A_k\Lambda_k^{-\frac{1}{2}} Ak=Λk21AˉkΛk21。其中 A ˉ k ∈ R N × N \bar A_k\in \mathbb{R}^{N\times N} AˉkRN×N与邻接矩阵相似。它的元素 A ˉ k i j \bar A_k^{ij} Aˉkij表示顶点 v i v_i vi S i k S_{ik} Sik子集中的顶点 v j v_j vj(也就是三种邻接顶点)。它被用于从 f i n f_{in} fin中为相应的权重向量选择特定的子集中的连接顶点。 Λ k i i = ∑ j ( A ˉ k i j ) + α \Lambda_k^{ii}=\sum_j(\bar A_k^{ij})+\alpha Λkii=j(Aˉkij)+α是归一化对角矩阵。 α \alpha α设置为0.001以避免空行。 W k ∈ R C o u t × C i n × 1 × 1 W_k\in \mathbb{R}^{C_{out}\times C_{in}\times1\times1} WkRCout×Cin×1×1 1 × 1 1\times1 1×1卷积运算的权向量,表示1式中的权重函数 w w w
  对于时间维,由于每个顶点的邻域数目固定为2(两个相邻帧中的对应关节),因此执行与经典卷积操作类似的图形卷积是很简单的。具体来说,我们对上面计算的输出特征映射进行 K t × 1 K_t×1 Kt×1卷积,其中 K t K_t Kt是时间维的核大小。
  利用上述公式,对图进行多层时空卷积运算,提取高层特征。然后利用全局平均池层和softmax分类器对提取的特征进行动作类别预测。

MULTI-STREAM ATTENTION-ENHANCED ADAPTIVE GRAPH CONVOLUTIONAL NETWORK

  这章主要是介绍MS-AAGCN的细节。

A. Adaptive graph convolutional layer

  上述骨架数据的时空图卷积是基于内在的基于人体的图来计算的,这可能不是如第1节Introduce所述的最佳选择。为了解决这一问题,我们提出了一种自适应图卷积层。它以端到端的学习方式,使图的拓扑结构与网络的其他参数一起优化。该图对于不同的层和样本是unique(独特,表示层或样本都有自己的一个独特的图),这大大增加了模型的灵活性。同时,将其设计为残差分支,保证了原模型的稳定性。
  具体而言,根据式2,图实际上分别由邻接矩阵和掩模(即 A k A_k Ak M k M_k Mk)确定。 A k A_k Ak决定两个顶点之间是否有连接, M k M_k Mk决定连接的强度。为了使图拓扑自适应,我们将等式2修改为以下形式: f o u t = ∑ k K v W k f i n ( B k + α C k ) f_{out}=\sum^{K_v}_kW_kf_{in}(B_k+\alpha C_k) fout=kKvWkfin(Bk+αCk)主要区别在于图的邻接矩阵,它分为两个子图: B k B_k Bk C k C_k Ck
The first sub-graph( B k B_k Bk)是从数据中学习的全局图。它表示更适合动作识别任务的图形拓扑。它由基于人体的图形的邻接矩阵初始化,即,类似于等式2的 A k A_k Ak,但又不同于 A k A_k Ak B k B_k Bk的元素在训练过程中与其他参数一起被参数化和更新。 B k B_k Bk的值不受约束,这意味着图是根据训练数据完全学习的。通过这种数据驱动的方法,模型可以学习完全针对识别任务的图。 B k B_k Bk对于每个层都是独特的,因此对于包含在不同层中的不同级别的语义来说更加个性化。
The second sub-graph ( C k C_k Ck)是为每个样本学习唯一拓扑的独立图。为了确定两个顶点之间是否存在连接以及连接的强度,我们使用标准化的嵌入高斯函数来估计两个顶点的特征相似性,如下所示: f ( v i , v j ) = e θ ( v i ) T ϕ ( v j ) ∑ j = 1 N e θ ( v i ) T ϕ ( v j ) f(v_i,v_j)=\frac{e^{\theta(v_i)^T\phi(v_j)}}{\sum_{j=1}^{N} e^{\theta(v_i)^T\phi(v_j)}} f(vi,vj)=j=1Neθ(vi)Tϕ(vj)eθ(vi)Tϕ(vj)其中N是顶点数。作者使用点积来衡量嵌入空间中的两个顶点的相似性。具体来说,在给定输入特征映射 f i n ∈ R C i n × T × N f_{in}\in \mathbb{R}^{C_{in}\times T\times N} finRCin×T×N的情况下,首先将其嵌入到嵌入空间 R C e × T × N \mathbb{R}^{C_{e}\times T\times N} RCe×T×N中,嵌入函数有 θ \theta θ ϕ \phi ϕ两个。在这里,通过大量的实验,我们选择1x1卷积层作为嵌入函数。将两个嵌入的特征映射重构为矩阵 M θ k ∈ R N × C e T M_{\theta k}\in \mathbb{R}^{N×C_eT} MθkRN×CeT和矩阵 M ϕ k ∈ R C e T × N M_{\phi k}\in \mathbb{R}^{C_eT×N} MϕkRCeT×N。然后将它们相乘得到一个相似矩阵 C k ∈ R N × N C_k\in \mathbb{R}^{N×N} CkRN×N,其元素 C k i j C^{ij}_k Ckij表示顶点 v i v_i vi和顶点 v j v_j vj的相似性。矩阵的值被规范化为(0,1),用作两个顶点的soft edge。由于归一化高斯具有softmax操作,我们可以根据下面公式计算 C k C_k Ck,如下所示: C k = S o f t M a x ( f i n T W θ k T W ϕ k f i n ) C_k=SoftMax(f_{in}^TW_{\theta k}^TW_{\phi k}f_{in}) Ck=SoftMax(finTWθkTWϕkfin)其中 W θ ∈ R C e × C i n × 1 × 1 W_\theta \in \mathbb{R}^{C_{e}\times C_{in}\times1\times1} WθRCe×Cin×1×1 W ϕ ∈ R C e × C i n × 1 × 1 W_\phi \in \mathbb{R}^{C_{e}\times C_{in}\times1\times1} WϕRCe×Cin×1×1分别是嵌入函数 θ \theta θ ϕ \phi ϕ的参数。
  Gating mechanism门控机制:全局图决定了动作识别任务的基本图拓扑,单个图根据不同的样本特征增加了特有表征。在实验中,我们发现在顶层比底层对单个图的要求更高。这是合理的,因为底层的接收场较小,这限制了从不同样本中学习图形拓扑的能力。此外,顶层包含的信息更具语义性,更具变化性,对图形拓扑的个性化要求更高。单个图更容易满足要求,因为它是基于输入特征构造的,并且对于每个样本都是独立的。基于这些观察,我们使用一个选通机制来调整不同层的单个图的重要性。基于这些观察,我们用一个门控机制来调整不同层的个别图的重要性。In detail, C k C_k Ck乘以参数化系数 α \alpha α,这对于每一层来说都是unique,并且在训练过程中学习和更新。
在这里插入图片描述
Initialization:在实验中我们发现,在训练过程的早期,图的拓扑结构发生了很大的变化,从而导致了模型的不稳定性,影响了模型的收敛性。为了稳定训练,author尝试了两种策略。第一种策略是使用 A k + α B + β C k A_k+\alpha B+\beta C_k Ak+αB+βCk作为邻接矩阵,其中 A k A_k Ak是固定的基于人体的图, B k B_k Bk C k C_k Ck α \alpha α β \beta β初始化为0,因此, A k A_k Ak将主导训练的早期。第二种策略是初始化 B k B_k Bk A k A_k Ak,在训练过程的早期阻止 B k B_k Bk梯度的传播,直到训练稳定。第二种策略在后文中得到了稍微好一点的验证。嵌入函数的权重( θ \theta θ ϕ \phi ϕ)和融合系数α都初始化为0。
  自适应图卷积层(AGCL)的总体结构如图2所示。图卷积( K v K_v Kv)的核size(channel)被设置为3。 w k w_k wk是等式1中引入的加权函数,其参数 W k W_k Wk是等式3中引入的。每一层都添加了一个类似于何凯明的残差连接,这样就可以在不破坏其初始行为的情况下将该层插入到任何现有模型中。如果输入信道的数目与输出信道的数目不同,则在剩余路径中插入1×1卷积(图2中带虚线的橙色框)以将输入变换为与信道尺寸中的输出匹配。G是控制这两类图语义的门。
在这里插入图片描述
B. Attention module
  作者提出了一个STC注意模块,如图3所示。它包括三个子模块:空间注意模块、时间注意模块和通道注意模块。
  Spatial attention module (SAM) 可以帮助模型对每个关节进行不同程度的关注。计算如下: M s = δ ( g s ( A v g P o o l ( f i n ) ) ) M_s=\delta(g_s(AvgPool(f_{in}))) Ms=δ(gs(AvgPool(fin)))其中 f i n ∈ R C i n × T × N f_{in}\in \mathbb{R}^{C_{in}\times T\times N} finRCin×T×N是输入特征映射,在所有帧上取平均值。 g s g_s gs是一维卷积运算。 W g s ∈ R 1 × C i n × K s W_{g_s}\in \mathbb{R}^{1\times C_{in}\times K_s} WgsR1×Cin×Ks,其中, K s K_s Ks是卷积核size。 δ \delta δ表示Sigmoid激活函数。注意力图 M s ∈ R 1 × 1 × N M_s \in \mathbb{R}^{1\times 1\times N} MsR1×1×N然后以残差的方式与输入特征图相乘以进行自适应特征细化。
  Temporal attention module (TAM) 与SAM相似,计算如下: M t = δ ( g t ( A v g P o o l ( f i n ) ) ) M_t=\delta(g_t(AvgPool(f_{in}))) Mt=δ(gt(AvgPool(fin)))其中 M t ∈ R 1 × T × 1 M_t \in \mathbb{R}^{1\times T\times 1} MtR1×T×1,其他符号定义同上。
  Channel attention module (CAM) 可以帮助模型根据输入样本增强判别特征(通道)。它生成如下注意图: M c = δ ( W 2 ( δ ( W 1 ( A v g P o o l ( f i n ) ) ) ) ) M_c=\delta(W_2(\delta(W_1(AvgPool(f_{in}))))) Mc=δ(W2(δ(W1(AvgPool(fin)))))其中 f i n f_{in} fin是所有关节和框架上的均值。 M c ∈ R C × 1 × 1 M_c \in \mathbb{R}^{C\times 1\times 1} McRC×1×1 W 1 ∈ R C × C r W_1 \in \mathbb{R}^{C\times \frac{C}{r}} W1RC×rC W 2 ∈ R C r × C W_2 \in \mathbb{R}^{\frac{C}{r}\times C} W2RrC×C是两个全连接层的权重。 δ \delta δ表示ReLU激活函数。
  Arrangement of the attention modules: 上面介绍的三个子模块可以以不同的方式放置:并行方式或顺序方式。最后我们发现顺序方式更好,顺序是SAM、TAM和CAM。
C.Basic block
  时间维上的卷积与ST-GCN相同,即对 C × T × N C×T×N C×T×N特征映射进行 K t × 1 K_t×1 Kt×1卷积。空间GCN和时间TCN之后是批处理规范化(BN)层和ReLU层。如图4所示,一个基本块是一个空间GCN(Convs)、一个STC注意模块(STC)和一个时间GCN(Convt)的序列。为了稳定训练和减缓梯度传播,在每个基本块上增加一个残差连接。
在这里插入图片描述
D. Network architecture
  如图5所示,网络的总体架构是这些基本块的堆栈(图4)。一共有9个块。每个块的输出通道数为64、64、64、128、128、128、256、256和256。在开始处添加一个数据BN层以规范化输入数据。在结束相同大小的不同样本的池特征映射时,执行全局平均池化。最后的输出被发送到softmax分类器以获得预测结果。
在这里插入图片描述
E. Multi-stream networks
  如第一节所述。 一阶信息(关节的坐标)和二阶信息(骨骼的方向和长度)以及它们的运动信息都是基于骨骼的动作识别任务中值得研究的。在这项工作中,我们在一个多流框架中对这四种模式进行建模。
  特别是,我们定义离骨架重心较近的关节是源关节,离重心较远的关节是目标关节。每个骨骼都表示为从其源关节指向其目标关节的向量。例如,给定一个在t帧的骨骼,其源关节 v i , t = ( x i , t , y i , t , z i , t ) v_{i,t}=(x_{i,t},y_{i,t},z_{i,t}) vi,t=(xi,t,yi,t,zi,t)及其目标关节 v j , t = ( x j , t , y j , t , z j , t ) v_{j,t}=(x_{j,t},y_{j,t},z_{j,t}) vj,t=(xj,t,yj,t,zj,t),计算骨骼的向量为 e i , j , t = ( x j , t − x i , t , y j , t − y i , t , z j , t − z i , t ) e_{i,j,t}=(x_{j,t}-x_{i,t},y_{j,t}-y_{i,t},z_{j,t}-z_{i,t}) ei,j,t=(xj,txi,t,yj,tyi,t,zj,tzi,t)。由于骨骼数据的图形中没有循环,因此可以为每个骨骼指定一个唯一的目标关节。请注意,关节数比骨骼数多一个,因为根关节未指定给任何骨骼。为了简化网络的设计,我们将一个值为0的空骨骼指定给根关节。因此,可以将骨骼的图形和网络设计为与关节相同的图形和网络。我们分别使用J流和B流来表示关节和骨骼的网络。
  至于运动信息,则计算为两个连续帧中相同关节或骨骼之间的差分。例如,给定帧内T的连接,即 v i , t = ( x i , t , y i , t , z i , t ) v_{i,t}=(x_{i,t},y_{i,t},z_{i,t}) vi,t=(xi,t,yi,t,zi,t),以及帧t+1中的相同的关节点,即 v i , t + 1 = ( x i , t + 1 , y i , t + 1 , z i , t + 1 ) v_{i,t+1}=(x_{i,t+1},y_{i,t+1},z_{i,t+1}) vi,t+1=(xi,t+1,yi,t+1,zi,t+1) v i , t v_{i,t} vi,t v i , t + 1 v_{i,t+1} vi,t+1之间的运动信息表示为 m i , t , t + 1 = ( x i , t + 1 − x i , t , y i , t + 1 − y i , t , z i , t + 1 − z i , t ) m_{i,t,t+1}=(x_{i,t+1}-x_{i,t},y_{i,t+1}-y_{i,t},z_{i,t+1}-z_{i,t}) mi,t,t+1=(xi,t+1xi,t,yi,t+1yi,t,zi,t+1zi,t)
  总体架构(MS-AAGCN)如图6所示。这四种形态(关节、骨骼及其运动)被输入到四个流中。最后,对四个流的softmax得分进行加权求和,得到动作得分并预测动作标签。
在这里插入图片描述

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值