【视频异常检测】Open-Vocabulary Video Anomaly Detection

摘要

当前具有弱监督的视频异常检测(VAD)方法固有地局限于封闭集设置,并且在开放世界应用中可能会遇到困难,因为在训练期间测试数据中可能存在不可见的异常类别。最近的一些研究试图解决一个更现实的设置,开放式VAD,其目的是在看到异常和正常视频的情况下检测未见的异常。然而,这种设置侧重于预测帧异常分数,没有识别特定异常类别的能力,尽管这种能力对于构建更智能的视频监控系统至关重要。本文进一步探讨了开放词汇表视频异常检测(OVVAD),其中我们的目标是利用预训练的大型模型来检测并分类可见和未见的异常。为此,我们提出了一个模型,该模型将OVVAD解耦为两个相互补充的任务——类别未知检测和类别特定分类——并共同优化这两个任务。特别地,我们设计了语义知识注入模块,为检测任务引入来自大型语言模型的语义知识;设计了新的异常合成模块,利用大型视觉生成模型为分类任务生成伪未知异常视频。这些语义知识和广泛异常极大地扩展了我们的模型在检测和分类各种可见和未见异常方面的能力。在三个广泛使用的基准测试上进行的大量实验表明,我们的模型在OVVAD任务上达到了最先进的性能。

引言

视频异常检测(Video anomaly detection, VAD)以检测不符合预期模式的异常事件为目的,在智能视频监控、视频内容审核等方面有着广阔的应用前景,越来越受到学术界和业界的关注。经过几年的蓬勃发展,VAD取得了长足的进步,许多作品不断涌现。

传统VAD根据监督方式大致可分为半监督VAD[17]和弱监督VAD[38]两类。它们之间的主要区别在于异常训练样本的可用性。虽然它们在监督模式和模型设计上有所不同,但都可以大致视为分类任务。对于半监督VAD,它属于一类分类,而弱监督VAD属于二元分类。具体来说,半监督VAD假设在训练阶段只有正常样本,不符合这些正常训练样本的测试样本被识别为异常,如图1(a)所示。大多数现有的方法本质上都是通过一类分类器[50]或自监督学习技术,如帧重建[9]、帧预测[17]、拼图[44]等,努力学习一类模式,即正常模式。同样,如图1(b)所示,弱监督VAD可以看作是一个二元分类任务,假设在训练阶段有正常和异常样本,但异常事件的精确时间注释是未知的。以前的方法广泛采用具有多实例学习(MIL)[38]或TopK机制[27]的二元分类器来区分正常和异常事件。一般来说,现有的半监督和弱监督VAD方法都将其重点限制在分类上,并使用相应的判别器对每个视频帧进行分类。虽然这些实践在一些广泛使用的基准测试中取得了显著的成功,但它们仅限于检测一组封闭的异常类别,并且无法处理任意的未见异常。这一限制限制了它们在开放世界场景中的应用,并增加了丢失报告的风险,因为实际部署中的许多真实世界的异常情况并不存在于训练数据中。

在这里插入图片描述

​ 图1

为了解决这个问题,最近的一些研究探索了一个全新的VAD系列,即open-set VAD[1,5,66,67]。open-set VAD的核心目的是训练正常和可见异常样本的模型,以检测未见异常(见图1©)。例如,异常训练样本只包括打斗和射击事件,期望训练后的模型能够检测出发生在道路事故现场的异常事件。与传统VAD相比,open-set VAD摆脱了封闭集困境,具有处理开放世界问题的能力。虽然这些作品在一定程度上揭示了它们的开放世界能力,但它们在解决异常类别的语义理解方面存在不足,这导致了开放世界中检测过程的模糊性。

