OpenCV 中的 Gui 特性

一.图片

1. 读入图像
Opencv是使用函数cv2.imread()读入图像,该函数对应填入两个参数,第一个参数是给函数提供图片的完整路径,第二个参数是要告诉函数应该如何读取这幅图片。

第二个参数的选项:
cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略,
这是默认参数。
cv2.IMREAD_GRAYSCALE:以灰度模式读入图像

(特别提示:就算图像的路径是错的,OpenCV 也不会提醒你的,但是当你使用命
令print(img)时得到的结果是None。)

import cv2
img = cv2.imread('C:/Users/www12/Desktop/liyifeng.jpg')

2.显示图像
opencv使用函数**cv2.imshow()**显示图像,窗口自动调整为图像大小,第一个参数是窗口的名字。其次才是我们的图像,你可以创建多个窗口,但是必须给他们不同的名字。

cv2.waitKey() 是一个键盘绑定函数。需要指出的是它的时间尺度是毫
秒级。函数等待特定的几毫秒,看是否有键盘输入。特定的几毫秒之内,如果
按下任意键,这个函数会返回按键的 ASCII 码值,程序将会继续运行。如果没
有键盘输入,返回值为 -1,如果我们设置这个函数的参数为 0,那它将会无限
期的等待键盘输入。它也可以被用来检测特定键是否被按下,例如按键 a 是否
被按下。

cv2.destroyAllWindows() 可以轻易删除任何我们建立的窗口。如果
你想删除特定的窗口可以使用 cv2.destroyWindow(),在括号内输入你想删
除的窗口名。

import cv2
img = cv2.imread('C:/Users/www12/Desktop/liyifeng.jpg')
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

得到的图像如下:
在这里插入图片描述

按动键盘上任意键图像就会消失。

3.保存图像
opencv使用cv2.imwrite()来保存一个图像,首先需要一个文件名,之后才是你要保存的图像。

cv2.imwrite('liyifeng.png',img)

4.小结
下面的程序将会加载一个灰度图,显示图片,按下’s’键保存后退出,或者
按下 ESC 键退出不保存。

import cv2

img = cv2.imread('C:/Users/www12/Desktop/liyifeng.jpg')
cv2.imshow('image',img)
k = cv2.waitKey(0)
if k == 27: 
    cv2.destroyAllWindows()
elif k == ord('s'): 
    cv2.imwrite('messigray.png',img)
cv2.destroyAllWindows()

(注:1. ESC的ASCII码对应27,;
2. 如果你用的是 64 位系统,你需要将 k = cv2.waitKey(0) 这行改成
k = cv2.waitKey(0)&0xFF。)

附加:使用Matplotlib
Matplotib 是 python 的一个绘图库,里头有各种各样的绘图方法。之后
会陆续了解到。现在,你可以学习怎样用 Matplotib 显示图像。你可以放大图
像,保存它等等。

代码如下:

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/www12/Desktop/cat.jpg',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.show()

在这里插入图片描述
(提示:彩色图像使用 OpenCV 加载时是 BGR 模式。但是 Matplotib 是 RGB
模式。所以彩色图像如果已经被 OpenCV 读取,那它将不会被 Matplotib 正
确显示)

用opencv直接加载:
在这里插入图片描述

直接用matplotlib加载的话会出现一点问题:
在这里插入图片描述
只是因为BGR对应到了RGB。

二.视频

1. 用摄像头捕获视频
我们经常需要使用摄像头捕获实时图像。OpenCV 为这中应用提供了一个
非常简单的接口。让我们使用摄像头来捕获一段视频,并把它转换成灰度视频
显示出来。从这个简单的任务开始吧。

为了获取视频,你应该创建一个 VideoCapture 对象。他的参数可以是
设备的索引号,或者是一个视频文件。设备索引号就是在指定要使用的摄像头。
一般的笔记本电脑都有内置摄像头。所以参数就是 0。你可以通过设置成 1 或
者其他的来选择别的摄像头。之后,你就可以一帧一帧的捕获视频了。但是最
后,别忘了停止捕获视频。

import cv2

cap = cv2.VideoCapture(0)

while(True):
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

cap.read() 返回一个布尔值(True/False)。如果帧读取的是正确的,
就是 True。所以最后你可以通过检查他的返回值来查看视频文件是否已经到
了结尾。

有时 cap 可能不能成功的初始化摄像头设备。这种情况下上面的代码会报
错。你可以使用 cap.isOpened(),来检查是否成功初始化了。如果返回值是
True,那就没有问题。否则就要使用函数 cap.open()。

