寻找图像中的局部极大点

  某个图像处理的任务需求被转化为一个寻找图像局部最大值的问题,例如下面的图像是一段来自医学投影的组织影像,其中用肉眼能够辨识出一些灰度值比较大的团块,这些团块都是代表着一定医学含义的组织。需求是找出类似这种团块的个数。

原图 需要找的团块

  后来在ImageJ中发现了一个这个比较奇妙的算法,叫做FindMaxima,这个算法支持提供一个ErorrTolerance参数之后,根据这个参数来调整寻找到极大位置的个数。例如选择ErorrTolerance为下面三个不同的数值后,算出来的团块数是不同的。

IJ中的算法 算法参数面板 算法结果

 

作者的描述

  根据ImageJ中提供的信息可以找到这个算法的原作者,叫做Michael Schmid,在论坛上可以找到他对自己写的这个算法的简单描述:

Hi, 

sorry, there is no publication on it (at least none that I am aware of, 

probably I have reinvented the wheel), but it is rather simple code: 

(1) Find the local maxima 

(2) Sort them in descending sequence 

(3) For each local maximum, do a flood fill algorithm with the gray level 

tolerance (without modifying the original, it is done on a temporary 

scratch image). Maxima where flood filling reaches a previously filled 

area (i.e., area of other maximum within the tolerance) are discarded. 

(4) In case of 'single points' output, if there are several points having 

the highest value inside the flood-filled area, use the one that is 

closest to their geometric center. 

 

Segmentation is a bit more difficult (it stems from older ImageJ 

versions), and I am currently about to see whether it can't be done faster 

and with better accuracy... 

 ------Michael 

  总结这个描述,可以按照如下思路简单的实现这个算法:

  1. 寻找到所有比8邻域像素值都大的像素点,存入数组L
  2. 对L按像素值从高到低排序
  3. 对每一个L中的像素P
    1. 以P为种子点执行泛洪法,包含原则为与P的像素值相差在tolerance之内,若遇到比P像素值更高的点或者遇到了被标记为Maxima的点,则此P点不为Maxima,否则P被标记为Maxima。
  4. 将L中标记为Maxima的体素输出

 

根据描述实现一个轻量版

  根据上述思路用C#实现一个版本,其代码如下:

复制代码
public struct Int16Double
{
    public int X;
    public int Y;
    public Int16Double(int x, int y)
    {
        X = x;
        Y = y;
    }
}
public struct Int16DoubleWithValue:IComparable<Int16DoubleWithValue>
{
    public int X;
    public int Y;
    public float V;
    public Int16DoubleWithValue(int x, int y, float value)
    {
        X = x;
        Y = y;
        V = value;
    }

