一个大一个小念什么| 苕皮是什么| hpv阳性有什么症状| 蔓越莓是什么| 舂米是什么意思| 梦见冬瓜是什么意思| 玉髓什么颜色最贵| 摊手是什么意思| 无花果和什么煲汤好| 看肾挂什么科| 男性吃什么可以壮阳| 回乡偶书的偶书是什么意思| 上梁不正下梁歪是什么意思| 发烧骨头疼是什么原因| 什么情况下要打破伤风针| 什么时间喝牛奶最佳| 圆是什么生肖| 鼾症是什么病| 爱放屁吃什么药| 沙棘有什么作用| 呆小症是缺乏什么激素| 茯苓是什么味道| 吃什么药能减肥| 红细胞偏高有什么危害| 癞子是什么意思| burberry是什么牌子| 口嫌体正直是什么意思| 蛋白糖是什么糖| qs是什么意思| 八面玲珑什么生肖| 麒麟长什么样| 喝什么茶去湿气| 克服是什么意思| 用盐水洗脸有什么好处和坏处| 女为什么字| 7月22日什么星座| 肝郁血虚吃什么中成药| 甲沟炎是什么样子的| 鱼休子是什么| cj是什么| 无的放矢什么意思| 滑石粉有什么作用| 柠字五行属什么| 腿弯疼是什么原因| 肾上腺挂什么科| 淡菜是什么| 喝什么茶对肝脏好| 牙龈出血吃什么| 缺钾有什么症状和危害| 250为什么是骂人的话| 溥仪什么时候去世的| gpi是什么意思| 荨麻疹是什么原因| 头部mra是什么检查| 区块链是什么| pigeon是什么牌子| 净高是什么意思| 去火吃什么食物| 什么牌子的氨糖最好| 姨妈老是推迟是为什么| 什么是黑色素瘤| 蒙脱石散什么时候吃| 利有攸往是什么意思| 幽门杆菌有什么症状| 孩子白细胞高是什么原因| 3月24日是什么星座| 吃什么可以淡化黄褐斑| 黄油可以用什么代替| 独什么心什么| 染色体xy代表什么| 第一磨牙什么时候换| 什么情况下能吃脑络通| laurel是什么牌子| 吃什么生精养精最快| 女人鼻头有痣代表什么| 血小板低是什么病| 血压和血糖有什么关系| 侧写是什么意思| 有什么好看的美剧| 什么叫姑息治疗| 姐字五行属什么| 同房后小腹疼痛是什么原因| 耳顺是什么意思| 肺部感染有什么症状| 肚子着凉吃什么药| 内心独白什么意思| 什么叫高危性行为| 父亲节出什么生肖| 拉尿有泡泡是什么原因| 房颤用什么药| 小腿浮肿吃什么药| 英文为什么怎么写| 玻尿酸有什么作用| 6月7号是什么星座| 小孩自闭症是什么原因引起的| 什么是辛亥革命| 此贝是什么字| 焦虑症是什么| 血压低吃什么水果最好| 积食是什么意思| 神疲乏力吃什么中成药| 围棋九段是什么水平| 蓝桉什么意思| 急性肠胃炎能吃什么水果| 什么是直径| 婚检男性检查什么| 阴道感染有什么症状| 忽悠什么意思| 小腿浮肿吃什么药最好| 小孩低烧吃什么药| 龙蛇混杂是什么生肖| bf是什么意思| 补办医保卡需要什么资料| 大便黄绿色是什么原因| 什么牌子的燃气灶质量好| 内热是什么原因引起的怎么调理| 白细胞正常c反应蛋白高说明什么| 韩国是什么民族| 梦见自己开车是什么意思| 次第花开是什么意思| 小孩自闭症是什么原因引起的| 真维斯属于什么档次| 眼睛有点模糊是什么原因| 胎盘下缘覆盖宫颈内口是什么意思| 鼻涕由清变黄说明什么| 热锅凉油是什么意思| 本字五行属什么| 精修照片用什么软件| 佛跳墙是什么| 承受是什么意思| 821是什么意思| 一什么饭| smeg什么品牌| 分辨率dpi是什么意思| 食指发麻是什么原因| 孟母三迁告诉我们什么道理| 打鸟是什么意思| 三月二十二是什么星座| 气场是什么意思| 大腿抽筋是什么原因| 为什么吃了避孕药还是怀孕了| 多汗症去医院挂什么科| 梦到生儿子有什么预兆| 8月28号是什么日子| 5.13是什么星座| 至死不渝什么意思| mra是什么意思| 三唑仑是什么| 均码是什么意思| 爱居兔女装是什么档次| 孕期脸上长痘痘是什么原因| 什么叫糖类抗原| 榴莲什么时间段吃最好| 什么治胃胀气| 吃什么药| 乙肝有什么危害| 义乌有什么大学| 属猪的幸运颜色是什么| 佝偻病缺少什么元素| spf50是什么意思| 女性脚冰凉是什么原因| 海口有什么好玩的| 乳腺囊肿和乳腺结节有什么区别| 颈动脉斑块是什么意思| moss是什么意思| 小孩急性肠胃炎吃什么药| 蛆长什么样| 萝莉控是什么意思| 月球是地球的什么星| 山药对人体有什么好处| 苦海翻起爱恨是什么歌| 十年什么婚| 山青读什么| 吃茶叶蛋有什么好处和坏处| 职称有什么用| 糍粑是什么做的| 发情什么意思| 离岸人民币是什么意思| 尿多是什么原因女性| bone什么意思| 噫气是什么意思| 什么是钙化点| 无毛猫叫什么| 前列腺特异性抗原是什么意思| 子宫形态失常是什么意思| 胃疼胃胀用什么药效果最好| pck是什么意思| 功劳叶的别名叫什么| 辟谷是什么意思| kelly是什么意思| 空调一匹是什么意思| 晒伤用什么| 山东有什么特产| 低血压吃什么食物好| 白月光是什么意思| 前列腺素是什么| 刘备是什么样的人| 感恩节是什么时候| 腐竹炒什么好吃| 最小的动物是什么| hpv16阳性有什么症状| 甘油三酯高是什么原因引起的| 胃字出头念什么| 指鼻试验阳性代表什么| 什么是再生纤维面料| 蜈蚣为什么不能打死| 备孕叶酸什么时候吃最好| 保胎针是什么药| 全身大面积湿疹暗示着什么| 节制的意思是什么| 血小板计数偏高是什么原因| 超敏c反应蛋白正常说明什么| 莲子有什么作用| 背靠背什么意思| 心影饱满是什么意思| 女人打掉孩子说明什么| 中元节是什么节日| 反颌是什么意思| 肠系膜多发淋巴结是什么意思| 潘驴邓小闲什么意思| m是什么牌子| 合掌是什么意思| 棺材中禁止放什么东西| 1956年属什么| 猫靠什么散热| 毒瘾为什么那么难戒| 胸部正位片检查什么| 女性黄体期是什么意思| 萘普生是什么药| 五岳是什么意思| 6月22号是什么星座| 纯钛对人体有什么好处| 温碧泉属于什么档次| 水为什么会结冰| 立春是什么生肖| 雀神是什么意思| 颞颌关节紊乱挂什么科| 海鲜有什么| 单于是什么意思| 凉烟都有什么牌子| 这是什么踏板| 胸部周围痒是什么原因| 40不惑是什么意思| 土克水是什么意思| 胃痛胃胀什么原因引起的| 女人左眼角有痣代表什么| 冬虫夏草有什么功效与作用| 豚鼠吃什么食物| 前列腺炎中医叫什么病| 考研复试是什么意思| 子不问卜自惹祸殃什么意思| 女性内分泌失调有什么症状| 什么是公主病| 握手是什么意思| 扁桃体发炎不能吃什么| 火烧火燎是什么意思| 阴湿是什么意思| 释迦摩尼是什么意思| outdoor是什么意思| 肛门痒是什么原因| 斗鱼吃什么食物| 看望病人送什么花合适| 人为什么要喝酒| gap是什么牌子的衣服| 百度
这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 ? 论坛首页 ? 企业专区 ? OpenVINO生态社区 ? 【原创】项目实战—CreditCard数字识别(十二)

