opencv ml模块 SVM使用笔记

opencv进阶19-基于opencv 决策树cv::ml::DTrees 实现demo示例 样本缺少某些特征的值,那么该样本就无法继续沿着树向下切分,也就无法到达叶子节点,即没有预测输出。在这种情况下,可以利用当前节点下面的所有子节点中的叶子节点来预测输出的平均值,作为这个样本的预测输出,故称之为代理切分。罕见的异常,即在训练集中正常比异常多很多,此时只需将每个案例都视为正常,即可实现非常好的分类性能。为了避免这种情况,可以指定先验,人为地增加异常概率(高达0.5,甚至更高),因此错误分类的异常权重变得更大,这样决策树就能做出适当地调整,以更好地检测异常样本。如果是,则向左移动,否则向右移动。 阅读详情

opencv Modules SVM使用笔记

写在前面:

最近在完成一个项目时,提取出的样本数据较大,自己也没有良好的处理数据的能力,就想着利用现成的 SVM对数据进行分类。

查了很多资料,对SVM的大致原理有点了解,网络上也有开源的LibSvm,可是在没有完全理解SVM原理前,阅读和修改源码有些难度。而opencv恰好有一个Machine Learning模块,囊括了大多数机器学习的算法,而SVM也在其中。

这篇笔记不包含SVM算法的具体原理,只是对opencv中的SVM使用方法做一点拙劣的笔记。下面开始:

SVM是什么?
SVM:Support Vector Machine,即支持向量机。通过Wiki,有个大体的认识支持向量机

源码阅读
源代码来自Introduction to Support Vector Machines,opencv3.1.0的官方网站。自己做了一些注释。

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>               //ml模块
#define NTRAINING_SAMPLES   100         // 每类的训练样本
#define FRAC_LINEAR_SEP     0.9f        // Fraction of samples which compose the linear separable part
using namespace cv;
using namespace cv::ml;                //ml命名空间
using namespace std;



int main()
{
    const int WIDTH = 512, HEIGHT = 512;
    Mat I = Mat::zeros(HEIGHT, WIDTH, CV_8UC3);

    //---------- 1. 随机生成训练数据(二维数据,超平面为二维) ---

    //训练200个样本,每个样本为2维向量
    Mat trainData(2 * NTRAINING_SAMPLES, 2, CV_32FC1);            
    //200*1,用以标注样本类别                
    Mat labels(2 * NTRAINING_SAMPLES, 1, CV_32SC1);                       

    RNG rng(100); // 随机数生成类        

                  // 设置数据中线性可分部分
    int nLinearSamples = (int)(FRAC_LINEAR_SEP * NTRAINING_SAMPLES);
    // 为类别1生成随机数
    Mat trainClass = trainData.rowRange(0, nLinearSamples);
    // x坐标范围为[0,0.4*WIDTH]
    Mat c = trainClass.colRange(0, 1);
    rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH));
    // y坐标范围为[0,WIDTH)
    c = trainClass.colRange(1, 2);
    rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
    // 为类别2生成随机数
    trainClass = trainData.rowRange(2 * NTRAINING_SAMPLES - nLinearSamples, 2 * NTRAINING_SAMPLES);
    // x坐标范围为(0.4*WIDTH,1*WIDTH)
    c = trainClass.colRange(0, 1);
    rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH));
    // y坐标范围为[0,1*HEIGHT]
    c = trainClass.colRange(1, 2);
    rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
    //------------------ 设置训练数据中线性不可分部分 ---------------
    // 为类别1,2生成数据
    trainClass = trainData.rowRange(nLinearSamples, 2 * NTRAINING_SAMPLES - nLinearSamples);
    // x坐标范围是 [0.4*WIDTH, 0.6*WIDTH)
    c = trainClass.colRange(0, 1);
    rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH));
    // y坐标范围是 [0, 1*HEIGHT)
    c = trainClass.colRange(1, 2);
    rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
    //-------- 分类(为类别1,2设置标志)----------
    labels.rowRange(0, NTRAINING_SAMPLES).setTo(1);  // 类1
    labels.rowRange(NTRAINING_SAMPLES, 2 * NTRAINING_SAMPLES).setTo(2);  // 类2