    public int CompareTo(Int16DoubleWithValue other)
    {
        return -this.V.CompareTo(other.V);
    }
}
public class BitMap2d
{
    public float[] data;
    public int width;
    public int height;
    public BitMap2d(int width, int height, float v)
    {
        this.width = width;
        this.height = height;
        data = new float[width * height];
        for (int i = 0; i < width * height; i++)
            data[i] = v;
    }
    public void SetPixel(int x, int y, byte v)
    {
        data[x + y * width] = v;
    }
    public float GetPixel(int x, int y)
    {
        return data[x + y * width];
    }
    public void ReadRaw(string path)
    {
        FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
        BinaryReader sr = new BinaryReader(fs);

        for (int i = 0; i < width * height; i++)
        {
            byte[] floatBytes = sr.ReadBytes(4);

            // swap the bytes

            byte temp = floatBytes[0];

            floatBytes[0] = floatBytes[3];

            floatBytes[3] = temp;

            temp = floatBytes[1];

            floatBytes[1] = floatBytes[2];

            floatBytes[2] = temp;

            // get the float from the byte array

            float value = BitConverter.ToSingle(floatBytes, 0);
            data[i] = value;
        }
        sr.Close();
        fs.Close();
        return;
    }
    public Bitmap MakeBmp()
    { 
        float min=float.MaxValue;
        float max=float.MinValue;
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                    float r=this.GetPixel(i,j);
                if(r>max)
                    max=r;
                if(r<min)
                    min=r;
            }
        }
        float delta=max-min;
        Bitmap bmp = new Bitmap(this.width, this.height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                float r=this.GetPixel(i,j);
                int b=(int)(255*(r-min)/delta);
                Color c=Color.FromArgb((byte)b,(byte)b,(byte)b);
                bmp.SetPixel(i, j, c);
            }
        }
        return bmp;
    }
}
public class FlagMap2d
{
    public int action_set_count;
    public int action_get_count;
    public int width;
    public int height;
    byte[] flags;
    public FlagMap2d(int width, int height,byte v)
    {
        this.width = width;
        this.height = height;
        action_get_count = 0;
        action_set_count = 0;
        flags = new byte[width * height];
        for(int i=0;i<width*height;i++)
            flags[i] = v;
    }
    public void SetFlagOn(int x, int y, byte v)
    {
        flags[x + y * width] = v;
        action_set_count++;
    }
    public byte GetFlagOn(int x, int y)
    {
        action_get_count++;
        return flags[x + y * width];
    }
}
复制代码
复制代码
public class MaximunFinder
{
    BitMap2d bmp;
    float torlerance;
    const byte UNPROCESSED = 0;
    const byte VISITED = 1;
    const byte PROCESSED = 2;
    static Int16Double[] Delta = new Int16Double[8]
    {
        new Int16Double(-1,-1),
        new Int16Double(-1,0),
        new Int16Double(-1,1),
        new Int16Double(0,-1),
        new Int16Double(0,1),
        new Int16Double(1,-1),
        new Int16Double(1,0),
        new Int16Double(1,1),
    };

    public MaximunFinder(BitMap2d bmp,float torlerance)
    {
        this.bmp = bmp;
        this.torlerance = torlerance;
    }
    public List<Int16DoubleWithValue> FindMaxima()
    {
        List<Int16DoubleWithValue> list = FindLocalMaxima();
        list.Sort();
        FlagMap2d flag=new FlagMap2d(bmp.width,bmp.height,0);
        List<Int16DoubleWithValue> r=new List<Int16DoubleWithValue>();
        List<Int16Double> temp=new List<Int16Double>();
        for (int i = 0; i < list.Count; i++)
        {
            if (flag.GetFlagOn(list[i].X, list[i].Y) == UNPROCESSED)
            {
                bool ret = FloodFill(list[i].X, list[i].Y,temp,flag);
                if (ret)
                {
                    r.Add(list[i]);
                        
                    MarkAll(temp, PROCESSED, flag);
                }
                else
                {
                    MarkAll(temp, UNPROCESSED, flag);
                    flag.SetFlagOn(list[i].X, list[i].Y, PROCESSED);
                }
                temp.Clear();
            }
        }
        return r;
    }

    private List<Int16DoubleWithValue> FindLocalMaxima()
    {
        List<Int16DoubleWithValue> list = new List<Int16DoubleWithValue>();
        for (int i = 1; i < bmp.width - 1; i++)
        {
            for (int j = 1; j < bmp.height - 1; j++)
            {
                if (IsMaxima(i, j))
                {
                    list.Add(new Int16DoubleWithValue(i, j,bmp.GetPixel(i,j)));
                }
            }
        }
        return list;
    }

    private bool IsMaxima(int i, int j)
    {
        float v = bmp.GetPixel(i, j);
        bool b1 = v > bmp.GetPixel(i - 1, j - 1);
        bool b2 = v > bmp.GetPixel(i, j - 1);
        bool b3 = v > bmp.GetPixel(i +1, j - 1);

        bool b4 = v > bmp.GetPixel(i - 1, j);
        bool b5 = v > bmp.GetPixel(i + 1, j);

        bool b6 = v > bmp.GetPixel(i - 1, j + 1);
        bool b7 = v > bmp.GetPixel(i, j + 1);
        bool b8 = v > bmp.GetPixel(i + 1, j + 1);
        return b1 && b2 && b3 && b4 && b5 && b6 && b7 && b8;
    }

