cv2.setMouseCallback、cv2.createTrackbar

本文介绍使用OpenCV库实现的绘图程序,包括鼠标事件监听和颜色选择功能。利用cv2.setMouseCallback设置鼠标事件回调,cv2.createTrackbar创建颜色调节滑块。

转载链接:http://www.cnblogs.com/pakfahome/p/3913559.html

今天主要看了OpenCV中的事件以及回调函数,这么说可能不准确,主要是下面这两个函数(OpenCV中还有很多这些函数,可以在 http://docs.opencv.org/trunk/modules/highgui/doc/user_interface.html 找到,就不一一列举了),然后自己做了一个简单的绘图程序

函数如下:

cv2.setMouseCallback(windowName, onMouse[, param]) 
cv2.createTrackbar(trackbarName, windowName, value, count, onChange) 

先看第一个函数,cv2.setMouseCallback()

复制代码
import cv2
import numpy as np

def draw_circle(event, x, y, flags, param):
    print type(param[0]), param[1]
    if event == cv2.EVENT_LBUTTONDBLCLK:
        cv2.circle(parma, (x,y), 100, (255,0,0), -1)

img = np.zeros((512,512,3), np.uint8)
a = []
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_circle, [img, a])

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

这段代码实现的功能是每当你在面板上双击时,绘制一个以双击点为园心,半径为100的圆

加粗的地方是设置回调函数的地方,共有3个参数,第一个参数,表示将要操作的面板名,第二个参数是回调函数名,第三个是给回调函数的参数

如果要给回调函数传递多个参数的话,则将这么多个参数存入一个列表/元组中,将其传入

然后看回调函数,共有5个参数:

第一个参数是鼠标事件名,可以通过如下方法查看OpenCV中的事件:

复制代码
event = [i for i in dir(cv2) if 'EVENT' in i]
print event

#############################################
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_MOUSEMOVE      EVENT_RBUTTONDBLCLK
EVENT_RBUTTONDOWN     EVENT_RBUTTONUP
复制代码

这么多事件,基本看名字就能知道干么了,就不说了

第二个,第三个参数是鼠标在面板中的坐标

第四个参数是有没有其他特殊控制,比如在按左键的时候,按了Ctrl,Shift,Alt键等,参数也是刚刚上面的EVENT列表中的,通过事件名可以找到对应flags

第五个参数则是setMouseCallback()函数给回调函数传递的参数,至于怎么传递,前面已经说了(我的代码中,a没有用,只是为了演示如何给回调函数传递函数用的)

下面是第二个函数,cv2.createTrackbar()

共有5个参数,其实这五个参数看变量名就大概能知道是什么意思了

第一个参数,是这个trackbar对象的名字

第二个参数,是这个trackbar对象所在面板的名字

第三个参数,是这个trackbar的默认值

第四个参数,是这个trackbar上调节的范围(0~count)

第五个参数,是调节trackbar时调用的回调函数名(为什么此处没有像setMouseCallback函数一样,设置一个回调函数的参数项,这个还不清楚)

至于如何获取trackbar的当前位置,可以通过

cv2.getTrackbarPos(trackbarname, winname) 

这个函数获得当前trackbar的位置,这里的参数我就不解释了。

最后用这两个函数做了下面一个简单的绘图程序:

每次获取当前的色彩,鼠标按下后开始绘图,鼠标移动到哪,则画到哪,默认是绘制从起始点到终点的矩形,如果按了'm'键,则切换绘制以起始点和终点为直径的圆,圆心在两点的中心,如果再按'm'键,则切换会矩形。(由于本人对Python的变量作用域这块理解还不是很到位,因此用了很多全局变量,写的不好,请大家多多见谅)

复制代码
import cv2
import numpy as np
import math
import copy as cp

drawing = False
mode = True
ix,iy = -1,-1
pre_img = np.zeros((512,512,3), np.uint8)
img = np.zeros((512,512,3), np.uint8)