最近,大型语言/视觉模型预训练[11,29,34,64]在广泛的下游任务中取得了惊人的成功[13 - 15,24,25,28,47,48,58,65],这也使我们能够解决开放词汇视频异常检测(OVVAD)。因此,在本文中,我们提出了一种基于大型预训练视觉/语言模型的OVVAD新模型,旨在检测和分类可见和未见异常,如图1(d)所示。与以前的VAD相比,OVVAD对应用程序具有很高的价值,因为它可以提供更多信息,更细粒度的检测结果,但更具挑战性,因为1)它不仅需要检测异常,还需要对异常进行分类;2)它需要处理看到的(基础)和未看到的(新)异常。为了解决这些挑战,我们明确地将OVVAD任务分解为两个相互补充的子任务:一个是未知类别检测,而另一个是特定类别的分类。为了改进未知类别检测,我们从两个方面进行了努力。我们首先引入了一个几乎没有权重的时间适配器(TA)模块来建模时间关系,然后引入了一个新的语义知识注入(SKI)模块,旨在借助大型语言模型将文本知识整合到视觉信号中。为了增强特定类别的分类,我们从对比语言图像预训练(CLIP)模型[29]中获得灵感,并使用可扩展的方式对异常进行分类,即文本标签和视频之间的对齐,并且我们设计了一种新的异常合成(NAS)模块来生成视觉(例如,图像和视频)材料,以帮助模型更好地识别新的异常。基于这些操作,我们的模型在OVVAD的三个流行基准上达到了最先进的性能,在UCF-Crime[38]、XDViolence[51]和UBnormal[1]上分别达到了86.40%的AUC、66.53%的AP和62.94%的AUC。

我们的贡献总结如下:

  1. 我们在一个具有挑战性但实际上很重要的开放词汇设置下探索视频异常检测。据我们所知,这是OVVAD的第一次工作。
  2. 然后,我们提出了一个建立在预训练大型模型之上的模型,该模型将OVVAD任务分解为两个相互补充的子任务——未知类别检测和特定类别分类——并共同优化它们以实现准确的OVVAD。
  3. 在未知类别检测任务中,我们设计了一个几乎无权重的时间适配器模块和一个语义知识注入模块,以大幅增强正常/异常帧检测。
  4. 在细粒度异常分类任务中,我们引入了一种新的异常合成模块来生成伪未见的异常视频,从而对新的异常类型进行准确分类。

相关工作

Semi-supervised VAD

主流的解决方案是通过自我监督的方式(例如重建和预测)或一类方式构建正常模式。对于自监督方式[8,54,56],基于重构的方法[4,21,22,33,39,55,60]通常利用编码器-解码器框架重构正常事件并计算重构误差,这些重构误差较大的事件被归类为异常。基于后续预测的方法[17,19]侧重于用之前的视频帧来预测未来的帧,并通过计算预测帧与实际帧的差值来判断是否为异常帧。最近的工作[37]结合了基于重建和预测的方法来提高检测性能。对于单类模型,有些作品尝试利用单类框架[35]学习正常模式,如单类支持向量机及其扩展(OCSVM [36], SVDD [50], GODS[45])。

Weakly supervised VAD

与半监督VAD相比,弱监督VAD[10,40]由正常样本和异常样本组成,可视为一种二元分类任务,目的是在时间注释的限制下在帧级检测异常。作为先驱工作,Sultani等人[38]首先提出了一个大规模的基准,并利用MIL机制训练了一个轻量级网络。然后Zhong等人[61]提出了一种基于图卷积网络的方法来捕获帧间的相似关系和时间关系。Tian等人([42])引入了自注意块和金字塔扩展卷积层来捕获多尺度时间关系。Wu等[51,52]构建了包含视听信号的最大规模基准,并提出了一种多任务模型来处理粗粒度和细粒度VAD。Zaheer等人提出了一种具有新正常抑制机制的聚类辅助弱监督框架。Li等人[16]提出了一种基于transformer的自训练多序列学习网络。Zhang等人[59]试图利用伪标签的完备性和不确定性。上述方法都是简单地使用预训练模型编码的视频或音频输入,如C3D[43]和I3D[3],虽然有少数作品[12,23,53]将CLIP模型引入弱监督VAD任务,但他们只是利用了CLIP强大的视觉特征,而忽略了CLIP的zero-shot能力。

Open-set VAD

VAD任务自然存在开放世界需求。面对开放世界的要求,传统的半监督工程更容易产生大量的假警报,而弱监督工程在检测已知异常时有效,但在检测未知异常时可能失效。开放集VAD旨在基于正常和可见异常训练模型,并尝试检测未见异常。Acsintoae et al.[1]为监督开放集VAD任务开发了第一个名为UBnormal的基准。Zhu等人[67]提出了一种通过将证据深度学习和归一化流集成到MIL框架中来处理开放集VAD任务的方法。此外,Ding等人提出了一种基于多头网络的模型来学习解纠缠异常表示,每个多头专门捕获一种特定类型的异常。与我们的模型相比,这些工作主要致力于开放世界检测,忽略了异常分类,而且这些工作也没有充分利用预训练模型。