你可以使用函数 cap.get(propId) 来获得视频的一些参数信息。这里
propId 可以是 0 到 18 之间的任何整数。每一个数代表视频的一个属性

其中的一些值可以使用 cap.set(propId,value) 来修改,value 就是
你想要设置成的新值。

例如,我可以使用 cap.get(3)cap.get(4) 来查看每一帧的宽和高。
默认情况下得到的值是 640X480。但是我可以使用 ret=cap.set(3,320)
和 ret=cap.set(4,240) 来把宽和高改成 320X240。

(注意:当你的程序报错时,你首先应该检查的是你的摄像头是否能够在其他程
序中正常工作(比如 linux 下的 Cheese。)

2.从文件中播放视频
与从摄像头中捕获一样,你只需要把设备索引号改成视频文件的名字。在
播放每一帧时,使用 cv2.waiKey() 设置适当的持续时间。如果设置的太低视
频就会播放的非常快,如果设置的太高就会播放的很慢(你可以使用这种方法
控制视频的播放速度)。通常情况下 25 毫秒就可以了。

下面是一些函数的参数:
• CV_CAP_PROP_POS_MSEC Current position of the video file
in milliseconds.
• CV_CAP_PROP_POS_FRAMES 0-based index of the frame to
be decoded/captured next.
• CV_CAP_PROP_POS_AVI_RATIO Relative position of the
video file: 0 - start of the film, 1 - end of the film.
• CV_CAP_PROP_FRAME_WIDTH Width of the frames in the
video stream.
• CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the
video stream.
• CV_CAP_PROP_FPS Frame rate.
• CV_CAP_PROP_FOURCC 4-character code of codec.
• CV_CAP_PROP_FRAME_COUNT Number of frames in the
video file.
• CV_CAP_PROP_FORMAT Format of the Mat objects returned
by retrieve() .
• CV_CAP_PROP_MODE Backend-specific value indicating the
current capture mode.
• CV_CAP_PROP_BRIGHTNESS Brightness of the image (only
for cameras).
• CV_CAP_PROP_CONTRAST Contrast of the image (only for
cameras).
• CV_CAP_PROP_SATURATION Saturation of the image (only
for cameras).
• CV_CAP_PROP_HUE Hue of the image (only for cameras).
• CV_CAP_PROP_GAIN Gain of the image (only for cameras).
• CV_CAP_PROP_EXPOSURE Exposure (only for cameras).
• CV_CAP_PROP_CONVERT_RGB Boolean flags indicating
whether images should be converted to RGB.
• CV_CAP_PROP_WHITE_BALANCE Currently unsupported
• CV_CAP_PROP_RECTIFICATION Rectification flag for stereo
cameras (note: only supported by DC1394 v 2.x backend currently)

import cv2

vc = cv2.VideoCapture('C:/Users/www12/Desktop/jiaoshi.mp4')

if vc.isOpened(): 
    oepn, frame = vc.read()
else:
    open = False

while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame,  cv2.COLOR_BGR2GRAY)
        cv2.imshow('result', gray)
        if cv2.waitKey(100) & 0xFF == 27:
            break
vc.release()
cv2.destroyAllWindows()

3.保存视频
在我们捕获视频,并对每一帧都进行加工之后我们想要保存这个视频。对
于图片来时很简单只需要使用 cv2.imwrite()。但对于视频来说就要多做点工
作。

这次我们要创建一个 VideoWriter 的对象。我们应该确定一个输出文件
的名字。接下来指定 FourCC 编码(下面会介绍)。播放频率和帧的大小也都
需要确定。最后一个是 isColor 标签。如果是 True,每一帧就是彩色图,否
则就是灰度图。

FourCC 就是一个 4 字节码,用来确定视频的编码格式。可用的编码列表
可以从fourcc.org查到。这是平台依赖的。下面这些编码器对我来说是有用个。

• In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is
more preferable. MJPG results in high size video. X264 gives
very small size video)

• In Windows: DIVX (More to be tested and added)
• In OSX : (I don’t have access to OSX. Can some one fill this?)

FourCC 码以下面的格式传给程序,以 MJPG 为例:
cv2.cv.FOURCC(‘M’,‘J’,‘P’,‘G’) 或者 cv2.cv.FOURCC(*‘MJPG’)
下面的代码是从摄像头中捕获视频,沿水平方向旋转每一帧并保存它。

import cv2

cap = cv2.VideoCapture(0)

fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('C:/Users/www12/Desktop/jiaoshi.mp4', fourcc, 20.0, (640, 480))

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret == True:
        frame = cv2.flip(frame, 0)
        out.write(frame)
        cv2.imshow('frame',gray)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break
    else:
        break
        
cap.release()
out.release()
cv2.destroyAllWindows()

三. OpenCV 中的绘图函数

总览:绘图函数大致有以下几种:
cv2.line(),cv2.circle(),cv2.rectangle(),
cv2.ellipse(),cv2.putText()
等。

上面所有的这些绘图函数需要设置下面这些参数:
• img:你想要绘制图形的那幅图像。
• color:形状的颜色。以 RGB 为例,需要传入一个元组,例如:(255,0,0)
代表蓝色。对于灰度图只需要传入灰度值。
• thickness:线条的粗细。如果给一个闭合图形设置为 -1,那么这个图形
就会被填充。默认值是 1.
• linetype:线条的类型,8 连接,抗锯齿等。默认情况是 8 连接。cv2.LINE_AA
为抗锯齿,这样看起来会非常平滑。

1.画线
要画一条线,你只需要告诉函数这条线的起点和终点。我们下面会画一条
从左上方到右下角的蓝色线段。

import numpy as np
import cv2

# 生成一个空的灰度图
img = np.zeros((512, 512, 3), np.uint8)
# 画线
cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
# 显示
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

在这里插入图片描述

line()函数源码:

void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

(注:
img: 要绘制线段的图像。
pt1: 线段的起点。
pt2: 线段的终点。
color: 线段的颜色,通过一个Scalar对象定义。
thickness: 线条的宽度。
lineType: 线段的类型。可以取值8, 4, 和CV_AA, 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
shift: 坐标点小数点位数。)

2.画矩形

要画一个矩形,你需要告诉函数的左上角顶点和右下角顶点的坐标。这次
我们会在图像的右上角话一个绿色的矩形。

import numpy as np
import cv2
img = np.zeros((512, 512, 3), np.uint8)
cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

在这里插入图片描述

3.画圆

要画圆的话,只需要指定圆形的中心点坐标和半径大小。我们在上面的矩
形中画一个圆。

import numpy as np
import cv2
img = np.zeros((512, 512, 3), np.uint8)
cv2.circle(img,(447,63), 63, (0,0,255), -1)
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

在这里插入图片描述
4.画椭圆
画椭圆比较复杂,我们要多输入几个参数。一个参数是中心点的位置坐标。
下一个参数是长轴和短轴的长度。椭圆沿逆时针方向旋转的角度。椭圆弧演
顺时针方向起始的角度和结束角度,如果是 0 很 360,就是整个椭圆。查看
cv2.ellipse() 可以得到更多信息。下面的例子是在图片的中心绘制半个椭圆。

import numpy as np
import cv2
img = np.zeros((512, 512, 3), np.uint8)
# 从左到右参数的意义 
# 空图像 中心坐标 长轴和短轴长度 初始旋转边的角度 初旋转角度 末旋转角度 颜色 边缘填充
cv2.ellipse(img,(256,256),(100,50),0,0,360,(20,213,79),-1)
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

在这里插入图片描述
5 画多边形
画多边形,需要指点每个顶点的坐标。用这些点的坐标构建一个大小等于
行数 X1X2 的数组,行数就是点的数目。这个数组的数据类型必须为 int32。
这里画一个黄色的具有四个顶点的多边形。

import numpy as np
import cv2
img = np.zeros((512, 512, 3), np.uint8)
pts=np.array([[10,3],[48,19],[60,3],[98,19]],np.int32) #数据类型必须是int32
pts=pts.reshape((-1,1,2)) 
#reshape 的第一个参数为-1, 表明这一维的长度是根据后面的维度的计算出来的。
#如果第三个参数是 False,我们得到的多边形是不闭合的(首尾不相连)。
cv2.polylines(img,[pts],True,(0,0,255),2) # 图像,点集,是否闭合,颜色,线条粗细
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

在这里插入图片描述
(注意:cv2.polylines() 可以被用来画很多条线。只需要把想要画的线放在一
个列表中,将这个列表传给函数就可以了。每条线都会被独立绘制。这会比用
cv2.line() 一条一条的绘制要快一些。)

6 在图片上添加文字

要在图片上绘制文字,你需要设置下列参数:
• 你要绘制的文字
• 你要绘制的位置
• 字体类型(通过查看 cv2.putText() 的文档找到支持的字体)
• 字体的大小
• 文字的一般属性如颜色,粗细,线条的类型等。为了更好看一点推荐使用
linetype=cv2.LINE_AA

