鱼C论坛

 找回密码
 立即注册
查看: 1650|回复: 0

[技术交流] 利用opencv以及easygui实现简易的多功能小程序(二)

[复制链接]
发表于 2020-10-21 21:12:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. import numpy as np
  2. from PIL import Image
  3. import matplotlib.pyplot as plt
  4. import matplotlib.cm as cm
  5. import scipy.signal as signal
  6. import cv2 as cv
  7. import random
  8. import easygui as g
  9. import imutils
  10. import time

  11. class Point(object):
  12.     def __init__(self,x,y):
  13.         self.x = x
  14.         self.y = y
  15.     def getX(self):
  16.         return self.x
  17.     def getY(self):
  18.         return self.y
  19. def criterion(p):  #定义我们自己种子生长的准则,p=1为一种规则,p=0为一种生长规则
  20.     if p == 1:
  21.         connect = [Point(-1,-1),Point(-1,0),Point(0,-1),Point(0,1),Point(1,1),Point(1,0),Point(-1,1),Point(1,-1)]
  22.     else:
  23.         connect = [Point(-1,0),Point(0,-1),Point(0,1),Point(1,0)]
  24.     return connect
  25. def gray_distance(image,point1,point2):    #返回灰度值之间的差异,太大的我们舍弃
  26.     return abs(int(image[point1.x,point1.y])-int(image[point2.x,point2.y]))
  27. def seed_growing(image):
  28.     thresh = 3
  29.     #我们自己设置的门限
  30.     label1 = 1    #label = 1这样的话图像中为黑色,容易发现
  31.     seed = [Point(250,100),Point(82,75),Point(20,300)]                #定义初始种子点
  32.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  33.     image = image.astype(np.uint8)
  34.     rows = image.shape[0]
  35.     cols = image.shape[1]
  36.     image_mark = np.full((rows,cols),255)
  37.     seedlist = []
  38.     p=1                 #定义我们自己的准则
  39.     connects = criterion(p)
  40.     for i in seed:
  41.         seedlist.append(i)
  42.     while ( len(seedlist) > 0):
  43.         seed_testing = seedlist.pop(0)
  44.         image_mark[seed_testing.x,seed_testing.y] = label1
  45.         for i in range(8):   #因为我定义的P为1 所以是8个点,p=0则有四个点
  46.             tempX = seed_testing.x + connects[i].x
  47.             tempY = seed_testing.y + connects[i].y
  48.             if tempX < 0 or tempY < 0 or tempX >=rows or tempY >= cols:
  49.                 continue
  50.             gray_dis = gray_distance(image,seed_testing,Point(tempX,tempY))
  51.             if gray_dis < thresh and image_mark[tempX,tempY] == 255:
  52.                 seedlist.append(Point(tempX,tempY))
  53.                 image_mark[tempX,tempY] = label1
  54.     cv.imshow('seed grow',image_mark.astype(np.uint8))
  55.     cv.waitKey(0)


  56. def nothing(x):
  57.     pass

  58. def change_number(image):
  59.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  60.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  61.     rows = image.shape[0]
  62.     cols = image.shape[1]
  63.     min_area = 0
  64.     max_area = 0
  65.     area = rows * cols
  66.     cv.namedWindow('could change threshhold')
  67.     cv.createTrackbar('intensity', 'could change threshhold', 0, 255, nothing)
  68.     count = 0
  69.     # chance =0
  70.     data1 = 699
  71.     data = 0
  72.     while (1):
  73.         cv.imshow('could change threshhold', image) # 返回滑块所在位置对应的值
  74.         medium_number = cv.getTrackbarPos('intensity', 'could change threshhold')
  75.         # if chance == 0:
  76.         image2 =image.copy()
  77.         for i in range(rows):
  78.             for j in range(cols):
  79.                 if int(image2[i, j]) < medium_number:
  80.                     image2[i, j] = 0
  81.                     min_area += 1
  82.                 else:
  83.                     image2[i, j] = 255
  84.                     max_area += 1
  85.         image2 = image2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  86.         cv.imshow('image2',image2)
  87.         data +=1
  88.         if data ==8:   #设置我们自己的时钟,按Q退出
  89.             string = 'gray area is {},white area is {}'.format(min_area * area / (min_area + max_area),max_area * area / (min_area + max_area))
  90.             print(string)
  91.             data = 0
  92.         # data +=1
  93.         # if data == 2:
  94.             # if data1 != medium_number:
  95.             #     data1 = medium_number
  96.             #     count = 0
  97.             # else:
  98.             #     count +=1
  99.             #     if count == 2:
  100.                     # image3 = image.copy()
  101.                     # for i in range(rows):
  102.                     #     for j in range(cols):
  103.                     #         if int(image3[i, j]) < medium_number:
  104.                     #             image3[i, j] = 0
  105.                     #             min_area += 1
  106.                     #         else:
  107.                     #             image3[i, j] = 255
  108.                     #             max_area += 1
  109.                     # image3 = image3.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  110.             # string = 'gray area is {},white area is {}'.format(min_area * area / (min_area + max_area),max_area * area / (min_area + max_area))
  111.             # print(string)
  112.             # count =0
  113.         # data = 0
  114.         # chance +=1
  115.         if cv.waitKey(1) == ord('q'):
  116.             break
  117.     cv.destroyAllWindows()


  118. def static_number(image):   #也进行灰度化
  119.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  120.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  121.     rows = image.shape[0]
  122.     cols = image.shape[1]
  123.     sum2 = []
  124.     for i in range(rows):
  125.         for j in range(cols):
  126.             sum2.append(int(image[i, j]))
  127.     sum2.sort()
  128.     medium_number = sum2[len(sum2)//2]     #去中位数的灰度值
  129.     min_area = 0
  130.     max_area = 0
  131.     area = rows * cols
  132.     for i in range(rows):
  133.         for j in range(cols):
  134.             if int(image[i,j]) < medium_number:
  135.                 image[i,j] = 0
  136.                 min_area +=1
  137.             else:
  138.                 image[i,j] = 255
  139.                 max_area +=1
  140.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  141.     g.msgbox('灰色区域面积为{0},白色面积为{1}'.format(min_area * area /(min_area+max_area),max_area * area/(min_area+max_area) ))
  142.     cv.imshow('static number image',image)
  143.     cv.waitKey(0)



  144. def myvar(image):   #将输入图片转换为灰度图
  145.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  146.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  147.     rows = image.shape[0]
  148.     cols = image.shape[1]
  149.     sum1=[]
  150.     for i in range(rows):
  151.         for j in range(cols):
  152.             sum1.append(int(image[i,j]))
  153.     sum_average = sum(sum1)/len(sum1)
  154.     var_sum=[]
  155.     for i in range(rows):
  156.         for j in range(cols):
  157.             var_sum.append(image[i,j]**2/len(sum1))
  158.     var = sum(var_sum) - sum_average**2
  159.     return var



  160. def hist_stretch(image):     #没做灰度变换
  161.     r_min, r_max = 255, 0
  162.     a=[]
  163.     for i in range(image.shape[0]):
  164.         for j in range(image.shape[1]):
  165.             for k in range(image.shape[2]):
  166.                 a.append(image[i,j,k])
  167.                 if image[i, j, k] > r_max:
  168.                     r_max = image[i, j, k]
  169.                 if image[i, j, k] < r_min:
  170.                     r_min = image[i, j, k]
  171.     a=np.array(a).reshape(-1)
  172.     a_var=np.var(a)
  173.     r1, s1 = r_min, 0
  174.     r2, s2 = r_max, 255  # 这四个值决定了分段函数的走向
  175.     # k1 = s1 / r1
  176.     # k3 = (255 - s2) / (255 - r2)
  177.     k2 = (s2 - s1) / (r2 - r1)     #255 * (最大灰度值-最小灰度值)

  178.     b=[]
  179.     precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)
  180.     for i in range(image.shape[0]):
  181.         for j in range(image.shape[1]):
  182.             for k in range(image.shape[2]):
  183.                 precewise_img[i, j, k] = k2 * (image[i, j, k] - r1)
  184.                 b.append(precewise_img[i,j,k])
  185.     b = np.array(b).reshape(-1,1)
  186.     b_var = np.var(b)
  187.     # g.msgbox('变换前的方差为{},变换后的方差为{}'.format(int(a),int(b)))
  188.     print(a)
  189.     print(b)
  190.     # 原图中做分段线性变化后需要对图像进行归一化操作,并将数据类型转换到np.uint8
  191.     cv.normalize(precewise_img, precewise_img, 0, 255, cv.NORM_MINMAX)
  192.     precewise_img = cv.convertScaleAbs(precewise_img)
  193.     g.msgbox('处理前的图片方差为{one},处理后的方差为{two}'.format(one=myvar(image), two=myvar(precewise_img)))

  194.     cv.imshow('origin image', imutils.resize(image, 480))
  195.     cv.imshow('hist_stretch image', imutils.resize(precewise_img, 480))
  196.     if cv.waitKey(0) == 27:
  197.         cv.destroyAllWindows()

  198. def muti_liner_stretch(image):                #s1,s2分别为灰度级上的两个边界,#该分段线性拉伸法,将灰度级分成三分,一份小于最小灰度级,一份大于最大灰度级,这两部分无定义,直接映射中间部分
  199.     # r_min, r_max = 255, 0
  200.     # for i in range(image.shape[0]):               #没做灰度变换
  201.     #     for j in range(image.shape[1]):
  202.     #         for k in range(image.shape[2]):
  203.     #             if image[i, j, k] > r_max:
  204.     #                 r_max = image[i, j, k]
  205.     #             if image[i, j, k] < r_min:
  206.     #                 r_min = image[i, j, k]
  207.     r1, s1 = 50,100
  208.     r2, s2 = 170,200      #这四个值决定了分段函数的走向
  209.     k1 = s1 / r1
  210.     k3 = (255 - s2) / (255 - r2)
  211.     k2 = (s2 - s1) / (r2 - r1)

  212.     precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)
  213.     for i in range(image.shape[0]):
  214.         for j in range(image.shape[1]):
  215.             for k in range(image.shape[2]):
  216.                 if r1 <= image[i, j, k] <= r2:
  217.                     precewise_img[i, j, k] = k2 * (image[i, j, k] - r1)
  218.                 elif image[i, j, k] < r1:
  219.                     precewise_img[i, j, k] = k1 * image[i, j, k]
  220.                 elif image[i, j, k] > r2:
  221.                     precewise_img[i, j, k] = k3 * (image[i, j, k] - r2)

  222.     # 原图中做分段线性变化后需要对图像进行归一化操作,并将数据类型转换到np.uint8
  223.     cv.normalize(precewise_img, precewise_img, 0, 255, cv.NORM_MINMAX)
  224.     precewise_img = cv.convertScaleAbs(precewise_img)
  225.     g.msgbox('处理前的图片方差为{one},处理后的方差为{two}'.format(one=myvar(image),two=myvar(precewise_img)))    #函数本身没做灰度化,但是求方差时我做了灰度化
  226.     cv.imshow('origin image', imutils.resize(image, 480))
  227.     cv.imshow('muti_liner_stretch image', imutils.resize(precewise_img, 480))
  228.     if cv.waitKey(0) == 27:
  229.         cv.destroyAllWindows()
  230. def medium_filter(image):  #中值滤波模板为3*3
  231.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  232.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  233.     # kernal_size=np.ones((3,3))
  234.     rows=image.shape[0]
  235.     cols = image.shape[1]
  236.     gray_data = image.copy()
  237.     img_new = []
  238.     for i in range(rows-3):   #减去3的原因是自己定义的模板都是3*3
  239.         line = []             #line记录着每一行的信息
  240.         for j in range(cols-3):
  241.             a = gray_data[i:i+3,j:j+3]  #此时类型a为np.uint8,转化为array类型方便后续计算
  242.             a=np.array(a)
  243.             a=np.sort(a.reshape(-1))
  244.             line.append(a[4])   #np.multiply表示两个矩阵点乘
  245.         img_new.append(line)   #记录着每一行卷积后的结果
  246.     image2=np.array(img_new)
  247.     image2 = (image2 / float(image2.max())) * 255

  248. # 显示图像
  249.     plt.subplot(2,1,1)
  250.     plt.title('original image')
  251.     plt.imshow(image,cmap=cm.gray)
  252.     plt.axis("off")
  253.     plt.subplot(2,1,2)
  254.     plt.title('after medium image')
  255.     plt.imshow(image2,cmap=cm.gray)
  256.     plt.axis("off")
  257.     plt.show()

  258. def PepperandSalt(image,percentage):   # percentage表示噪声点出现的概率    #进来的第一步是灰度化
  259.     # R = np.mat(image[:, :, 0])
  260.     # G = np.mat(image[:, :, 1])
  261.     # B = np.mat(image[:, :, 2])
  262.     # img_gray2 = R * 0.299 + G * 0.587 + B * 0.114
  263.     img_gray2 = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  264.     img_gray2 = img_gray2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  265.     NoiseImg=img_gray2
  266.     rows,cols=NoiseImg.shape
  267.     NoiseNum=int(percentage*rows*cols)
  268.     for i in range(NoiseNum):
  269.         randX=np.random.randint(0,rows)
  270.         randY=np.random.randint(0,cols)
  271.         if random.randint(0,1) == 0:
  272.             NoiseImg[randX,randY]=0
  273.         else:
  274.             NoiseImg[randX,randY]=255
  275.     cv.imshow('Peppernoise image', NoiseImg)
  276.     cv.waitKey(1000)

  277. def GaussianNoise(image,mean,sigma):     #mean表示均值,sigma表示方差    #第一步是灰度化
  278.     # R=np.mat(image[:,:,0])
  279.     # G=np.mat(image[:,:,1])
  280.     # B=np.mat(image[:,:,2])
  281.     # img_gray2 = R*0.299+G*0.587+B*0.114
  282.     img_gray2 = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  283.     img_gray2 = img_gray2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  284.     NoiseImg=img_gray2
  285.     rows = NoiseImg.shape[0]
  286.     cols = NoiseImg.shape[1]
  287.     rows,cols=NoiseImg.shape
  288.     for i in range(rows):
  289.         for j in range(cols):
  290.             NoiseImg[i,j]=NoiseImg[i,j]+random.gauss(mean,sigma)
  291.     # NoiseImg = NoiseImg+np.random.normal(mean,sigma,NoiseImg.shape)
  292.     # NoiseImg =  NoiseImg - np.full( NoiseImg.shape, np.min( NoiseImg))     # 全填充限定像素值下限(减去最小值,下限重新定义为0)
  293.     # NoiseImg =  NoiseImg * 255 / np.max( NoiseImg)               #限定像素值上限
  294.             if NoiseImg[i,j]<0:
  295.                 NoiseImg[i,j] = 0
  296.             elif NoiseImg[i,j]>255:
  297.                 NoiseImg[i,j] = 255
  298.     cv.imshow('guasenoise image', NoiseImg)
  299.     cv.waitKey(1000)

  300. def salt(image1,number):      #number表述噪声点数量
  301.     image = image1.copy()
  302.     rows= image.shape[0]
  303.     cols = image.shape[1]
  304.     for i in range(number):
  305.         x=np.random.randint(0,rows)   #np.ranom.randint 取不到右边界,ranodm.randint取得到右边界
  306.         y=np.random.randint(0,cols)
  307.         c=random.randint(0,1)
  308.         if c == 1:
  309.             image[x,y] = 255
  310.         else:
  311.             image[x,y] = 0
  312.     return image
  313. def convolution(kernal_size, image):
  314.     rows=image.shape[0]
  315.     cols = image.shape[1]
  316.     gray_data = image.copy()
  317.     img_new = []
  318.     for i in range(rows-3):   #减去3的原因是自己定义的模板都是3*3
  319.         line = []             #line记录着每一行的信息
  320.         for j in range(cols-3):
  321.             a = gray_data[i:i+3,j:j+3]
  322.             a=np.array(a)
  323.             line.append(np.sum(np.multiply(kernal_size, a)))   #np.multiply表示两个矩阵点乘
  324.         img_new.append(line)   #记录着每一行卷积后的结果
  325.     return np.array(img_new)
  326. def mean_image(image):                  #均值滤波     #进来的第一不也是灰度化
  327.     suanzi = np.ones((3,3))/9 # 创建全1算子(1/9)
  328.     # 打开图像并转化成灰度图像
  329.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  330.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  331.     image2 = convolution(image=image,kernal_size=suanzi)
  332.     # 将结果灰度值转化到0-255
  333.     image2 = (image2/float(image2.max()))*255
  334.     image3=cv.blur(image,(5,5))

  335.     # 显示图像
  336.     plt.subplot(3,1,1)
  337.     plt.title('original image')
  338.     plt.imshow(image,cmap=cm.gray)
  339.     plt.axis("off")
  340.     plt.subplot(3,1,2)
  341.     plt.title('after meaning image')
  342.     plt.imshow(image2,cmap=cm.gray)
  343.     plt.axis("off")
  344.     plt.subplot(3, 1, 3)
  345.     plt.title('function made')
  346.     plt.imshow(image3, cmap=cm.gray)
  347.     plt.axis("off")
  348.     plt.show()
  349. def func(x,y,sigma=1):
  350.     return 100*(1/(2*np.pi*sigma))*np.exp(-((x-1)**2+(y-1)**2)/(2.0*sigma**2))   #创建高斯函数,该函数中心为(1,1),所以创建3*3比较合适

  351. def gause_image(image):             #高斯滤波,第一步也实现了灰度化
  352.     suanzi = np.fromfunction(func,(3,3),sigma=2)  # 创建高斯函数,(1,1)为函数的中心,这里是生成3*3的标准差为2的高斯算子
  353.     # 打开图像并转化成灰度图像
  354.     image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
  355.     image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
  356.     image2 = convolution(image=image, kernal_size=suanzi)
  357.     # 将结果灰度值转化到0-255
  358.     image2 = (image2 / float(image2.max())) * 255

  359.     # 显示图像
  360.     plt.subplot(2, 1, 1)
  361.     plt.title('original image')
  362.     plt.imshow(image, cmap=cm.gray)
  363.     plt.axis("off")
  364.     plt.subplot(2, 1, 2)
  365.     plt.title('after gause image')
  366.     plt.imshow(image2, cmap=cm.gray)
  367.     plt.axis("off")
  368.     plt.show()
  369. if __name__ == '__main__':
  370.     # image1 = cv.imread('D:\\test.jpg')  #读取我们的照片
  371.     # # image_salt = salt(image,2000)       #加入噪声
  372.     # # mean_image(image_salt)
  373.     # # gause_image(image_salt)
  374.     # GaussianNoise(image1, mean=2, sigma=14)
  375.     # cv.imshow('salt image', PepperandSalt(image1, percentage=0.01))
  376.     msg = "请输入您想要完成的任务(建议您第一步先打开图片)"
  377.     title = '第二次作业'
  378.     choice = ('打开图片', '退出')
  379.     a = g.buttonbox(msg=msg, title=title, choices=choice)
  380.     if a == '打开图片':
  381.         filename = g.fileopenbox(msg="请打开一个jpg文件")
  382.         img = cv.imread(filename)
  383.         msg1 = "选择您想要实现的功能"
  384.         title1 = '第二次作业'
  385.         choice1 = ('显示噪声图', '滤波', '阈值分割', '分段线性法拉伸', '直方图拉伸', '区域生长法分割','重新选择图片','退出')
  386.         q = 1
  387.         while q:
  388.             b = g.buttonbox(msg=msg1, title=title1, choices=choice1)
  389.             # while b!='退出':
  390.             if b == '显示噪声图':
  391.                 msg2 = "选择您想要实现的功能"
  392.                 title2 = '第二次作业'
  393.                 choice2 = ('灰色椒盐噪声图', '灰色高斯噪声图','退出')
  394.                 q1=1
  395.                 while q1:
  396.                     noise_image_choice = g.buttonbox(msg=msg2, title=title2, choices=choice2)
  397.                     if noise_image_choice == '灰色椒盐噪声图':
  398.                         PepperandSalt(img, percentage=0.01) #这里设置椒盐噪声点出现的概率为0.01
  399.                     elif noise_image_choice == '灰色高斯噪声图':
  400.                         GaussianNoise(img, mean=2, sigma=14) #这里设置均值为2,方差为4
  401.                     else:
  402.                         q1 =0

  403.             elif b == '滤波':
  404.                 msg_b = "选择您想要实现的功能"
  405.                 title_b = '第二次作业'
  406.                 choice_b = ('均值滤波', '高斯滤波','中值滤波')
  407.                 q_b = 1
  408.                 while q_b:
  409.                     b_remove_noise = g.buttonbox(msg=msg_b, title=title_b, choices=choice_b)
  410.                     if b_remove_noise == '均值滤波':
  411.                         mean_image(salt(img,number=5000))          #salt为自己定义的可以随意增加噪声点的函数,number为自己定义噪声点的数量
  412.                     elif b_remove_noise =='高斯滤波':
  413.                         gause_image(salt(img,number=5000))
  414.                     elif b_remove_noise == '中值滤波':
  415.                         medium_filter(salt(img,number=5000))
  416.                     else:
  417.                         q_b = 0

  418.             elif b == '阈值分割':
  419.                 msg_b1 = "选择您想要实现的功能"
  420.                 title_b1 = '第二次作业'
  421.                 choice_b1 = ('固定阈值', '调节参数窗')
  422.                 q_b1 = 1
  423.                 while q_b1:
  424.                     b_remove_noise1 = g.buttonbox(msg=msg_b1, title=title_b1, choices=choice_b1)
  425.                     if b_remove_noise1 == '固定阈值':
  426.                         static_number(img)
  427.                     elif b_remove_noise1 == '调节参数窗':
  428.                         change_number(img)
  429.                     else:
  430.                         q_b1 = 0

  431.             elif b == '分段线性法拉伸':
  432.                 muti_liner_stretch(img)
  433.             elif b == '直方图拉伸':
  434.                 hist_stretch(img)
  435.             elif b == '区域生长法分割':
  436.                 seed_growing(img)
  437.             elif b == '重新选择图片':
  438.                 filename = g.fileopenbox(msg="请打开一个jpg文件")
  439.                 img = cv.imread(filename)
  440.             else:
  441.                 q = 0
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-28 16:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表