方法

Problem Statement.

所研究的OVVAD问题可以正式表述如下。假设给定一个训练样本集 X = { x i } i = 1 N + A \mathcal{X}=\{x_{i}\}_{i=1}^{N+A} X={xi}i=1N+A,其中 X n = { x i } i N {\mathcal{X}_{n}}=\{x_{i}\}_{i}^{N} Xn={xi}iN为正常样本集, X a = { x i } i = N + 1 N + A \mathcal{X}_{a}=\{x_{i}\}_{i=N+1}^{N+A} Xa={xi}i=N+1N+A为异常样本集。对于 X a \mathcal{X}_{a} Xa中的每个样本 x i x_i xi,它有一个对应的视频级类别标签 y i , y i ∈ C b a s e y_{i},y_{i}\in C_{base} yi,yiCbase,这里, C b a s e C_{base} Cbase表示基本(见过的)异常类别的集合, C \mathcal{C} C C b a s e C_{base} Cbase C n o v e l C_{novel} Cnovel的并集,其中 C n o v e l C_{novel} Cnovel表示新颖(未见的)异常类别的集合。基于训练样本 X \mathcal{X} X,目标是训练一个能够检测和分类基本异常和新异常的模型。具体来说,模型的目标是预测每一帧的异常置信度,如果视频中存在异常,则识别异常类别。

1、Overall Framework

基于封闭集分类的传统方法不太可能处理开放词汇场景下的VAD。为此,我们利用语言-图像预训练模型作为基础,例如CLIP,由于其强大的zero-shot泛化能力。如图2所示,给定一个训练视频,我们首先将其输入CLIP Φ C L I P − v \Phi_{CLIP-v} ΦCLIPv的图像编码器中,得到形状为 n × c n\times c n×c的帧级特征 x f x_f xf,其中 n n n为视频帧数, c c c为特征维数。然后这些特征通过TA模块、SKI模块和检测器产生帧级异常置信度 p p p,该pipeline主要应用于未知类别检测任务。另一方面,对于特定类别的分类,我们从其他跨不同视觉任务的开放词汇工作中汲取灵感[31,46,63],并使用跨模态对齐机制。具体来说,我们首先生成跨帧级特征的视频级聚合特征,然后生成异常类别的文本特征/嵌入,最后,我们基于视频级特征和文本特征之间的对齐来估计异常类别。此外,我们引入了NAS模块,在大型语言模型(LLM)和人工智能生成的内容模型(AIGC)的帮助下生成潜在的新异常,以实现新类别识别。

在这里插入图片描述

​ 图2

2、Temporal Adapter Module

时间依赖性在VAD中起着至关重要的作用[49,62]。在这项工作中,我们使用CLIP的冻结图像编码器来获得视觉特征,但由于CLIP是在图像-文本对上进行预训练的,因此缺乏对时间依赖性的考虑。为了弥合图像和视频之间的差距,在最近的研究中,使用时间Transformer[13,25]已成为一种常规做法。然而,这种范式在新类别上的性能明显下降[13,32],可能的原因是时间Transformer中的附加参数可能专门针对训练集,从而损害了对新类别的泛化。因此,我们在经典图卷积网络的基础上设计了一种几乎无权重的时间依赖性适配器。数学上,它可以表示如下:

x t = L N ( s o f t m a x ( H ) x f ) ( 1 ) x_t=LN(softmax\left(H\right)x_f)\quad(1) xt=LN(softmax(H)xf)(1)

其中LN为层归一化操作,H为邻接矩阵,使用softmax归一化保证H的每一行之和等于1。这样的设计是用来捕捉基于每两个帧之间的位置距离的上下文依赖关系。邻接矩阵的计算方法如下:

H ( i , j ) = − ∣ i − j ∣ σ ( 2 ) H_{(i,j)}=\frac{-|i-j|}{\sigma}\quad(2) H(i,j)=σij(2)

i i i帧与第 j j j帧之间的接近关系仅由它们的相对时间位置决定。σ是控制距离关系影响范围的超参数。根据该公式,两帧之间的时间距离越近,接近关系得分越高,反之越低。值得注意的是,在TA模块中,只有层归一化涉及很少的参数。