//------------------ 2. 设置支持向量机范围 -------------
//------------------- 3. 训练SVM -------------------------
    cout << "Starting training process" << endl;
    Ptr<SVM> svm = SVM::create();   //声明SVM对象
    svm->setType(SVM::C_SVC);   //SVM模型选择                   
    svm->setC(0.2);             //惩罚因子设置(原始0.1)           
    svm->setKernel(SVM::LINEAR);   //核函数类型:线性                
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));        //迭代要求         
    svm->train(trainData, ROW_SAMPLE, labels);           //训练                                         
    cout << "Finished training process" << endl;

    //------------------------ 4. 显示结果区域 ----------------------------------------
    Vec3b green(0, 100, 0), blue(100, 0, 0);
    for (int i = 0; i < I.rows; ++i)
        for (int j = 0; j < I.cols; ++j)
        {   
             //Mat_<float>为Mat1f,一维向量v=(i,j) 
             Mat  = (Mat1f(1, 2) << i, j);
            //Mat sampleMat = (Mat_<float>(1, 2) << i, j); 

            //判别是哪一类     

            if (response == 1)    I.at<Vec3b>(j, i) = green;   
            else if (response == 2)    I.at<Vec3b>(j, i) = blue;
        }
    //----------------------- 5. 显示训练数据-------------------------------

    int thick = -1;
    int lineType = 8;
    float px, py;
    // 类 1
    for (int i = 0; i < NTRAINING_SAMPLES; ++i)
    {
        px = trainData.at<float>(i, 0);       
        py = trainData.at<float>(i, 1);    
        circle(I, Point((int)px, (int)py), 3, Scalar(0, 255, 0), thick, lineType);
    }
    // 类2
    for (int i = NTRAINING_SAMPLES; i <2 * NTRAINING_SAMPLES; ++i)
    {
        px = trainData.at<float>(i, 0);
        py = trainData.at<float>(i, 1);
        circle(I, Point((int)px, (int)py), 3, Scalar(255, 0, 0), thick, lineType);
    }
    //------------------------- 6. 画出支持向量 ----------------------------
    thick = 2;
    lineType = 8;
    Mat sv = svm->getUncompressedSupportVectors();
    for (int i = 0; i < sv.rows; ++i)
    {
        const float* v = sv.ptr<float>(i);
        circle(I, Point((int)v[0], (int)v[1]), 6, Scalar(0, 0, 0), thick, lineType);
    }
    imwrite("result.png", I);                      // save the Image
    imshow("SVM for Non-Linear Training Data", I); // show it to the user
    waitKey(0);
}

运行结果
运行环境是VS2015+opencv3.1.0。

思路阐述

以上代码通过core.hpp中的RNG随机数生成类,生成了200个二维向量作为训练数据,数值大小在[0,512)中,以便可以用一张图片表示,存储在一个200*2的Mat结构里。同时生成一个Mat的label,将x坐标在一定范围内点标识为类1,其余为类2。生成的训练数据二维可分,故超平面为二维平面内的直线。
下面通过创建一个SVM类,调用几个函数,设定参数,并训练数据。

    Ptr<SVM> svm = SVM::create();   //声明SVM对象
    svm->setType(SVM::C_SVC);   //SVM模型选择                   
    svm->setC(0.1);             //惩罚因子设置          
    svm->setKernel(SVM::LINEAR);   //核函数类型:线性                
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER,  
                   (int)1e7, 1e-6));        //迭代要求         
    svm->train(trainData, ROW_SAMPLE, labels);           //训练                                         
    cout << "Finished training process" << endl;

几个地方需要注意一下:

  • 1.SVM类型选择:setType(SVM::C_SVC)
    SVM模型类型枚举:
    enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR };
    如果只是用ml::SVM,完成简单的数据分类,则可以这个参数设置为C_SVC.