共2条 1/1 1 跳转至

【原创】项目实战—CreditCard数字识别(十二)

高工
2025-08-04 19:26:23     打赏
百度 这则标语很雷人,把痰吐窗外就是讲卫生吗(3月23日中国江西网)  寥寥数字反映的是公交车司机维护车内环境卫生的热切诉求,但这样的雷人标语一出,也不免让网友炸了锅。

项目实战—Credit Card 数字识别续

现在我们需要进行第二阶段的工作。

准备工作(opencv

cv2.getStructuringElement()

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))

这个函数的第一个参数表示内核的形状,有三种形状可以选择。

矩形:MORPH_RECT;

交叉形:MORPH_CROSS;

椭圆形:MORPH_ELLIPSE;

第二和第三个参数分别是内核的尺寸以及锚点的位置。一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得

getStructuringElement函数的返回值:
对于锚点的位置,有默认值Point-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。

cv2.resize()

cv2.resize(InputArray src, OutputArray dst, Size, fx, fy, interpolation)

InputArray src 输入图片

OutputArray dst 输出图片 (可省)

Size 输出图片尺寸 w, h)宽和高

fx, fy 沿x轴,y轴的缩放系数 interpolation 插入方式

interpolation 选项所用的5种插值方法:

cv2.INTER_NEAREST 最近邻插值