def nothing(x):
    pass

def draw_circle(event, x, y, flags, param):
    global ix,iy,drawing,mode,pre_img,img
    
    # 每次获取当前Trackbar的位置
    r = cv2.getTrackbarPos('R', 'hello')
    g = cv2.getTrackbarPos('G', 'hello')
    b = cv2.getTrackbarPos('B', 'hello') 
    colors=(b,g,r)    
   
    print colors 
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing == True:
            img = cp.deepcopy(pre_img)
            if mode == True:
                cv2.rectangle(img, (ix,iy), (x,y), colors, -1)
            else:
                length = int(math.sqrt((ix-x)**2+(iy-y)**2)/2)
                center = (int(float(ix+x)/2), int(float(iy+y)/2))
                cv2.circle(img, center, length, colors, -1)
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv2.rectangle(img, (ix,iy), (x,y), colors,-1)
        else:
            length = int(math.sqrt((ix-x)**2+(iy-y)**2)/2)
            center = (int(float(ix+x)/2), int(float(iy+y)/2))
            cv2.circle(img, center, length, colors, -1)
        pre_img=img
   
   
# 创建面板       
cv2.namedWindow('hello')

# 在面板'hello'上,创建3个trackbar,分别命名为R,G,B,回调函数都是啥都不做
cv2.createTrackbar('R', 'hello', 0,255, nothing)
cv2.createTrackbar('G', 'hello', 0,255, nothing)
cv2.createTrackbar('B', 'hello', 0,255, nothing)

# 创建鼠标事件的回调函数
cv2.setMouseCallback('hello', draw_circle)

while(1):
    cv2.imshow('hello',img)
    k = cv2.waitKey(1) & 0xFF
    # 每次按'm'键都会切换状态,当m=True时,绘制矩形,m=False,绘制圆
    if k == ord('m'):
        mode = not mode
        
    # 如果按了'ESC'键,则关闭面板
    elif k == 27:
        break
    
cv2.destroyAllWindows()
复制代码

绘制出来的效果如下:

 