标志作用
C_SVCC表示惩罚因子,C越大表示对错误分类的惩罚越大
NU_SVC和C_SVC类似(参数C的范围不同,C_SVC采用的是0到正无穷,NU_SVC是[0,1]。)
ONE_CLASS需要类标号,用于支持向量的密度估计和聚类.
EPSILON_SVR敏感损失函数,对样本点来说,存在着一个不为目标函数提供任何损失值的区域,即-带。
NU_SVR由于EPSILON_SVR需要事先确定参数,然而在某些情况下选择合适的参数却不是一件容易的事情。而NU_SVR能够自动计算参数。
  • 2.惩罚因子设置: svm->setC(0.1)
    ①大的C(惩罚因子)使得解决方案更小的误分类率和更小的间隔。考虑到在这种情况下,分类错误的代价是昂贵的。因为优化的目的是减小不同,更小的误分类率是被接受的
    ②小的C(惩罚因子)使得解决方案有更大的分类间隔和更大的误分类率。这种情况下,最小化没有考虑太多总和,因此它更注重于发现有更大间隔的高维空间。

  • 3.选择核函数类型
    简要说一下,核函数在SVM的作用。
    SVM是一个二分类器,目的是找到一个平面,将已知的数据分为两类。以上代码已经实现了对二维空间中数据的分类,二维空间中的平面即为分类的直线(又叫做支持向量)。设想数据复杂一点,虽然维度还是三维,可是已经不能找到简单的平面来对数据进行分类。见图

    线性不可分

    从人眼来看,很明显可以用一个圆来对两类数据进行分类,而SVM所定义的最佳分类平面在二维空间中是直线。所以核函数出现了,它能将二维空间变化到高维空间。现在将两个圆坐标变换到三维空间,经过简单的旋转变换,可以用平面对数据进行分类,可见下图(来自pluskid:下面的gif 动画,先用 Matlab 画出一张张图片,再用 Imagemagick 拼贴成)
    三维

    好了,回到opencv中的SVM核函数:
    enum {LINEAR, POLY, RBF,SIGMOID, PRECOMPUTED };
    LINEAR:线性核函数(linear kernel)
    POLY:多项式核函数(ploynomial kernel)
    RBF:径向机核函数(radical basis function)
    SIGMOID:神经元的非线性作用函数核函数(Sigmoid tanh)

    根据数据的特性选择不同核函数,进行SVM分类。

4.训练

svm->train(trainData, ROW_SAMPLE, labels);

trainData:训练数据
labels:数据类型几率

关于ROW_SAMPLE,见ml.hpp中的定义(添加注释)

enum SampleTypes
{    
    //每一行为一个样本数据
    ROW_SAMPLE = 0, //!< each training sample is a row of samples
   //每一列为一个样本数据
    COL_SAMPLE = 1  //!< each training sample occupies a column of samples
};

知道以上内容后,我们就可以利用opencv中的SVM进行简单的数据分类。
————–2017.3.8

opencv学习笔记-ml模块中的svm使用 之前我使用过matlab和python写过svm,这次xiang 阅读详情

相关推荐

opencv系列之机器学习(ml)

(版本为3.4.0) opencv官方api文档:https://docs.opencv.org/ ml模块的svm操作: python版本 1、生成训练数据 训练文件分别以类标签为文件名,里面存放对应的类文件 def generate_data(self,file_dir): train_data= [] train_labels = [] if os.pa...

zhanghenan123的博客 4371

C/C++开发,opencv-ml库学习,支持向量机(SVM)应用

基于MNIST 数据集(手写数字识别)学习SVM(支持向量机)模型的数据集处理、模型训练、模型测试、模型调用全过程,给出完整编译过程及全代码。

技术需要分享 2943

OpenCV-Python实战(13)——OpenCV与机器学习的碰撞

机器学习是人工智能的子集,它为计算机以及其它具有计算能力的系统提供自动预测或决策的能力,诸如虚拟助理、车牌识别系统、智能推荐系统等机器学习应用程序给我们的日常生活带来了便捷的体验。机器学习的蓬勃发展,得益于以下三个关键因素:1) 海量数据集;2) 算法的快速发展;3) 计算机硬件的发展。在本文中,我们将学习 OpenCV 提供的常见机器学习算法和技术,用于解决计算机视觉项目中的实际问题,例如分类和回归问题。

盼小辉丶的博客 2万+

opencv机器学习ml模块简介

本文不涉原理,只介绍如何使用! ml模块为opencv的机器学习(machine learning,ml)代码库,包含各种机器学习算法: 0, class CvStatModel ; class CvMLData; struct CvParamGrid; 1,Normal Bayes Classifier(贝叶斯分类); 2,K-...

知识搬运工的博客 1万+

Opencv学习笔记 - OpenCV 4机器学习算法简介

在机器学习中,一些比较流行方法的包括:支持向量机(SVM)、人工神经网络(ANN)、聚类、k-最近邻、决策树和深度学习。OpenCV支持并实现几乎所有这些方法,并有详细的文档说明。 OpenCV 4 机器学习算法 OpenCV实现了其中的八种机器学习算法,所有这些算法都继承自StatModel类,这八种算法是: ·人工神经网络 ·随机树 ·期望最大化 ·k-最近邻 ·............

学以致用 知行合一 5626

OpenCV入门(三十)快速学会OpenCV 29 支持向量机SVM