import numpy as np
import cv2
img = np.zeros((512, 512, 3), np.uint8)
# 字体
font=cv2.FONT_HERSHEY_SIMPLEX
# 底板 文字 位置 字体 文字大小 颜色 线条粗细
cv2.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),4)
cv2.imshow('image',img)
cv2.waitKey(0) 
cv2.destroyAllWindows()

在这里插入图片描述
(警 告:所 有 的 绘 图 函 数 的 返 回 值 都 是 None, 所 以 不 能 使 用 img =
cv2.line(img,(0,0),(511,511),(255,0,0),5)。)

四. 把鼠标当画笔

主要要学习的目标函数:cv2.setMouseCallback()

1.简单演示
这里我们来创建一个简单的程序,他会在图片上你双击过的位置绘制一个
圆圈。
首先我们来创建一个鼠标事件回调函数,但鼠标事件发生是他就会被执行。
鼠标事件可以是鼠标上的任何动作,比如左键按下,左键松开,左键双击等。
我们可以通过鼠标事件获得与鼠标对应的图片上的坐标。根据这些信息我们可
以做任何我们想做的事。你可以通过执行下列代码查看所有被支持的鼠标事件。

import cv2
events = [i for i in dir(cv2) if 'EVENT' in i]
print(events)

['EVENT_FLAG_ALTKEY', 'EVENT_FLAG_CTRLKEY', 'EVENT_FLAG_LBUTTON', 'EVENT_FLAG_MBUTTON', 'EVENT_FLAG_RBUTTON', 'EVENT_FLAG_SHIFTKEY', 'EVENT_LBUTTONDBLCLK', 'EVENT_LBUTTONDOWN', 'EVENT_LBUTTONUP', 'EVENT_MBUTTONDBLCLK', 'EVENT_MBUTTONDOWN', 'EVENT_MBUTTONUP', 'EVENT_MOUSEHWHEEL', 'EVENT_MOUSEMOVE', 'EVENT_MOUSEWHEEL', 'EVENT_RBUTTONDBLCLK', 'EVENT_RBUTTONDOWN', 'EVENT_RBUTTONUP']

所有的鼠标事件回调函数都有一个统一的格式,他们所不同的地方仅仅是
被调用后的功能。我们的鼠标事件回调函数只用做一件事:在双击过的地方绘
制一个圆圈。下面是代码,不懂的地方可以看看注释。

import cv2
import numpy as np