cv2.INTER_LINEAR 双线性插值(默认设置)

cv2.INTER_AREA 使用像素区域关系进行重采样。

cv2.INTER_CUBIC 4x4像素邻域的双三次插值

cv2.INTER_LANCZOS4 8x8像素邻域的Lanczos插值

cv2.findContours() & cv2.drawContours()

binary, contours, hierarchy = cv2.findContours(src_bi, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

NONE输出所有点,SIMPLE只保留他们的终点。

binary是返回的二值图

contours返回一个listlist中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。

hierarchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数

cv2.drawContours(image, contours, contourIdx, color[, thickness[,
lineType[, hierarchy[, maxLevel[, offset ]]]]])

第一个参数是指明在哪幅图像上绘制轮廓; 第二个参数是轮廓本身,在Python中是一个list

第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1cv2.FILLED),则为填充模式。绘制参数将在以后独立详细介绍。

现在我们即将进行最终的代码实现,具体过程不讲述,代码种有详细注释,一步一步的调试

代码实现

我们将使用实验图片:

                                              image.png

image.png

image.png

image.png

image.png

模板图片:

image.png

来看代码:

ocr_template_match.py

# 导入工具包
from imutils import contours
import numpy as np
import argparse
import cv2
import myutils
 
# 设置参数
# 在pycharm中,Edit Configurations中配置下面参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
ap.add_argument("-t", "--template", required=True, help="path to template OCR-A image")
ar = ap.parse_args()
args = vars(ap.parse_args())  # print(args["image"])
# "第一种方式:"
# args = vars(ap.parse_args())
# args为字典{'image': 'images/credit_card_01.png', 'template': 'images/ocr_a_reference.png'}
# 调用方式:print(args["image"])
# "第二种方式:"
# args = ap.parse_args()
# Namespace(image='images/credit_card_01.png', template='images/ocr_a_reference.png')
# 调用方式:print(args.image)
 
 
# 指定****类型
FIRST_NUMBER = {
      "3": "American Express",
      "4": "Visa",
      "5": "MasterCard",
      "6": "Discover Card"
}
 
 
# 绘图展示
def cv_show(name, img):
      cv2.imshow(name, img)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
 
 
# 读取一个模板图像
img = cv2.imread(args["template"])
cv_show('img', img)
# 灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('ref', ref)
# 二值图像
# ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]  # 法1c
ret, ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)  # 法2, 10值越小,保留的黑越黑,INV后变成白色
# ref要么是0要么是255
# ret返回的是阈值;ref返回的是二值化后的图像矩阵,是二维矩阵。
cv_show('ref', ref)
 
# 计算轮廓
#cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓
 
# ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# ref_二值图, refCnts是边缘轮廓,返回值形状为(10,),表示10个形状,每个里面是一个列表,列表里是具体每一个轮廓的值。
# cv2.RETR_EXTERNAL获取外轮廓, cv2.RETR_TREE获取所有轮廓
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)  # -1表示画出所有轮廓
cv_show('img', img)
print(np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]  # 排序,指定 从左到右 还是 从上到下
# refCnts找到的轮廓不一定就是,从左往右123,现在找到的10个轮廓顺序乱序,需要将轮廓从左往右对应拍成0,1,2..等等
digits = {}
 
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):  # (i, c)加不加括号都是一样的
      # 计算外接矩形并且resize成合适大小
      (x, y, w, h) = cv2.boundingRect(c)
      roi = ref[y:y + h, x:x + w]
      roi = cv2.resize(roi, (57, 88), cv2.INTER_LINEAR)
      cv_show("roi", roi)
      # 每一个数字对应每一个模板
      digits[i] = roi
print(digits)
 
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
# (9, 3)是指的矩阵的宽w和高h, 9是因为想让横向的信息多保留?
# rectKernel为:
# [[1 1 1 1 1 1 1 1 1]
#  [1 1 1 1 1 1 1 1 1]
#  [1 1 1 1 1 1 1 1 1]]
# 形状(3, 9)
 
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
 
# 读取输入图像,预处理
image = cv2.imread(args["image"])
cv_show('image', image)
image = myutils.resize(image, width=300)  # resize前(368, 583, 3),resize后(189, 300, 3)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# cv_show('gray', gray)
cv_show('gray', gray)
 
# gradX = cv2.morphologyEx(tophat, cv2.MORPH_CLOSE, rectKernel)
# # 此处的卷积核为(9, 3),全1
# cv_show('gradX', gradX)  # 此处做闭操作也行
# 闭操作就是把字连接起来
 
# 顶帽操作,突出更明亮的区域;为了突出字体,所以核(9,3)和字体部分差不多比例
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)   # 可以对灰度图进行操作
cv_show('tophat', tophat)
 
# gradX = cv2.morphologyEx(tophat, cv2.MORPH_CLOSE, rectKernel)
# # 此处的卷积核为(9, 3),全1
# cv_show('gradX', gradX)  # 此处做闭操作也行
 
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)  # ksize=-1相当于用3*3的
cv_show('gradX1', gradX)
gradX = np.absolute(gradX)  # 这个是(0,3040)之间的浮点数
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))  # 这个是(0,255)之间的浮点数
gradX = gradX.astype("uint8")
cv_show('gradX', gradX)
 
# 通过闭操作(先膨胀,再腐蚀)将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
# 此处的卷积核为(9, 3),全1
cv_show('gradX', gradX)
 
# THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# cv_show('thresh', thresh)
cv2.imshow('thresh2', thresh)
 
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)  # 再来一个闭操作
cv_show('thresh', thresh)
 
# 计算轮廓
 
thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
      cv2.CHAIN_APPROX_SIMPLE)
 
cnts = threshCnts
cur_img = image.copy()
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
cv_show('img', cur_img)
cv2.imwrite("1.jpg", cur_img)  # 把图片保存下来,然后用画图软件打开查看大小。
locs = []
 
# 遍历轮廓
for (i, c) in enumerate(cnts):
      # 计算矩形
      (x, y, w, h) = cv2.boundingRect(c)
      ar = w / float(h)
      # 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
      if ar > 2.5 and ar < 4.0:
             if (w > 40 and w < 55) and (h > 10 and h < 20):
                    #符合的留下来
                    locs.append((x, y, w, h))
 
# 将符合的轮廓从左到右排序
locs = sorted(locs, key=lambda x: x[0])
output = []
 
# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):
      # initialize the list of group digits
      groupOutput = []
      # 根据坐标提取每一个组
      group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
      cv_show('group', group)
      # 预处理
      group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
      cv_show('group', group)
      # 计算每一组的轮廓
      group_, digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
             cv2.CHAIN_APPROX_SIMPLE)
      digitCnts = contours.sort_contours(digitCnts, method="left-to-right")[0]
 
      # 计算每一组中的每一个数值
      for c in digitCnts:
             # 找到当前数值的轮廓,resize成合适的的大小
             (x, y, w, h) = cv2.boundingRect(c)
             roi = group[y:y + h, x:x + w]
             roi = cv2.resize(roi, (57, 88))
             cv_show('roi', roi)
 
             # 计算匹配得分
             scores = []
 
             # 在模板中计算每一个得分
             for (digit, digitROI) in digits.items():
                    # 模板匹配
                    result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)
                    (_, score, _, _) = cv2.minMaxLoc(result)  # 由于使用的是相关性,所以是去最大值即可
                    # min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
                    # # 返回的res 中min_loc代表每一个滑动窗口左上角坐标的值,min_val代表损失
                    # print(score)
                    scores.append(score)
 
             # 得到最合适的数字
             groupOutput.append(str(np.argmax(scores)))
 
      # 画出来
      cv2.rectangle(image, (gX - 5, gY - 5),
             (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
      cv2.putText(image, "".join(groupOutput), (gX, gY - 15),
             cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
      # cv2.FONT_HERSHEY_SIMPLEX为字体,常用还有cv2.FONT_HERSHEY_COMPLEX
 
      # 得到结果
      print(groupOutput)
      output.extend(groupOutput)
      print(output)
 
# 打印结果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)

myutils.py

import cv2
 
 
def sort_contours(cnts, method="left-to-right"):
    reverse = False
    i = 0
 
    if method == "right-to-left" or method == "bottom-to-top":
        reverse = True
 
    if method == "top-to-bottom" or method == "bottom-to-top":
        i = 1
    boundingBoxes = [cv2.boundingRect(c) for c in cnts]  # 用一个最小的矩形,把找到的形状包起来x,y,h,w
    # print(cv2.boundingRect(cnts[0]))  # (730, 20, 54, 85)
    print(list(zip(cnts, boundingBoxes)))
    print(zip(cnts, boundingBoxes))
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
                                        key=lambda b: b[1][i], reverse=reverse))
 
    return cnts, boundingBoxes
 
 
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

最终效果:

image.png

image.png

image.png

image.png

image.png

可以看到,效果非常不错。

当然了,我们本次所用的数字识别,其本质来讲属于模板匹配,并非真正意义上的数字识别,不过接下来我们将使用更加强大的OCR识别。

 


对计算机视觉感兴趣?这个社区推荐给你~

>>点击了解OpenVINO生态开发社区



工程师
2025-08-04 21:10:46     打赏
2楼

十分感谢您的分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
嗜酸性粒细胞偏高是什么意思 在什么什么后面 一惊一乍是什么意思 大什么什么手 生菜有什么营养价值
游泳是什么运动 武则天墓为什么不敢挖 蝉蜕有什么功效 6.12是什么星座 6月7号什么星座
老年人经常头晕是什么原因造成的 22是什么生肖 人设是什么意思 什么的味道 脚气病缺什么维生素
农历10月24日是什么星座 什么是什么造句 蝙蝠长什么样 上颌窦炎吃什么药 qt是什么
肝功能是什么hcv8jop3ns9r.cn 三保是什么hcv8jop8ns2r.cn 经期吃什么好hcv9jop4ns6r.cn 梦见吃红薯是什么意思hcv8jop3ns3r.cn 可乐煮姜有什么作用chuanglingweilai.com
bebe是什么意思shenchushe.com 大姨妈期间适合吃什么hcv8jop2ns7r.cn 一垒二垒三垒全垒打是什么意思hcv9jop4ns5r.cn 汁字五行属什么dayuxmw.com 男士睾丸疼是什么原因hcv8jop0ns0r.cn
drg什么意思hcv8jop8ns6r.cn 是什么意思啊dayuxmw.com 黄芪和枸杞泡水喝有什么作用hcv8jop7ns1r.cn 鹅蛋和什么不能一起吃hcv8jop6ns0r.cn 刚生完孩子的产妇吃什么水果好tiangongnft.com
腋毛有什么作用hcv7jop7ns3r.cn 什么阻力hcv8jop4ns8r.cn 一月十七是什么星座hcv8jop1ns2r.cn 任性什么意思hcv8jop5ns8r.cn 牙龈出血吃什么chuanglingweilai.com
百度