3、Semantic Knowledge Injection Module

人类在感知环境时往往会利用先验知识,例如,我们可以在没有直接看到火焰的情况下,根据气味和烟雾推断出火灾的存在。基于这个想法,我们提出了SKI模块来明确地引入额外的语义知识来辅助视觉检测。如图2所示,对于视频中的正常事件,我们使用固定模板提示大规模语言模型(如ChatGPT[2]和SparkDesk 1)获取关于常见场景和动作的信息,如街道、公园、商场、步行、跑步、工作等。同样,我们生成与异常场景相关的额外单词,包括爆炸、爆裂、火光等术语。最后,我们得到了几个由 M p r i o r M_{prior} Mprior表示的短语列表,该列表由名词单词(场景)和动词单词(动作)组成。有了 M p r i o r M_{prior} Mprior,我们利用CLIP的文本编码器提取文本嵌入作为语义知识,如下所示:

F t e x t = Φ C L I P − t ( Φ t o k e n ( M p r i o r ) ) ( 3 ) F_{text}=\Phi_{CLIP-t}\left(\Phi_{token}(M_{prior})\right)\quad(3) Ftext=ΦCLIPt(Φtoken(Mprior))(3)

其中 F t e x t ∈ R l × c F_{text}\in\mathcal{R}^{l\times c} FtextRl×c Φ C L I P − t \Phi_{CLIP-t} ΦCLIPt表示CLIP的文本编码器, Φ t o k e n \Phi_{token} Φtoken表示将单词转换为向量的语言tokenizer。

然后,为了将这些语义知识有效地整合到视觉信息中以增强异常检测,我们设计了一种跨模态注入策略。这种策略鼓励视觉信号寻找相关的语义知识,并将其整合到过程中。这样的操作演示如下:

F k n o w = s i g m o i d ( x t F t e x t ⊤ ) F t e x t / l ( 4 ) F_{know}=sigmoid\begin{pmatrix}x_tF_{text}^\top\end{pmatrix}F_{text}/l\quad(4) Fknow=sigmoid(xtFtext)Ftext/l(4)

其中 F k n o w ∈ R n × c F_{know}\in\mathcal{R}^{n\times c} FknowRn×c,我们使用sigmoid而不是softmax来确保视觉信号可以包含更多相关的语义概念。

最后,我们将 F k n o w F_{know} Fknow x t x_t xt连接起来,创建一个既包含视觉信息又包含集成语义知识的输入。我们将此输入输入到二元检测器中,以生成用于未知类别检测的异常置信度。

4、Novel Anomaly Synthesis Module

虽然目前预训练的视觉语言模型,如CLIP,具有令人印象深刻的zero-shot能力,但它们在各种下游任务上的zero-shot性能,特别是与视频相关的任务,仍然远远不能令人满意。出于同样的原因,我们的模型是建立在这些预训练的视觉语言模型之上的,它是在基础异常和正常样本上训练的,这使得它在面对新的异常时容易出现泛化缺陷。随着大型生成模型的出现,生成样本作为伪训练数据已经成为一种可行的解决方案[20,26]。因此,我们提出了NAS模块,仅基于潜在异常类别生成一系列伪新异常。然后,我们利用这些样本来微调提出的模型,以改进新异常的分类和检测。NAS模块总体上包括三个关键流程:

1)最初,我们用带有预定义的模板 p r o m p t g e n prompt_{gen} promptgen的LLMs(例如,ChatGPT, ERNIE Bot[41])提示像生成十个关于现实世界中“战斗”的简短场景描述,以生成潜在新类别的文本描述。然后,我们使用AIGC模型,如DALL·E mini [30], Gen-2[7],生成相应的图像或短视频。这可以表示为:

V g e n = Φ A I G C ( Φ L L M ( p r o m p t g e n ) ) ( 5 ) V_{gen}=\Phi_{AIGC}\left(\Phi_{LLM}(prompt_{gen})\right)\quad(5) Vgen=ΦAIGC(ΦLLM(promptgen))(5)

其中 V g e n V_{gen} Vgen是生成图像( I g e n I_{gen} Igen)和短视频( S g e n S_{gen} Sgen)的组合。