支持向量机(Support Vector Machine, SVM)是一种二分类模型,目标是寻找一个标准(称为超平面)对样本数据进行分割,分割的原则是确保分类最优化(类别之间的间隔最大)。当数据集较小时,使用支持向量机进行分类非常有效。支持向量机是最好的现成分类器之一,这里所谓的“现成”是指分类器不加修改即可直接使用。在对原始数据分类的过程中,可能无法使用线性方法实现分割。支持向量机在分类时,把无法线性分割的数据映射到高维空间,然后在高维空间找到分类最优的线性分类器。

小幽余生不加糖 1404

C/C++开发,opencv-ml库学习,ml模块代码实现研究

c++ opencv库的ml模块代码实现分析。

技术需要分享 1999

欧拉 openEuler 20.03安装配置tigervnc-server

欧拉 openEuler 20.03安装配置tigervnc-server openEuler VNC

郭亚望 8951

学习笔记之——opencv的ML模块

之前开始学opencv的时候就看到opencv里面有机器学习模块(machine learning,ML),但是一直以来跟着这么多书籍学习都没有发现有提及过(毕竟opencv是针对图像处理方面的,所以大部分书籍都以介绍图像处理方面的为主)。无意中,在《OpenCV和Visual Studio图像识别应用开发》一书中看到有ML模块的介绍,所以就打算写下这一篇学习笔记~在opencv中,ML模块是一组...

gwpscut的博客 6042

超详细!动态规划详解分析(典型例题分析和对比,附源码)

为啥要使用动态规划?什么时候使用动态规划?以下是我的一些理解和心得,如果你感兴趣,就接着往下看吧。 对您有帮助的话记得给我点个赞哟! 动态规划的基本思想 动态规划(Dynamic Programming,DP)算法通常用于求解某种具有最优性质的问题。在这类问题中,可能会有许多可行解,每一个解都对应一个值,我们希望找到具有最优值的解。 动态规划算法与分治法类似,其基本思想也是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中 得到原有问题的解。与分治法不同的是,动态规划经分解后得到的子问题

qq_44398094的博客 8万+

Blender地形建模实战:5步搞定Gazebo仿真地形(附避坑指南)

本文提供了一份详细的Blender地形建模实战指南,旨在帮助开发者快速创建Gazebo仿真地形。文章通过五个核心步骤,从环境准备、地形雕刻、模型优化导出,到创建Gazebo模型包及问题排错,系统讲解了如何将Blender中的地形模型成功导入Gazebo进行机器人仿真,并重点分享了关键的避坑经验。

weixin_28475533的博客 342

OpenCV学习笔记:opencv_ml模块

转自:http://www.cnblogs.com/xylc/p/3406141.html 一,简介 该模块为opencv的机器学习(machine learning,ml)代码库,包含各种机器学习算法: 0, class CvStatModel ; class CvMLData; struct CvParamGrid; 1,bayesian,Normal Bayes

qq_38662499的博客 897

基于微信小程序的垃圾分类系统,附源码

垃圾分类小程序管理员功能有个人中心,管理员管理,意见反馈管理,视频类型管理,垃圾类型管理,新闻类型管理,论坛信息管理,环保视频管理,环保知识管理,垃圾信息管理,环保新闻管理,用户管理,知识问答试卷管理,试题管理,测试管理,轮播图管理。用户可以在微信小程序上面注册登录,查看各种环保信息和垃圾信息,还可以参加知识问答等操作。垃圾分类小程序的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。

Java徐师兄的博客 2074

OpenCV方法cv2.ml.SVM_create() 创建——支持向量机SVM

OpenCV创建SVM,完整源码示例,超详细解释,新手也能学会!!!

WenJGo的博客 1514

webrtc+uniapp(h5和app)实现在线聊天功能 uniapp+网页+服务端源码

uniapp端代码 服务端代码 public/index.html

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 754

本地玩转AI还得靠这个,SillyTavern(酒馆)到底有多强?

SillyTavern是一款本地运行的LLM交互前端,支持文本生成、图像生成、语音合成等功能。它最初是TavernAI的分支,现已独立开发,社区活跃,功能更新频繁。SillyTavern通过前端UI和插件系统连接各种大模型后端,如OpenAI、KoboldAI等,用户可以在本地创建“虚拟酒馆”与各种角色对话。其功能亮点包括角色卡、角色记忆、世界设定、多人聊天室、自定义UI和行为脚本、插件扩展支持等。SillyTavern适合AI创作用户、AI工程师、LLM爱好者和AIGC创作者。它有两个维护分支:relea

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 8031

OpenCV学习笔记(十六)——支持向量机(SVM)