    private bool FloodFill(int x, int y,List<Int16Double> ret,FlagMap2d flag)
    {
        ret.Clear();
        Queue<Int16Double> queue = new Queue<Int16Double>();
        ret.Add(new Int16Double(x, y));
        float pvalue = bmp.GetPixel(x, y);
        flag.SetFlagOn(x, y, VISITED);
        queue.Enqueue(new Int16Double(x, y));
        while (queue.Count != 0)
        {
            Int16Double p = queue.Dequeue();
            for (int i = 0; i < 8; i++)
            {
                int tx = p.X + Delta[i].X;
                int ty = p.Y + Delta[i].Y;
                if(InRange(tx, ty))
                {
                    byte f= flag.GetFlagOn(tx,ty);
                    if(f==PROCESSED)
                        return false;
                    else
                    {
                        bool minum = false;
                        if (IncludePredicate(tx, ty, pvalue,ref minum) && f == UNPROCESSED)
                        {
                            if (minum)
                                return false;
                            Int16Double t = new Int16Double(tx, ty);
                            queue.Enqueue(t);
                            flag.SetFlagOn(tx, ty, VISITED);
                            ret.Add(t);
                        }
                    }

                }
            }
        }
        return true;
    }

    private bool InRange(int tx, int ty)
    {
        return tx >= 0 && tx < bmp.width && ty >= 0 && ty < bmp.height;
    }

    private bool IncludePredicate(int x, int y, float pv, ref bool min)
    {
        float v = bmp.GetPixel(x, y);
        if (pv < v)
            min = true;
        return pv - v <= torlerance;
    }

    private void MarkAll(List<Int16Double> ret, byte v,FlagMap2d flag)
    {
        for (int i = 0; i < ret.Count; i++)
        {
            flag.SetFlagOn(ret[i].X, ret[i].Y, v);
        }
    }

}
复制代码

 

 

算法输出预览

  原图和输出图像如下表所示:

 
原图 本文实现的输出 IJ的输出

   代码地址:https://github.com/chnhideyoshi/SeededGrow2d/tree/master/FindMaxima