import cv2 import numpy as np from PyQt5.QtWidgets import QFileDialog, QApplication import sys import zoom_pixel_viewer as pv def nothing(x): pass cv2.namedWindow('Image Process',cv2.WINDOW_NORMAL) cv2.resizeWindow('Image Process',500,800) hh='Max' hl='Min' wnd = 'Image Process' app = QApplication(sys.argv) filenames, filetype = QFileDialog.getOpenFileName() PATH = filenames cv2.createTrackbar("Max", "Image Process",0,255,nothing) cv2.setTrackbarPos("Max", "Image Process",180) cv2.createTrackbar("Min", "Image Process",0,255,nothing) cv2.setTrackbarPos("Min", "Image Process",78) cv2.createTrackbar("Blur", "Image Process",0,20,nothing) cv2.createTrackbar("Dilation", "Image Process",0,5,nothing) cv2.createTrackbar("Erosion", "Image Process",0,5,nothing) cv2.createTrackbar("Zoom", "Image Process",1,10,nothing) cv2.createTrackbar("scale_percent","Image Process",90,110,nothing) cv2.setTrackbarPos("scale_percent", "Image Process",100) cv2.createTrackbar("MedianFilter", "Image Process",0,10,nothing) cv2.createTrackbar("contourMax", "Image Process",0,255,nothing) cv2.createTrackbar("contourMin", "Image Process",0,255,nothing) cv2.createTrackbar("Gamma correct", "Image Process",0,20,nothing) cv2.setTrackbarPos("Gamma correct", "Image Process",10) cv2.createTrackbar("Filter_CA_low", "Image Process",0,10000,nothing) cv2.createTrackbar("Filter_CA_max", "Image Process",0,500000,nothing) cv2.setTrackbarPos("Filter_CA_max", "Image Process",500000) cv2.createTrackbar("max_height", "Image Process",0,3000,nothing) cv2.setTrackbarPos("max_height", "Image Process",3000) cv2.createTrackbar("low_height", "Image Process",0,100,nothing) cv2.setTrackbarPos("low_height", "Image Process",0) cv2.createTrackbar("BINAY_INV", "Image Process",0,1,nothing) cv2.createTrackbar("Color", "Image Process",0,2,nothing) cv2.createTrackbar("ClipLimit", "Image Process",0,100,nothing) cv2.createTrackbar("TileGridSize", "Image Process",0,50,nothing) cv2.createTrackbar("Max_graylevel", "Image Process",0,255,nothing) cv2.setTrackbarPos("Max_graylevel", "Image Process",255) img = cv2.imdecode(np.fromfile(PATH, dtype=np.uint8),cv2.IMREAD_COLOR) temp_img = np.copy(img) img = cv2.resize(img, (0,0), fx=1, fy=1) while(1): #image前处理 hul=cv2.getTrackbarPos("Min", "Image Process") huh=cv2.getTrackbarPos("Max", "Image Process") b = cv2.getTrackbarPos("Blur", "Image Process") d = cv2.getTrackbarPos("Dilation", "Image Process") e = cv2.getTrackbarPos("Erosion", "Image Process") f = cv2.getTrackbarPos("Zoom", "Image Process") m = cv2.getTrackbarPos("MedianFilter", "Image Process") g = cv2.getTrackbarPos("Gamma correct", "Image Process") canny_max=cv2.getTrackbarPos("contourMax", "Image Process") canny_min=cv2.getTrackbarPos("contourMin", "Image Process") CA_low = cv2.getTrackbarPos("Filter_CA_low", "Image Process") CA_max = cv2.getTrackbarPos("Filter_CA_max", "Image Process") max_height = cv2.getTrackbarPos("max_height", "Image Process") low_height = cv2.getTrackbarPos("low_height", "Image Process") BINAY_INV = cv2.getTrackbarPos("BINAY_INV", "Image Process") Color = cv2.getTrackbarPos("Color", "Image Process") Clip = cv2.getTrackbarPos("ClipLimit", "Image Process") GridSize = cv2.getTrackbarPos("TileGridSize", "Image Process") Max_graylevel = cv2.getTrackbarPos("Max_graylevel", "Image Process") scale_percent = cv2.getTrackbarPos("scale_percent","Image Process") #resize scale_percent = 104.1 width = int(img.shape[1]*scale_percent/100) height = int(img.shape[0]*scale_percent/100) dim = (width,height) resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA) #Gamma 校正 gamma = g # gamma < 1 增強暗部,gamma > 1 增強亮部 gamma_corrected = np.power(resized / 255, (gamma/10) ) * 255 gamma_corrected = np.uint8(gamma_corrected) #其他预处理 thresh1 = cv2.GaussianBlur(gamma_corrected,(3,3),b) kernel = np.ones((3,3),np.uint8) thresh1 = cv2.dilate(thresh1,kernel,iterations=d) thresh1 = cv2.erode(thresh1,kernel,iterations=e) thresh1 = cv2.medianBlur(thresh1,(2*m+1)) thresh1 = cv2.cvtColor(thresh1, cv2.COLOR_BGR2GRAY) print (thresh1.dtype) try: clahe = cv2.createCLAHE(clipLimit=Clip, tileGridSize=(GridSize,GridSize)) thresh1 = clahe.apply(thresh1) except: pass ret,thresh2 = cv2.threshold(thresh1,hul,huh,cv2.THRESH_BINARY_INV) #EDGE DETECTION edges = cv2.Canny(thresh1,canny_min,canny_max) edges = 255 - edges #black -> whitecv edges_COLOR = cv2.cvtColor(edges,cv2.COLOR_GRAY2RGB) if Color == 0 : edges_COLOR[np.where((edges_COLOR==[0,0,0]).all(axis=2))] = [255,0,0] if Color == 1 : edges_COLOR[np.where((edges_COLOR==[0,0,0]).all(axis=2))] = [0,255,0] if Color == 2 : edges_COLOR[np.where((edges_COLOR==[0,0,0]).all(axis=2))] = [0,0,255] Conv_hsv_Gray = thresh2 if BINAY_INV == 1 : ret, mask2 = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU) else: ret, mask2 = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY |cv2.THRESH_OTSU) contours , hierarchy = cv2.findContours(mask2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) filtered_contours = [] for contour in contours: area = cv2.contourArea(contour) x,y,w,h = cv2.boundingRect(contour) if area > CA_low and h < max_height and area < CA_max and low_height < h : # 根據實際圖像調整閾值 filtered_contours.append(contour) areas = [cv2.contourArea(contour) for contour in filtered_contours] total_area = sum(areas) # 在圖像上繪製輪廓並標註面積 ''' filtered_contours_2 = [] for cnt in filtered_contours: if h < max_height: filtered_contours_2.append(cnt) ''' output_img=resized contour_img = np.ones_like(resized,dtype=np.uint8)*255 #创建空白图像 取过滤后的contour if Color == 0: cv2.drawContours(contour_img, filtered_contours, -1,(255,0,0) ,1) if Color == 1: cv2.drawContours(contour_img, filtered_contours, -1,(0,255,0) ,1) if Color == 2: cv2.drawContours(contour_img, filtered_contours, -1,(0,0,255) ,1) thresh1 = cv2.cvtColor(thresh1,cv2.COLOR_GRAY2RGB) #img2 = edges_COLOR img2 = contour_img #换过滤后的contour #img1 = gamma_corrected img1 = thresh1 img1 = resized rows,cols,channels = img2.shape roi = img1[0:rows,0:cols] img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) #ret, mask = cv2.threshold(img2gray,175,255,cv2.THRESH_BINARY) ret, mask = cv2.threshold(img2gray,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU) mask_inv = cv2.bitwise_not(mask) img1_bg = cv2.bitwise_and(roi,roi,mask = mask) img2_fg = cv2.bitwise_and(img2,img2,mask = mask_inv) dst = cv2.add(img1_bg,img2_fg) #ret,thresh2 = cv2.threshold(img,hul,huh,cv2.THRESH_BINARY_INV) #ret,thresh3 = cv2.threshold(img,hul,huh,cv2.THRESH_TRUNC) #ret,thresh4 = cv2.threshold(img,hul,huh,cv2.THRESH_TOZERO) #ret,thresh5 = cv2.threshold(img,hul,huh,cv2.THRESH_TOZERO_INV) dst = cv2.resize(dst, (0,0), fx=0.5+(f/10), fy=0.5+(f/10)) edges_COLOR = cv2.resize(edges_COLOR, (0,0), fx=0.5+(f/10), fy=0.5+(f/10)) thresh1 = cv2.resize(thresh1, (0,0), fx=0.5+(f/10), fy=0.5+(f/10)) contour_img = cv2.resize(contour_img, (0,0), fx=0.5+(f/10), fy=0.5+(f/10)) image1=contour_img lower_white = np.array([230,230, 230]) # 白色下界,可調整 upper_white = np.array([255, 255, 255]) # 白色上界 mask1 = cv2.inRange(image1, lower_white, upper_white) # 白色區域為 255,其他為 0 #mask2 = cv2.inRange(image2, lower_white, upper_white) # 白色區域為 255,其他為 0 # 將遮罩中白色區域在原圖上反轉為黑色 result1 = image1.copy() #result2 = image2.copy() result1[mask1 == 255] = [0, 0, 0] # 將白色區域設為黑色 (RGB = 0, 0, 0) cv2.imshow("Chlaeenhance",thresh1) cv2.imshow("Contour",edges_COLOR) cv2.imshow("Img_contour",dst) cv2.imshow("contour_filter",result1) #cv2.imshow("Conv_hsv_Gray",Conv_hsv_Gray) #cv2.imshow("thresh4",thresh4) #cv2.imshow("thresh5",thresh5) k = cv2.waitKey(1) & 0xFF if k == ord ('a'): pv.show(dst) #pv.show(result1) if k == ord ('s'): #cv2.imwrite(PATH[0:-4]+'_BINARY.jpg',thresh1) #cv2.imwrite(PATH[0:-4]+'_contour_filter.jpg',contour_img) cv2.imwrite(PATH[0:-4]+'_contour_filter_black.png',result1) cv2.imwrite(PATH[0:-4]+'_dst.png',dst) if k == ord ('m'): while(1): dst2 = dst.copy() edges_COLOR2 = edges_COLOR.copy() # 全局变量 g_window_name = "img" # 窗口名 g_window_wh = [800, 800] # 窗口宽高 g_location_win = [0, 0] # 相对于大图,窗口在图片中的位置 location_win = [0, 0] # 鼠标左键点击时,暂存g_location_win g_location_click, g_location_release = [0, 0], [0, 0] # 相对于窗口,鼠标左键点击和释放的位置 g_zoom, g_step = 1, 0.1 # 图片缩放比例和缩放系数 g_image_original = edges_COLOR2 # 原始图片,建议大于窗口宽高(800*600) g_image_zoom = g_image_original.copy() # 缩放后的图片 g_image_show = g_image_original[g_location_win[1]:g_location_win[1] + g_window_wh[1], g_location_win[0]:g_location_win[0] + g_window_wh[0]] # 实际显示的图片 # 矫正窗口在图片中的位置 # img_wh:图片的宽高, win_wh:窗口的宽高, win_xy:窗口在图片的位置 def check_location(img_wh, win_wh, win_xy): for i in range(2): if win_xy[i] < 0: win_xy[i] = 0 elif win_xy[i] + win_wh[i] > img_wh[i] and img_wh[i] > win_wh[i]: win_xy[i] = img_wh[i] - win_wh[i] elif win_xy[i] + win_wh[i] > img_wh[i] and img_wh[i] < win_wh[i]: win_xy[i] = 0 print(img_wh, win_wh, win_xy) # 计算缩放倍数 # flag:鼠标滚轮上移或下移的标识, step:缩放系数,滚轮每步缩放0.1, zoom:缩放倍数 def count_zoom(flag, step, zoom): if flag > 0: # 滚轮上移 zoom += step if zoom > 1 + step * 20: # 最多只能放大到3倍 zoom = 1 + step * 20 else: # 滚轮下移 zoom -= step if zoom < step: # 最多只能缩小到0.1倍 zoom = step zoom = round(zoom, 2) # 取2位有效数字 return zoom def on_checkbox(state, userdata): print (f"Checkbox state: { 'Checked' if state else 'Unchecked'}") # OpenCV鼠标事件 def mouse(event, x, y, flags, param): global g_location_click, g_location_release, g_image_show, g_image_zoom, g_location_win, location_win, g_zoom if event == cv2.EVENT_LBUTTONDOWN: # 左键点击 g_location_click = [x, y] # 左键点击时,鼠标相对于窗口的坐标 location_win = [g_location_win[0], g_location_win[1]] # 窗口相对于图片的坐标,不能写成location_win = g_location_win elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左键拖曳 g_location_release = [x, y] # 左键拖曳时,鼠标相对于窗口的坐标 h1, w1 = g_image_zoom.shape[0:2] # 缩放图片的宽高 w2, h2 = g_window_wh # 窗口的宽高 show_wh = [0, 0] # 实际显示图片的宽高 if w1 < w2 and h1 < h2: # 图片的宽高小于窗口宽高,无法移动 show_wh = [w1, h1] g_location_win = [0, 0] elif w1 >= w2 and h1 < h2: # 图片的宽度大于窗口的宽度,可左右移动 show_wh = [w2, h1] g_location_win[0] = location_win[0] + g_location_click[0] - g_location_release[0] elif w1 < w2 and h1 >= h2: # 图片的高度大于窗口的高度,可上下移动 show_wh = [w1, h2] g_location_win[1] = location_win[1] + g_location_click[1] - g_location_release[1] else: # 图片的宽高大于窗口宽高,可左右上下移动 show_wh = [w2, h2] g_location_win[0] = location_win[0] + g_location_click[0] - g_location_release[0] g_location_win[1] = location_win[1] + g_location_click[1] - g_location_release[1] check_location([w1, h1], [w2, h2], g_location_win) # 矫正窗口在图片中的位置 g_image_show = g_image_zoom[g_location_win[1]:g_location_win[1] + show_wh[1], g_location_win[0]:g_location_win[0] + show_wh[0]] # 实际显示的图片 elif event == cv2.EVENT_MOUSEWHEEL: # 滚轮 z = g_zoom # 缩放前的缩放倍数,用于计算缩放后窗口在图片中的位置 g_zoom = count_zoom(flags, g_step, g_zoom) # 计算缩放倍数 w1, h1 = [int(g_image_original.shape[1] * g_zoom), int(g_image_original.shape[0] * g_zoom)] # 缩放图片的宽高 w2, h2 = g_window_wh # 窗口的宽高 g_image_zoom = cv2.resize(g_image_original, (w1, h1), interpolation=cv2.INTER_AREA) # 图片缩放 show_wh = [0, 0] # 实际显示图片的宽高 if w1 < w2 and h1 < h2: # 缩放后,图片宽高小于窗口宽高 show_wh = [w1, h1] cv2.resizeWindow(g_window_name, w1, h1) elif w1 >= w2 and h1 < h2: # 缩放后,图片高度小于窗口高度 show_wh = [w2, h1] cv2.resizeWindow(g_window_name, w2, h1) elif w1 < w2 and h1 >= h2: # 缩放后,图片宽度小于窗口宽度 show_wh = [w1, h2] cv2.resizeWindow(g_window_name, w1, h2) else: # 缩放后,图片宽高大于窗口宽高 show_wh = [w2, h2] cv2.resizeWindow(g_window_name, w2, h2) g_location_win = [int((g_location_win[0] + x) * g_zoom / z - x), int((g_location_win[1] + y) * g_zoom / z - y)] # 缩放后,窗口在图片的位置 check_location([w1, h1], [w2, h2], g_location_win) # 矫正窗口在图片中的位置 # print(g_location_win, show_wh) g_image_show = g_image_zoom[g_location_win[1]:g_location_win[1] + show_wh[1], g_location_win[0]:g_location_win[0] + show_wh[0]] # 实际的显示图片 cv2.imshow(g_window_name, g_image_show) # 主函数 if __name__ == "__main__": # 设置窗口 cv2.namedWindow(g_window_name, cv2.WINDOW_NORMAL) # 设置窗口大小,只有当图片大于窗口时才能移动图片 cv2.resizeWindow(g_window_name, g_window_wh[0], g_window_wh[1]) cv2.moveWindow(g_window_name, 700, 100) # 设置窗口在电脑屏幕中的位置 # 鼠标事件的回调函数 cv2.setMouseCallback(g_window_name, mouse) #cv2.waitKey(0) # 不可缺少,用于刷新图片,等待鼠标操作 #cv2.destroyAllWindows() elif k == 27: #wait for ESC key to exit break if k == 27: #wait for ESC key to exit img= temp_img img = cv2.resize(img, (0,0), fx=2, fy=2) break # elif k == 27: #wait for ESC key to exit # break if cv2.getWindowProperty("Chlaeenhance", cv2.WND_PROP_VISIBLE) < 1 : break if cv2.getWindowProperty("Contour", cv2.WND_PROP_VISIBLE) < 1 : break if cv2.getWindowProperty("Img_contour", cv2.WND_PROP_VISIBLE) < 1 : break cv2.destroyAllWindows() ****解读一下这个程序
最新发布
12-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值