支持向量机(Support Vector Machine,SVM)是一种二分类模型,目标是寻找一个标准(称为超平面)对样本数据进行分割,分割的原则是确保分类最优化(类别之间的间隔最大)。当数据集较小时,使用支持向量机进行分类非常有效。支持向量机是最好的现成分类器之一,这里所谓的“现成”是指分类器不加修改即可直接使用。

简简单单的学习笔记,致力于帮助更多前进路上的朋友~ 3514

【网络安全】AntSword蚁剑新手快速入门(附实战案例)

蚁剑(AntSword)是一款开源的跨平台WebShell管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。蚁剑的特点主要有如下几点:1.支持多平台。包括macOS、Linux 32位、Linux 64位、Linux armv7l、Linux arm64、Windows 32位、Windows 64位。2.完善的文档。中国蚁剑文档地址。3.多项功能。文件管理功能、虚拟终端功能、数据库管理功能。4.内置代理功能。

等风来 1万+

【OpenCV】ml 模块:机器学习任务

OpenCV的ml模块是专为机器学习任务设计的工具集,提供SVM、决策树、KNN等经典算法实现。该模块与计算机视觉流程紧密结合,支持从数据准备、模型训练到预测评估的全流程操作。通过Mat对象处理特征数据,支持分类、回归和聚类任务,常与HOG等特征提取方法配合使用。ml模块具有高效C++实现和Python接口,适用于图像分类、目标检测等实际应用场景。其模型可保存为文件便于复用,为计算机视觉任务提供便捷的机器学习解决方案。

彬彬侠的博客 960

SIMULINK开发项目实例 1000 例专栏之第960例--基于电力系统稳定性的建模与仿真场景:-含分布式电源的配电网电压稳定性研究

间歇性与随机性:例如,太阳能依赖于日照强度,风能依赖于风速,这使得它们的输出功率具有不确定性。逆变器接口:大多数分布式电源通过逆变器接入电网,这对电网的动态响应特性产生了影响。位置分散:通常分布在用户侧或靠近负荷中心的位置。本文详细介绍了如何使用Simulink结合Simscape Electrical 构建一个用于研究含分布式电源配电网电压稳定性的模型,并提供了详细的仿真流程说明。

xiaoheshang_123的博客 153

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

(openCV 十)ML_SVM

import cv2 import numpy as np import matplotlib.pyplot as plt # 训练的点数 train_pts = 30 # 创建测试的数据点,2类 # 以(-1.5, -1.5)为中心 rand1 = np.ones((train_pts,2)) * (-2) + np.random.rand(train_pts, 2) print('ran...

niuniu0243111006的博客 2267

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【opencv-ml】支持向量机简介

Introduction to SupportVector Machines支持向量机简介Goal在本教程中,您将学习如何:使用 OpenCV 函数 cv::ml::SVM::train构建基于 SVM 的分类器,并使用 cv::ml::SVM::predict来测试其性能。What is a SVM?支持向量机(A Support Vector Machine) (SV...

cxyhjl的博客 2256

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

OpenCV ML 模块使用指南

OpenCV 的ML模块提供了丰富的机器学习算法,可用于解决各种计算机视觉和数据分析问题。本指南将详细介绍该模块中主要的机器学习算法,包括支持向量机(SVM)、K 均值聚类(K-Means)和神经网络(ANN),并结合图像分类和聚类分析这两个典型应用场景进行代码实现与解释。

junjun4561482的专栏 988

利用C++和OpenCV3设计支持向量机SVM分类器

文章目录一、代码示例二、SVM训练过程2.1 数据准备2.2 初始化SVM参数2.3 训练SVM2.4 保存数据2.5 加载保存的数据2.6 测试数据三、显示支持向量机分类区域3.1 初始化图像显示区域3.2 显示SVM决策区域3.3 显示训练数据3.4 显示支持向量四、输出结果 一、代码示例 `话不多说,直接上代码: #include <opencv2/opencv.hpp> #include <opencv2/ml.hpp> #include<iostream> u

weixin_50624597的博客 1622

SVM 支持向量机,如何寻找超平面的

SVM 支持向量机,如何寻找超平面的? 1.SVM概念 支持向量机(Support Vector Machine, SVM)是一种二分类模型,目标是寻找一个标准(称为超平面)对样本数据进行分割,分割的原则是确保分类最优化(类别之间的间隔最大)。 1.1 分类 下图绿色和黄色,红色可以基本建红色和黄色划分开 用到CV2的向量机模块 cv2.ml.SVM_create ...

keny-大成的博客 4007
下一篇: 分裂布雷格曼方法--(Split Bregman Method)
半子yuan
博客等级 码龄11年 27粉丝 22原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值