def draw_circle(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDBLCLK:
        cv2.circle(img, (x, y), 100, (0, 0, 255), -1)
        
#创建图像与窗口并将窗口与回调函数绑定
img = np.zeros((512, 512, 3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_circle)

while(1):
    cv2.imshow('image', img)
    if cv2.waitKey(20)&0xFF==27:
        break;
        
cv2.destroyAllWindows()

在这里插入图片描述

2.高级一点的示例
现在我们来创建一个更好的程序。这次我们的程序要完成的任务是根据我
们选择的模式在拖动鼠标时绘制矩形或者是圆圈(就像画图程序中一样)。所以
我们的回调函数包含两部分,一部分画矩形,一部分画圆圈。这是一个典型的
例子他可以帮助我们更好理解与构建人机交互式程序,比如物体跟踪,图像分
割等。

import cv2
import numpy as np
#鼠标按下则为True 鼠标松开则为False
drawing=False
#mode为True则画矩形 mode为False则画曲线
mode=True
#初始化坐标
ix,iy=-1,-1 
# 定义画图函数
def draw_circle(event,x,y,flags,param):
    #声明全局变量
    global ix,iy,drawing,mode
    #如果鼠标左边按下去了     
    if event==cv2.EVENT_LBUTTONDOWN:
        #drawing赋值为True  开始绘图        
        drawing=True
        #获取坐标   
        ix,iy=x,y
    #当按下了鼠标左边并且在移动的时候         
    elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
        #如果可以画图     
        if drawing==True:
            #看是画矩形还是曲线   
            if mode==True:
                cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
            else:
            	cv2.circle(img,(x,y),3,(0,0,255),-1) 
    #如果鼠标松开 绘图结束 drawing为False 
    elif event==cv2.EVENT_LBUTTONUP:
        drawing=False

下面我们要把这个回调函数与 OpenCV 窗口绑定在一起。在主循环中我
们需要将键盘上的“m”键与模式转换绑定在一起。

img=np.zeros((512,512,3),np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
    cv2.imshow('image',img)
    k=cv2.waitKey(1)&0xFF
    if k==ord('m'):
        mode=not mode
    elif k==27:
        break

在这里插入图片描述

效果如上,按动m更换画图模式,可以进行自由画图啦!

五. 用滑动条做调色板

现在我们来创建一个简单的程序:通过调节滑动条来设定画板颜色。我们
要创建一个窗口来显示显色,还有三个滑动条来设置 B,G,R 的颜色。当我们
滑动滚动条是窗口的颜色也会发生相应改变。默认情况下窗口的起始颜色为黑。
cv2.getTrackbarPos() 函数的一个参数是滑动条的名字,第二个参数
是滑动条被放置窗口的名字,第三个参数是滑动条的默认位置。第四个参数是
滑动条的最大值,第五个函数是回调函数,每次滑动条的滑动都会调用回调函
数。回调函数通常都会含有一个默认参数,就是滑动条的位置。在本例中这个
函数不用做任何事情,我们只需要 pass 就可以了。
滑动条的另外一个重要应用就是用作转换按钮。默认情况下 OpenCV 本
身不带有按钮函数。所以我们使用滑动条来代替。在我们的程序中,我们要创
建一个转换按钮,只有当装换按钮指向 ON 时,滑动条的滑动才有用,否则窗
户口都是黑的。

import cv2
import numpy as np

#这个时候回调函数不需要起作用  pass即可
def nothing(x):
    pass

#创建一副黑色图像
img=np.zeros((300,512,3),np.uint8)

cv2.namedWindow('image')

cv2.createTrackbar('R','image',0,255, nothing)
cv2.createTrackbar('G','image',0,255, nothing)
cv2.createTrackbar('B','image',0,255, nothing)

switch='0:OFF\n1:ON'

cv2.createTrackbar(switch,'image',0,1,nothing)

while(1):
    cv2.imshow('image',img)
    k=cv2.waitKey(1)&0xFF
    if k==27:
        break
    r=cv2.getTrackbarPos('R','image') 
    g=cv2.getTrackbarPos('G','image') 
    b=cv2.getTrackbarPos('B','image') 
    s=cv2.getTrackbarPos(switch,'image')
    if s==0:
        img[:]=0
    else:
        img[:]=[b,g,r]
cv2.destroyAllWindows()

效果图如下:
在这里插入图片描述

小结任务:创建一个画板,可以自选各种颜色的画笔绘画各种图形。

效果图如下所示, 这样我们就完成了一个可以自己选定任何颜色的并且可以在圆和矩形中切换绘制的一个画图板.

import cv2
import numpy as np

def nothing(x):
    pass

#当鼠标按下时变为 True
drawing=False
#如果 mode 为 true 绘制矩形。按下'm' 变成绘制曲线。
mode=True
#创建回调函数
ix,iy=-1,-1 
#绘图函数     
def draw_circle(event,x,y,flags,param):
    #获取滑动条上的RGB值         
    r=cv2.getTrackbarPos('R','image') 
    g=cv2.getTrackbarPos('G','image') 
    b=cv2.getTrackbarPos('B','image')
    #确定颜色
    color=(b,g,r)
    #定义全局变量         
    global ix,iy,drawing,mode
    # 当按下左键是返回起始位置坐标
    if event==cv2.EVENT_LBUTTONDOWN:
        drawing=True
        ix,iy=x,y
    # 当鼠标左键按下并移动是绘制图形。event 可以查看移动,flag 查看是否按下
    elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
        if drawing==True:
            if mode==True:
                cv2.rectangle(img,(ix,iy),(x,y),color,-1)
            # 绘制圆圈,小圆点连在一起就成了线,3 代表了笔画的粗细
            else:
                cv2.circle(img,(x,y),3,color,-1)
    # 当鼠标松开停止绘画。
    elif event==cv2.EVENT_LBUTTONUP:
        drawing==False
            
img=np.zeros((512,512,3),np.uint8)
cv2.namedWindow('image')
cv2.createTrackbar('R','image',0,255,nothing)
cv2.createTrackbar('G','image',0,255,nothing)
cv2.createTrackbar('B','image',0,255,nothing)
cv2.setMouseCallback('image',draw_circle)

while(1):
    cv2.imshow('image',img)
    k=cv2.waitKey(1)&0xFF
    if k==ord('m'):
        mode=not mode
    elif k==27:
        break
cv2.destroyAllWindows()

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值