2)随后,对于 I g e n I_{gen} Igen,我们从[18]中汲取灵感,并引入了一个简单而有效的动画策略,将单个图像转换为模拟场景变化的视频剪辑。具体来说,对于给定的图像,我们采用不同裁剪比例的中心裁剪机制来选择相应的图像区域,然后将这些区域的大小调整回原始大小并将它们级联以创建新的视频剪辑 S c a t S_{cat} Scat

3)最后,为了模拟真实世界中异常视频通常很长且未经修剪的情况,我们引入了第三步,伪异常合成,通过将 S c a t S_{cat} Scat S g e n S_{gen} Sgen插入随机选择的正常视频中。此外,插入位置也是随机选择的。这个过程产生最终的伪异常样本 V n a s \mathcal{V}_{nas} Vnas。详细描述和结果参见补充资料。

有了 V n a s \mathcal{V}_{nas} Vnas,我们微调了我们的模型,它最初是在 X \mathcal{X} X上训练的,以增强其对新异常的泛化能力。

5、Objective Functions

5.1 Training stage without pseudo anomaly samples

对于类别不可知的检测,遵循之前的VAD工作[27,49],我们使用top-K机制在异常和正常视频中选择前K个高异常置信度。我们计算这些选择的平均值,并将平均值作为视频级预测输入到sigmoid函数中。这里,对于异常视频我们设置 K = n / 16 K=n/16 K=n/16,对于正常视频我们设置 K = n K=n K=n。最后,我们计算了视频级预测与二元标签之间的二元交叉熵 L b c e L_{bce} Lbce

对于特定类别的分类,我们计算聚合的视频级特征和文本类别嵌入之间的相似性,以得出视频级分类预测。我们还使用交叉熵损失函数来计算视频级分类损失 L c e L_{ce} Lce。考虑到OVVAD是一个弱监督任务,我们不能直接从帧级注释中获得视频级聚合特征。在[49]之后,我们采用了基于软注意力的聚合,如下所示:

x a g g = s o f t m a x ( p ) ⊤ x t ( 6 ) x_{agg}=softmax(p)^\top x_t\quad(6) xagg=softmax(p)xt(6)

对于文本类别嵌入,我们受到CoOp[63]的启发,将可学习提示附加到原始类别嵌入中。

对于SKI模块的参数 F t e x t F_{text} Ftext,我们的目标是在训练阶段进行显式优化。我们打算区分正常的知识嵌入和异常的知识嵌入。对于正常视频,我们期望其视觉特征与正常知识嵌入的相似度较高,与异常知识嵌入的相似度较低。为此,我们首先提取每个视频和文本知识嵌入之间的相似度矩阵,然后为每帧选择得分最高的前10%并计算平均值,最后,我们应用基于交叉熵的损失 L s i m − n L_{sim-n} Lsimn。对于异常视频,我们预期异常知识嵌入和异常视频帧特征之间具有高度相似性。由于在弱监督下缺乏精确的帧级注释,我们采用了一种称为Top-K的硬注意选择机制来定位异常区域。然后执行相同的操作来计算损耗 L s i m − a L_{sim-a} Lsima

总的来说,在训练阶段,我们使用了三个损失函数,总损失函数为:

L t r a i n = L b c e + L c e + L s i m ( 7 ) L_{train}=L_{bce}+L_{ce}+L_{sim}\quad(7) Ltrain=Lbce+Lce+Lsim(7)

式中 L s i m L_{sim} Lsim L s i m − n L_{sim-n} Lsimn L s i m − a L_{sim-a} Lsima的和。

5.2 Fine-tuning stage with pseudo anomaly samples

从NAS模块获得 V n a s \mathcal{V}_{nas} Vnas后,我们继续对模型进行微调。 V n a s \mathcal{V}_{nas} Vnas是合成的,为我们提供帧级注释,并允许我们通过完全监督来优化我们的模型以进行检测。对于分类, L c e 2 L_{ce2} Lce2 L c e L_{ce} Lce保持相同,关键的区别在于标签不仅可用于基本类别,也可用于潜在的新类别。对于检测, L b c e 2 L_{bce2} Lbce2是帧级的二元交叉熵损失。

最后,微调阶段的总损失函数为:

L t u n e = L b c e 2 + L c e 2 + λ ( L b c e + L c e ) ( 8 ) L_{tune}=L_{bce2}+L_{ce2}+\lambda(L_{bce}+L_{ce})\quad(8) Ltune=Lbce2+Lce2+λ(Lbce+Lce)(8)

  • 25
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 通过下载 youmi-vocabulary 背单词微信小程序的代码和相关资源文件后,我们可以直接进行设定和定制。 首先,我们可以打开代码文件,然后根据自己的需求对页面布局、颜色、字体等进行修改。如果想要增加新的功能或者修改现有功能,可以找到相应的代码文件进行编辑,如卡片的显示、单词的存储和读取等。 在设定过程中,我们可以对小程序的首页进行设置,比如添加背景图片、修改标题、调整按钮位置等。另外,我们还可以设定各个页面间的跳转关系,如单词卡片页面跳转到单词详情页面、单词详情页面跳转到例句页面等。对于每个页面的样式和交互,可以通过修改代码中的CSS样式和JavaScript代码来实现。 如果想要添加新的单词库或者词典,我们可以在资源文件中添加相应的文件,然后在代码中引用这些文件,以便在小程序中使用。同时,我们还可以根据需要对单词库进行编辑,如添加新的单词、修改释义或者例句等。 在完成设定后,我们可以运行小程序进行调试,检查是否有错误或者不符合预期的地方。如果发现问题,可以根据提示进行修改,直到满足我们的需求为止。 最后,将修改后的代码和资源文件上传到微信小程序开发者工具中,进行编译和发布,即可在微信中使用我们自己定制的 youmi-vocabulary 背单词微信小程序了。 ### 回答2: youmi-vocabulary 背单词微信小程序是一个用于帮助用户背单词的工具。用户只需要将代码及相关资源文件下载后,可以直接设定并使用该小程序。 首先,将代码及相关资源文件下载到本地。可以通过下载链接或者将代码拷贝到本地的方式进行下载。下载完成后,可以将代码放置在合适的位置。 接下来,设定该微信小程序。打开微信开发者工具,选择该项目所在的文件夹,即可进行设定。在设定过程中,可以配置小程序的基本信息、界面设计、功能模块等,以及与服务器的连接方式等。 一旦设定完成,就可以使用该小程序了。用户可以通过微信扫描小程序二维码,或者在微信搜索框中搜索小程序名称,进入小程序页面。在小程序页面上,用户可以进行单词背诵、词义理解、例句听写等功能。小程序会根据用户设定的英语水平、背诵计划等提供个性化的背单词内容和学习进度统计。 此外,youmi-vocabulary 还提供了一些其他功能,例如字典查询、记忆曲线、背单词游戏等,以提高用户的学习效果和学习兴趣。 总结来说,youmi-vocabulary 背单词微信小程序是一个方便用户背单词的工具。用户只需要下载代码及相关资源文件,并进行设定,就可以使用该小程序,并享受它提供的个性化背单词功能和其他学习辅助功能。 ### 回答3: youmi-vocabulary 背单词微信小程序是一个帮助用户背诵并记忆单词的工具。用户可以在微信小程序上下载该小程序的代码和相关资源文件,并进行设置,以便使用该小程序。 通过下载 youmi-vocabulary 背单词微信小程序的代码和资源文件,用户可以获得小程序的完整功能并进行自定义设置。这些代码和资源文件可能包括小程序的前端代码、后端代码、配置文件、图片等。用户可以根据自己的需求修改这些文件,例如更改小程序的界面样式、增加新的功能、调整单词库等。 在设定时,用户可以根据自己的需求进行个性化设置。例如,用户可以选择自己所需的单词库,根据自己的学习进度和水平设定背诵计划,并进行记忆方面的设置,如背单词的方式(英译汉、汉译英、听力等),记忆模式(选择题、填空题等),以及复习频率等。 通过设定,youmi-vocabulary 背单词微信小程序可以根据用户的需求和设置,在背诵单词的过程中提供个性化的学习体验。用户可以根据自己的设定,系统自动提供对应的背诵任务和学习资料,帮助用户高效、有序地记忆单词。同时,用户也可以根据自己的学习情况进行实时调整和优化设定,以达到最佳学习效果。 总之,通过下载 youmi-vocabulary 背单词微信小程序的代码和相关资源文件,并进行设定,用户可以个性化地使用这个小程序,高效记忆单词,提升自己的语言能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值