提交 b4300c88 编写于 作者: 得过且过的勇者y's avatar 得过且过的勇者y

Initial commit

上级 3fbdd5d6
import cv2
# 鼻子检测
def nose_detection(img):
img = cv2.GaussianBlur(img, (5, 5), 0) # 高斯滤波
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图片转化成灰度
nose_cascade = cv2.CascadeClassifier("haarcascade_mcs_nose.xml")
nose_cascade.load("data/haarcascades/haarcascade_mcs_nose.xml") # 文件所在的具体位置
'''此文件是opencv的haar鼻子特征分类器'''
noses = nose_cascade.detectMultiScale(gray, 1.3, 5) # 鼻子检测
for (x, y, w, h) in noses:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # 画框标识鼻子
flag = 0 # 检测到鼻子的标志位,如果监测到鼻子,则判断未带口罩
if len(noses) > 0:
flag = 1
return img, flag
# 眼睛检测
def eye_detection(img):
img = cv2.GaussianBlur(img, (5, 5), 0) # 高斯滤波
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图片转化成灰度
eyes_cascade = cv2.CascadeClassifier("haarcascade_eye_tree_eyeglasses.xml")
eyes_cascade.load("data/haarcascades/haarcascade_eye_tree_eyeglasses.xml") # 文件所在的具体位置
'''此文件是opencv的haar眼睛特征分类器'''
eyes = eyes_cascade.detectMultiScale(gray, 1.3, 5) # 眼睛检测
for (x, y, w, h) in eyes:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # 画框标识眼部
# print("x y w h is", (x, y, w, h))
# frame = cv2.rectangle(img, (x, y+h), (x + 3*w, y + 3*h), (255, 0, 0), 2) # 画框标识眼部
return img, eyes
def back(x):
pass
# 嘴巴检测
def get_mouth(faces, predictor, img_gray):
for i, face in enumerate(faces):
# 人脸高度
height = face.bottom() - face.top()
# 人脸宽度
width = face.right() - face.left()
shape = predictor(img_gray, face)
# 48-67 为嘴唇部分
x = []
y = []
for j in range(48, 68):
x.append(shape.part(j).x)
y.append(shape.part(j).y)
# 根据嘴唇位置和人脸大小推断口罩位置
y_max = int(max(y) + 2 * height / 5 + 10)
y_min = int(min(y) - 2 * height / 5 - 10)
x_max = int(max(x) + 2 * width / 5)
x_min = int(min(x) - 2 * width / 5)
size = ((x_max - x_min), (y_max - y_min))
return x_min, x_max, y_min, y_max, size
import time
import cv2
import numpy as np
# 双边滤波,size为核大小
def bilateral_filter(image, size=3, sigma_s=20, sigma_c=20):
h, w, c = image.shape # 获取图像信息
image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REPLICATE) # 扩展边界
pic_ = image.copy()
time_start = time.time()
for i in range(size, size + h): # 双边滤波
for j in range(size, size + w):
for k in range(c):
tol_up = 0.0
tol_down = 0.0
for m in range(i - size, i + size + 1):
for n in range(j - size, j + size + 1):
temp = get_g(image, i, j, m, n, k, sigma_s, sigma_c)
tol_up += temp * pic_[m, n, k]
tol_down += temp
value = min(255.0, tol_up / tol_down) # 防止值溢出
pic_[i, j, k] = value
time_end = time.time()
print("花费时间:", time_end - time_start)
return pic_[size: size + h, size: size + w] # 裁剪回原图
def get_g(image, i, j, m, n, k, sigma_s, sigma_c):
gs = np.exp(-((i - m) ** 2 + (j - n) ** 2) / (2 * sigma_s ** 2))
gr = np.exp(-(float(image[i, j, k]) - float(image[m, n, k])) ** 2 / (2 * sigma_c ** 2))
return gs * gr
# 中值滤波,size为核大小
def median_filter(image, size=3):
h, w, c = image.shape
image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REPLICATE) # 扩展边界
pic_ = image.copy()
for i in range(size, size + h):
for j in range(size, size + w):
for k in range(c):
pic_[i, j, k] = np.median(image[i-size: i+size, j-size: j+size, k]) # 调用np.median求取中值
return pic_
# 均值滤波,size为核大小
def average_filter(image, size=3):
h, w, c = image.shape
image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REPLICATE) # 扩展边界
pic_ = image.copy()
for i in range(size, size + h):
for j in range(size, size + w):
for k in range(c):
pic_[i, j, k] = np.mean(image[i-size: i+size, j-size: j+size, k]) # 调用np.median求取均值
return pic_
# 高通滤波, r为通带半径
def high_pass_filter(image, r=40):
image_ = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
dft = np.fft.fft2(image_)
# 将频域从左上角移动到中间
dft_shift = np.fft.fftshift(dft)
h, w = dft_shift.shape[0], dft_shift.shape[1]
mh, mw = int(h/2), int(w/2) # 中心位置
dft_shift[mh-r: mh+r, mw-r: mw+r] = 0
# 傅里叶逆变换
i_dft_shift = np.fft.ifftshift(dft_shift)
i_image = np.fft.ifft2(i_dft_shift)
i_image = np.uint8(np.abs(i_image))
return i_image
# 低通滤波器
def low_pass_filter(img, size=60):
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 傅里叶变换
img_dft = np.fft.fft2(img)
# 将频域从左上角移动到中间
dft_shift = np.fft.fftshift(img_dft)
# 高通滤波
h, w = dft_shift.shape[0], dft_shift.shape[1]
mh, mw = int(h/2), int(w/2)
mask = np.zeros(dft_shift.shape, dtype=np.uint8)
mask[mh-int(size/2): mh+int(size / 2), mw-int(size/2): mw+int(size/2)] = 1
dft_shift = dft_shift * mask
# 将频域从中间移动到左上角
i_dft_shift = np.fft.ifftshift(dft_shift)
i_img = np.fft.ifft2(i_dft_shift)
i_img = np.uint8(np.abs(i_img))
return i_img
import random
import numpy as np
from numpy import array, clip, uint8
from numpy.random import uniform, rayleigh
# 添加高斯噪声
def add_gauss_noise(image, sigma=40):
# 获得r,g,b三个图像通道
r = image[:, :, 0].flatten()
g = image[:, :, 1].flatten()
b = image[:, :, 2].flatten()
# 遍历像素随机生成高斯噪声
# 对每个通道增加噪声
for i in range(image.shape[0] * image.shape[1]):
pr = int(r[i]) + random.gauss(0, sigma)
pg = int(g[i]) + random.gauss(0, sigma)
pb = int(b[i]) + random.gauss(0, sigma)
if pr < 0:
pr = 0
if pr > 255:
pr = 255
if pg < 0:
pg = 0
if pg > 255:
pg = 255
if pb < 0:
pb = 0
if pb > 255:
pb = 255
r[i] = pr
g[i] = pg
b[i] = pb
image[:, :, 0] = r.reshape([image.shape[0], image.shape[1]])
image[:, :, 1] = g.reshape([image.shape[0], image.shape[1]])
image[:, :, 2] = b.reshape([image.shape[0], image.shape[1]])
return image
# 添加椒盐噪声,arg为信噪比(不增加噪声的像素点/总像素点)
def add_salt_noise(image, arg=0.9):
image_ = image.copy()
for h in range(image_.shape[0]):
for w in range(image_.shape[1]):
if np.random.random(1) > arg:
image_[h, w] = np.random.randint(2) * 255
return image_
# 添加伽马噪声,var为方差
def add_gamma_noise(image, var=0.1):
image = array(image/255, dtype=float)
# 2个服从指数分布的噪声叠加
noise = np.random.gamma(2, var ** 0.5, image.shape)
image = image + noise
image = clip(image, 0, 1)
image = uint8(image * 255)
return image
# 添加均匀噪声,high为上界,low为下界
def add_uniform_noise(image, high=1.0, low=0.0):
image = array(image/255, dtype=float)
noise = uniform(low, high, image.shape)
image = image + noise
image = clip(image, 0, 1)
image = uint8(image * 255)
return image
# 添加瑞利噪声, var为方差
def add_rayleigh_noise(image, var=0.1):
image = array(image/255, dtype=float)
noise = rayleigh(var ** 0.5, image.shape)
image = image + noise
image = clip(image, 0, 1)
image = uint8(image * 255)
return image
import math
import cv2
import dlib
import face_recognition
import numpy as np
from PIL import Image
import Detector
def change_size(image, ratio):
h = image.shape[0]
w = image.shape[1]
dh = int(ratio * h)
dw = int(ratio * w)
image = cv2.resize(image, (dw, dh))
return image
# 计算灰度直方图
def get_gray_hist(image):
h, w, c = image.shape
gray_hist = np.zeros(256, np.uint32)
for i in range(h):
for j in range(w):
for k in range(c):
gray_hist[image[i][j][k]] += 1
return gray_hist
# 直方图正规化
def regularize(image):
i_max = np.max(image)
i_min = np.min(image)
o_min, o_max = 0, 255
a = float(o_max - o_min) / (i_max - i_min)
b = o_min - a * i_min
image = a * image + b
image = image.astype(np.uint8)
return image
# 直方图均衡化
def equalize(image):
h, w, c = image.shape
gray_hist = get_gray_hist(image)
cal_gray_hist = np.zeros(256, np.uint32)
cal_gray_hist[0] = gray_hist[0]
for i in range(1, 256):
cal_gray_hist[i] = cal_gray_hist[i-1] + gray_hist[i]
output = np.zeros(256, np.uint8)
param = 256.0 / (h * w)
for i in range(256):
j = param * float(cal_gray_hist[i]) - 1
if j > 0:
output[i] = math.floor(j)
else:
output[i] = 0
equal_hist = np.zeros(image.shape, np.uint8)
for i in range(h):
for j in range(w):
for k in range(c):
equal_hist[i][j][k] = output[image[i][j][k]]
return equal_hist
def remove_background(img, col):
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('data/shape_predictor_68_face_landmarks.dat')
h, w = img.shape[:2]
faces = detector(img, 0)
mask = np.zeros(img.shape[:2], np.uint8)
bg = np.zeros((1, 65), np.float64)
fg = np.zeros((1, 65), np.float64)
if len(faces) > 0:
for k, d in enumerate(faces):
left = max(int((3 * d.left() - d.right()) / 2), 1)
top = max(int((3 * d.top() - d.bottom()) / 2) - 60, 1)
right = min(int((3 * d.right() - d.left()) / 2), w)
bottom = min(int((3 * d.bottom() - d.top()) / 2) + 60, h)
rect = (left, top, right, bottom)
else:
exit(0)
# 函数返回的mask中明显的背景像素为0,明显的前景像素为1,可能的背景像素为2,可能的前景像素为3
cv2.grabCut(img, mask, rect, bg, fg, 10, cv2.GC_INIT_WITH_RECT)
# mask为0或2(即为背景的)设置为0
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
# 背景颜色(蓝/红/白)
bg_color = [(225, 166, 23), (0, 0, 255), (255, 255, 255)]
# 相乘则将背景的像素置为0,留下前景
img = img * mask[:, :, np.newaxis]
# 腐蚀操作
img = cv2.erode(img, None, iterations=1)
# 膨胀操作
img = cv2.dilate(img, None, iterations=1)
for i in range(h): # 高
for j in range(w):
if max(img[i, j]) == 0:
img[i, j] = bg_color[col]
img = img[rect[1]:rect[3], rect[0]:rect[2]]
img = cv2.resize(img, (164, 233))
cv2.imwrite("images/tmp/certificate.png", img)
def paste_pic(img, col):
remove_background(img, col)
img = Image.open("images/tmp/certificate.png")
background = Image.open("images/certificate.png")
background.paste(img, (534, 196))
background.save("result/certificate.png", quality=95)
def face_rec(img, face_characters, face_names):
face_locations = face_recognition.face_locations(img) # 获得所有人的人脸位置
img_characters = face_recognition.face_encodings(img, face_locations) # 获得所有人的人脸特征值
pic_face_names = [] # 记录画面中的所有人名
for img_character in img_characters: # 和数据库人脸进行对比
# 数据集中相似度超过0.5的则为true,否则为false,优先返回高匹配度
tol = 0.05
flag = 0
while tol <= 0.5:
res = face_recognition.compare_faces(face_characters, img_character, tolerance=tol)
# 存在匹配的结果则记录下标
if True in res:
index = res.index(True)
name = face_names[index]
pic_face_names.append(name)
flag = 1
break
tol += 0.02
if flag == 0:
pic_face_names.append("unknown")
# 将捕捉到的人脸显示出来
for (top, right, bottom, left), name in zip(face_locations, pic_face_names):
cv2.rectangle(img, (left, top), (right, bottom), (0, 0, 255), 2) # 画人脸矩形框
# 加上人名标签
cv2.rectangle(img, (left, bottom - 30), (right, bottom), (0, 0, 255), cv2.FILLED)
cv2.putText(img, name, (left + 5, bottom - 5), cv2.FONT_HERSHEY_DUPLEX, 1.0, (255, 255, 255), 1)
# 保存图片并进行实时的显示
h = img.shape[0]
w = img.shape[1]
ratio1 = 500 / h
ratio2 = 800 / w
img = change_size(img, min(ratio1, ratio2))
cv2.imwrite("images/tmp/face_rec.jpg", img)
if len(img_characters) == 0:
return 0
return 1
def mask_rec(img):
img_nose, noses = Detector.nose_detection(img) # 鼻子检测
if noses == 1: # 检测到鼻子说明未戴口罩
cv2.putText(img_nose, "NO MASK", (15, 30), cv2.FONT_HERSHEY_COMPLEX, 0.9, (0, 0, 255), 1) # 图片上写字
cv2.imwrite('images/tmp/mask_rec.jpg', img_nose)
if noses == 0: # 未检测到鼻子则进行眼睛检测
img_eye, eyes = Detector.eye_detection(img) # 进行眼睛检测,返回检测之后的图形以及标志位
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 将图片转化成HSV格式
h, s, v = cv2.split(hsv) #
# h_min = cv2.getTrackbarPos("h_min", 'skin') # 获取bar
# h_max = cv2.getTrackbarPos("h_max", 'skin')
# if h_min > h_max:
# h_max = h_min
thresh = cv2.inRange(h, 0, 15) # 提取人体肤色区域
if len(eyes) > 1: # 判断是否检测到两个眼睛,其中eyes[0]为左眼坐标
# 确定口罩区域
# 左眼的begin为口罩begin
mask_x_begin = min(eyes[0][0], eyes[1][0])
# 右眼begin+右眼宽度为口罩end
mask_x_end = max(eyes[0][0], eyes[1][0]) + \
eyes[list([eyes[0][0], eyes[1][0]]).index(max(list([eyes[0][0], eyes[1][0]])))][2]
# 越界处理
if mask_x_end > img_eye.shape[0]:
mask_x_end = img_eye.shape[0]
# 眼睛高度为口罩begin
mask_y_begin = max(eyes[0][1] + eyes[0][3], eyes[1][1] + eyes[1][3]) + 20
# 越界处理
if mask_y_begin > img_eye.shape[1]:
mask_y_begin = img_eye.shape[1]
mask_y_end = max(eyes[0][1] + 3 * eyes[0][3], eyes[1][1] + 3 * eyes[1][3]) + 20
if mask_y_end > img_eye.shape[1]:
mask_y_end = img_eye.shape[1]
cv2.rectangle(img_eye, (mask_x_begin, mask_y_begin), (mask_x_end, mask_y_end), (255, 0, 0), 2)
mask_scale = 0
face_scale = 0
# 遍历二值图,为0则total_mask_pixel+1,否则total_face_pixel+1
for i in range(mask_x_begin, mask_x_end):
for j in range(mask_y_begin, mask_y_end):
if thresh[i, j] == 0:
mask_scale += 1
else:
face_scale += 1
if mask_scale > face_scale:
cv2.putText(img_eye, "HAVE MASK", (mask_x_begin, mask_y_begin - 10),
cv2.FONT_HERSHEY_COMPLEX, 0.9, (0, 0, 255), 1)
if mask_scale < face_scale:
cv2.putText(img_eye, "NO MASK", (mask_x_begin, mask_y_begin - 10),
cv2.FONT_HERSHEY_COMPLEX, 0.9, (0, 0, 255), 1)
cv2.imwrite("images/tmp/mask_rec.jpg", img_eye)
![](https://file.iviewui.com/cloud-ide/1024game-cover.png)
## 一、大赛介绍
代码开发随着云计算技术的不断发展,云 IDE 能够帮助开发者聚焦业务逻辑,简化应用开发难度,提升软件研发效率。云 IDE 应用挑战赛是由 CSDN 自主策划的轻量级挑战赛事。参赛者可在 CSDN 的云 IDE 上([https://ide.csdn.net](https://ide.csdn.net))自动拉取代码并在线运行、预览、提交代码,赛事所有的事项都可以在云 IDE 内一站式完成。比赛不对作品提交形式作限制,参赛者可以尽情发挥自己的想象力。
## 二、参赛对象
大赛面向全社会开放,个人、高等院校、科研单位、企业等人员均可报名参赛。
说明:如有大赛主办方和技术支持单位(如 CSDN 员工)参赛,则自动放弃获奖资格。
## 三、赛事安排
| 赛程 | 时间 |
| ---- | ---- |
| 参赛报名及提交作品 | 2022.10.23 - 2022.11.06 |
| 作品评选 | 2022.11.07 - 2022.11.14 |
| 评选结果公布 | 2022.11.15 |
| 奖励发放 | 2022.11.16 - 2022.11.22 |
## 四、奖项设置
| 奖项 | 奖品 | 人数 |
| ---- | ---- | ---- |
| 一等奖 | **奖金 ¥5000 元** + 10核 10G 云实验环境会员 -1年| 1 |
| 二等奖 | **奖金 ¥2000 元** + 10核 10G 云实验环境会员 -1年 | 2 |
| 三等奖 | **奖金 ¥1000 元** + 10核 10G 云实验环境会员 -1年 | 5 |
| 优秀奖 | **奖金 ¥100 元** + 10核 10G 云实验环境会员 -1年 | 80 |
| 参与奖 | 10核 10G 云实验环境会员 -1个月 | 前10000名参赛者可得 |
注:一年10核10G云实验环境会员,非云服务器,是云容器实验环境,详细介绍[戳我查看](https://mydev.csdn.net/product/pod/new)
## 五、参赛要求
1. 开发者可根据自己情况选择业界知名开源项目进行自行开发,或自研可开源项目结合GitCode和Cloud IDE进行开发与适配,作品要求必须能通过 CSDN 的云 IDE 内置的预览功能,在云 IDE 内预览。(CSDN 的云IDE:[https://ide.csdn.net](https://ide.csdn.net))。作品可以是任何小应用(如外卖H5、个人主页);小游戏(如 2048、五子棋);各类特效(如 three.js、前端动画)等。
2. 未满 18 周岁的报名者,请在报名前征得有法定监护权的监护人的同意。
3. 参赛作品不存在抄袭等行为。
4. 除参与奖外,获奖人员,领奖时需实名认证,1 个实名认证用户仅可领取1份奖项。
## 六、报名及参赛流程
1. **进入 1024 云 IDE 应用挑战赛页面:[https://gitcode.net/cloud-ide/1024](https://gitcode.net/cloud-ide/1024)****Fork 该项目,即参与比赛**
2. **参赛后,将 Fork 的项目在云 IDE 中打开,并在云IDE中完成您自己的作品,提交代码。**
在云IDE提交代码,有2种操作方法,任选其一即可:
**方法一:**
> (1) 访问 [https://ide.csdn.net](https://ide.csdn.net) ,新建工作空间,仓库地址填写 克隆 的 Git 地址(操作方法:点击”克隆“,复制 ”通过SSH Clone项目“ 的链接)
>
> <img src="https://gitcode.net/cloud-ide/1024/-/raw/main/src/gitcode-ssh.png" width="400px" style="border: 6px solid #fff;border-radius: 2px;">
> <img src="https://file.iviewui.com/cloud-ide/cloud-ide-img-1.png" width="400px" style="border: 6px solid #fff;border-radius: 2px;">
>
> (2)填写 SSH 的 Git 地址,并将云 IDE 提供的 SSH Key (操作方法:[https://dev-ide.csdn.net/doc#git_commit](https://dev-ide.csdn.net/doc#git_commit) )绑定到自己的 GitCode SSH 密钥中 [https://gitcode.net/-/profile/keys](https://gitcode.net/-/profile/keys)
**方法二:**
> (1) 直接在 Fork 的 GitCode 域名前加 ide 进入,例如 https://gitcode.net/xxxxx/1024 修改为 https://idegitcode.net/xxxxx/1024
> <br/>
> <img src="https://file.iviewui.com/cloud-ide/cloud-ide-img-2.png" width="400px" style="border: 6px solid #fff;border-radius: 2px;display:block">
>
> (2) 提交代码时,云 IDE 会让用户输入 CSDN 的账号和密码(即手机号+密码)
**3. 提交代码后,即可等待CSDN官方进行评选。** 2022.11.07 - 2022.11.14为作品评选时间,2022.11.15公布评选结果。
## 七、评选规则
由评选委员会根据获得的 Star、作品复杂程度、易用性、新颖性等多角度评选。
1. Star 占比 20%
a. 获得 Star 的数量,1 颗即为 1 分,最高 20 分封顶
2. 作品复杂程度占比 40%
a. 作品完整度
b. 代码简洁,代码可读性强
c. 架构清晰
d. 作品难度,如使用了一些高级 API,比如 WebGL、Canvas
3. 易用性占比 30%
a. 作品配套的说明,如果项目介绍、如果使用等
b. 交互体验,产品具有较好的交互体验,有足够的易用性
c. 可用,代码能在 CSDN 的云 IDE 上完整运行
4. 新颖性占比 10%
a. 新颖性,使用了较为新颖的技术实现
## 八、领奖规则
1. 获奖名单会在该评选结束后在该页面公布。
2. 工作人员将在活动结束后的7个工作日内,通过CSDN私信联系中奖用户,进行发奖,请您注意消息通知。
## 九、赛事交流
参赛选手官方交流群(仅作为选手之间讨论和交流)。扫码进入选手沟通群。大赛重要节点通知会在群内第一时间告知,请所有报名选手务必加群
<img src="https://file.iviewui.com/asd/cloud-ide/cloud-ide-2.png" width="200px" style="border: 6px solid #fff;border-radius: 2px;">
## 十、其他说明
若出现以下情况,将视为违规,大赛组委会有权取消用户参赛资格及获得的奖项。
1. 参赛报名信息虚假,或不符合大赛报名要求的参赛者。
2. 参赛作品涉嫌抄袭,侵犯他人知识产权等行为。
3. 参赛期间或参赛作品发现或被举报认定存在的其他违法、违规行为。
法律允许范围内的,最终解释权归 CSDN 所有。
<div style="height:200px"></div>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册