Maxima快速参考手册 命令手册 帮助 pdf 目录 1 基本介绍 4 1.1 一历史 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 启动和退出 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3 在线帮助 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.4 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2 初等数学 8 2.1 算术运算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.2 常用初等函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.3 预定义常数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.4 自定义函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.5 求和与求积 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.6 代数运算与化简 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.6.1 多项式展开 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.6.2 因式分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.6.3 等量代换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.6.4 分式展开 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.6.5 分式化简 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.6.6 对数、指数及根式化简 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.6.7 条件假设 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.7 三角函数变换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 *Maxima快速参考手册 by Huan Ma is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. +Copyright ?c 2010–2011 Huan Ma. 欢迎反馈:yusufma77@yahoo.com 1 2.7.1 常用变换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.7.2 控制变量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.8 解方程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.8.1 单个方程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.8.2 方程组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.8.3 数值解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.9 复数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.9.1 实部与虚部 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.9.2 复共轭 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.9.3 复数模和辐角 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.9.4 直角形式和极坐标形式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3 矩阵 17 3.1 矩阵输入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.1 交互式输入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.2 以列表形式输入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.3 以函数形式输入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.4 对角矩阵 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.1.5 单一非零元素矩阵 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.2 矩阵运算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.2.1 加减乘除 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.2.2 幂运算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2.3 矩阵乘法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.3 行(列)操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.3.1 提取行(列) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.3.2 增加行(列) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.3.3 子矩阵 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.4 线性代数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.4.1 行列式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.4.2 矩阵转置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.4.3 矩阵的逆 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.4.4 矩阵的秩 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.4.5 高斯消元 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.4.6 本征值和本征向量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4 微积分 23 4.1 微分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.2 积分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.2.1 不定积分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.2.2 定积分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2 4.2.3 数值积分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 4.3 泰勒展开 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.4 拉普拉斯变换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.5 留数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 5 微分方程 27 5.1 一阶或二阶常微分方程通解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.2 初值问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.3 边值问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.4 一阶线性微分方程组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 6 特殊函数 29 7 作图 30 7.1 二维作图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 7.1.1 一般函数作图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 7.1.2 对数坐标图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 7.1.3 参数方程作图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 7.1.4 数据作图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 7.1.5 存为图片文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 7.2 三维作图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 8 图形界面 35 8.1 wxMaxima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 8.2 xmaxima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 8.3 TeXmacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 8.4 Emacs+imaxima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 9 Maxima编程 39 9.1 do循环 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 9.2 if条件句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 9.3 block程序块 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 9.4 read读取 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 9.5 结果输出 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 9.5.1 二维表示 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 9.5.2 输出到文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 9.6 随机数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 9.7 batch执行程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 9.8 tex输出 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 索引 43 3
### 回答1: 在Matlab图像处理局部最大值指的是在一张图像局部区域内的像素值最高的。通常使用局部最大值来检测图像的特定目标或者物体。以图像锐度增强为例,局部最大值可以用来识别图像边缘和角等特征。 Matlab一般使用imregionalmax函数来寻找局部最大值。这个函数可以查找图像的所有局部最大值,并将它们的像素位置返回为一个二维矩阵。使用imregionalmax函数时,需要指定一个阈值,该阈值会过滤掉一些像素,只留下高于阈值的像素来查找局部最大值。 除了imregionalmax函数,还有一些其他的方法可以寻找图像局部最大值,例如使用高斯核或者成比例的盒形滤波器进行滤波,再使用imregionalmax函数进行查找。 在实际应用局部最大值可以用于图像分割、图像匹配、物体检测等多种应用场景。但需要注意的是,在处理图像时,需要考虑到局部最大值的稳定性和灵敏度,以及如何设置合理的阈值来保证检测结果的准确性。 ### 回答2: MATLAB 局部最大值指的是一个图像,某个像素周围的像素值都比它低,而它本身的像素值是最高的。在简单的图像处理或计算机视觉算法,找到局部最大值非常重要。在 MATLAB ,可以使用 imregionalmax() 函数来寻找局部最大值。 该函数的使用方法如下: 1. 首先需要加载图像,可以使用 imread() 函数。 2. 将图像转换为灰度图像,可以使用 rgb2gray() 函数。 3. 使用 imregionalmax() 函数来找到局部最大值。该函数有一个输入参数 im,表示要寻找局部最大值的图像。函数的输出是一个二值图像,其白色像素表示图像局部最大值。 4. 可以将输出的二值图像与原始图像进行叠加,使用 imshow() 函数即可。 需要注意的是,使用 imregionalmax() 函数查找局部最大值时,需要指定一个连通区域(即周围的像素),默认情况下为 8 连通区域。可以使用 strel() 函数来创建一个不同的 structuring element,从而调整连通区域的大小。 总之,MATLAB 局部最大值是很重要的图像处理概念,可以使用 imregionalmax() 函数来轻松寻找。 ### 回答3: 在MATLAB图像处理局部最大值是指在图像选择一个特定的区域,在该区域找到像素值最大的。这种局部最大值的搜索算法被称为极大值抑制(non-maximum suppression)。在进行局部最大值计算时,需要考虑到当前像素所在的图像区域,以便在该区域查找像素值的最大值。该算法可用于检测图像的边缘和角,而不必搜索整个图像。 通常,局部最大值算法的实现方式是,首先对图像进行梯度计算,以便找到图像的边缘和角。接着,在梯度图像将边缘和角标注出来,并确保像素值高于阈值。然后,在每个标注出来的位置选择一个局部窗口,确保该窗口的大小适当,并且包含了当前像素。最后,在窗口找到像素值最大的,将其标注为局部最大值。 总之,MATLAB图像局部最大值计算算法可以通过极大值抑制来实现,它可以用于检测图像的边缘和角。该算法需要选择一个适当的局部窗口大小,并确保像素值高于阈值,以便对图像进行有效的处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值