算法设计:

1:识别模板图片各个数字的轮廓:

#读取模板图像
img=cv2.imread('model.png')
#灰度图
ref=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值图像(阈值)
ref=cv2.threshold(ref.copy(), 10, 255, cv2.THRESH_BINARY_INV)[1]
#计算轮廓(仅外部)
contours, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# cv2.findContours()函数接受的参数为二值图
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv_shown('template_Contours',img)
#print (np.array(contours).shape)
contours = sort_contours(contours, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {}
for(i,c)in enumerate(contours):(x,y,w,h)=cv2.boundingRect(c)roi=ref[y:y+h,x:x+w]roi=cv2.resize(roi,(57,88))digits[i]=roicv_shown('img',digits[i])

2 信用卡卡号提取:
1):读取图片并进行礼帽操作

#读取输入图像,预处理
image = cv2.imread('credit_card_01.png')
cv_shown('Input_img',image)
image = resize(image, width=300)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_shown('Input_gray',gray)#礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv_shown('Input_tophat',tophat)

2) 求图像梯度并进行归一化:

gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的ksize=-1)
gradX = np.absolute(gradX) # absolute: 计算绝对值
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))#归一化
gradX = gradX.astype("uint8")

3)进行闭操作使图片轮廓更加清晰

#闭操作
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_shown('Input_CLOSE_gradX',gradX)# THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_shown('Input_thresh',thresh)#闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, rectKernel)
#cv_shown('Input_CLOSE_gradX',gradX)

4) 读取出图片中的所需轮廓

# 计算轮廓
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_shown('Input_Contours',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):groupOutput = []group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5] # 往外扩一点cv_shown('group',group)# 二值化的groupgroup = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]group_name = 'Input_group_' + str(i)cv_shown(group_name,group)

5)在所读取出的轮廓中求所需四个数字的轮廓

# 计算每一组的轮廓 这样就分成4个小轮廓了digitCnts,hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)# 排序digitCnts = sort_contours(digitCnts,method="left-to-right")[0]for c in digitCnts:  z=0(x, y, w, h) = cv2.boundingRect(c) # 外接矩形roi = group[y:y + h, x:x + w]      # 在原图中取出小轮廓覆盖区域,即数字roi = cv2.resize(roi, (57, 88))roi_name = 'roi_'+str(z)# cv_show(roi_name,roi)

6)将获取的数字轮廓与模板匹配

2.imwrite('./credit_card_01/' + group_name + '.jpg',group)scores = [] # 单次循环中,scores存的是一个数值 匹配 10个模板数值的最大得分# 在模板中计算每一个得分# digits的digit正好是数值0,1,...,9;digitROI是每个数值的特征表示for (digit, digitROI) in digits.items():result = cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF)   (_, score, _, _) = cv2.minMaxLoc(result)   # score是最大值scores.append(score) # 10个最大值# 得到最合适的数字groupOutput.append(str(np.argmax(scores)))    # 取最大值z = z+1

总代码如下

import cv2
def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1# 计算外接矩形 boundingBoxes是一个元组boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w# sorted排序(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxes  # 轮廓和boundingBoxess
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 imageif 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
import numpy as np
import argparse
import cv2
# 绘图
def cv_shown(name,image):cv2.imshow(name,image)cv2.waitKey(0)cv2.destroyAllWindows()
# 指定信用卡类型
FIRST_NUMBER = {"3": "American Express","4": "Visa","5": "MasterCard","6": "Discover Card"
}
# 【模板处理流程: 轮廓检测,外接矩形,抠出模板,让模板对应每个数值】
#读取模板图像
img=cv2.imread('model.png')
cv_shown('templte',img)
#灰度图
ref=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值图像(阈值)
ref=cv2.threshold(ref.copy(), 10, 255, cv2.THRESH_BINARY_INV)[1]
#cv_shown('template_bi',ret)
#计算轮廓(仅外部)
contours, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# cv2.findContours()函数接受的参数为二值图
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv_shown('template_Contours',img)
#print (np.array(contours).shape)
contours = sort_contours(contours, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {}
#读取模板图像的各个模块
for(i,c)in enumerate(contours):(x,y,w,h)=cv2.boundingRect(c)roi=ref[y:y+h,x:x+w]roi=cv2.resize(roi,(57,88))digits[i]=roicv_shown('img',digits[i])
#【输入图像处理】
# 形态学操作,礼帽+闭操作可以突出明亮区域,但并不是非得礼帽+闭操作
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
#getStructuringElement函数会返回指定形状和尺寸的结构元素。
#矩形:MORPH_RECT;
#交叉形:MORPH_CROSS;
#椭圆形:MORPH_ELLIPSE;#读取输入图像,预处理
image = cv2.imread('credit_card_01.png')
cv_shown('Input_img',image)
image = resize(image, width=300)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_shown('Input_gray',gray)#礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
#cv_shown('Input_tophat',tophat)
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的ksize=-1)
#cv_shown('sobelx',gradX)gradX = np.absolute(gradX)  # absolute: 计算绝对值
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))#归一化
gradX = gradX.astype("uint8")#print (np.array(gradX).shape)
cv_shown('Input_Sobel_gradX',gradX)#闭操作
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_shown('Input_CLOSE_gradX',gradX)# THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_shown('Input_thresh',thresh)#闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, rectKernel)
#cv_shown('Input_CLOSE_gradX',gradX)# 计算轮廓
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_shown('Input_Contours',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):groupOutput = []group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5] # 往外扩一点cv_shown('group',group)# 二值化的groupgroup = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]group_name = 'Input_group_' + str(i)cv_shown(group_name,group)#cv2.imwrite('./credit_card_01/' + group_name + '.jpg',group)scores = []  # 单次循环中,scores存的是一个数值 匹配 10个模板数值的最大得分# 在模板中计算每一个得分# digits的digit正好是数值0,1,...,9;digitROI是每个数值的特征表示for (digit, digitROI) in digits.items():result = cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF)   (_, score, _, _) = cv2.minMaxLoc(result)   # score是最大值scores.append(score) # 10个最大值# 得到最合适的数字groupOutput.append(str(np.argmax(scores)))    # 取最大值z = z+1# 画出来cv2.rectangle(image, (gX - 5, gY - 5),(gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# putText参数:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细cv2.putText(image, " ".join(groupOutput), (gX, gY - 15),cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 1)# 得到结果output.extend(groupOutput)
# 打印结果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv_shown("Output_image", image)
cv2.waitKey(0)

对于代码中的参数理解

1)cv2.boundingRect: cv2.boundingRect(cnt)这个函数cnt是一个轮廓点集合,也就是它的参数,可以通过cv2.findContours获取;
返回四个值,分别是x,y,w,h;
2)sorted: sorted() 函数对所有可迭代的对象进行排序操作。
-----sorted(iterable, key=None, reverse=False) -----

  • iterable -- 可迭代对象。
  • key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序(也可以通过 key 的值来进行数组/字典的排序)。
  • reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

3)zip: zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
4)cv2.resize:
cv2.resize(InputArray src, OutputArray dst, Size, fx, fy, interpolation)

  • InputArray src 输入图片
  • OutputArray dst 输出图片
  • Size 输出图片尺寸
  • fx, fy 沿x轴,y轴的缩放系数
  • interpolation 插入方式

5)cv2.threshold():
cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst

  • src:表示的是图片源
  • thresh:表示的是阈值(起始值)
  • maxval:表示的是最大值
  • type:表示的是这里划分的时候使用的是什么类型的算法.

6)cv2.findContours:
opencv2返回两个值:contours:hierarchy。
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

  • img:寻找轮廓的图像.
  • mode:轮廓的检索模式,有四种:
    • cv2.RETR_EXTERNAL表示只检测外轮廓
    • cv2.RETR_LIST检测的轮廓不建立等级关系
    • cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
    • cv2.RETR_TREE建立一个等级树结构的轮廓。
  • method:轮廓的近似办法
    • cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
    • cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    • cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
      返回值

cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。

  • contour返回值
    cv2.findContours()函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示
  • hierarchy返回值
    该函数还可返回一个可选的hiararchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。

7)cv2.drawContours()函数:
drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

  • image:在哪幅图像上绘制轮廓;

  • contours:轮廓本身,在Python中是一个list。

  • contourIdx:指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。

  • color为轮廓的颜色,

  • thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,

  • lineType为线型,

  • hierarchy为轮廓结构信息,

  • 第八个参数为maxLevel

8)cv2.getStructuringElement( ):

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

    • 矩形:MORPH_RECT;
    • 交叉形:MORPH_CROSS;
    • 椭圆形:MORPH_ELLIPSE;
  • 第二和第三个参数分别是内核的尺寸以及锚点的位置。一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得

9)cv2.morphologyEx
cv2.morphologyEx(src, op, kernel) 进行各类形态学的变化

  • src传入的图片
  • op进行变化的方式
    • cv2.MORPH_OPEN 开运算(open) ,先腐蚀后膨胀的过程。开运算可以用来消除小黑点,在纤细点处分离物体、平滑较大物体的边界的 同时并不明显改变其面积。
    • cv2.MORPH_CLOSE 闭运算(close),先膨胀后腐蚀的过程。闭运算可以用来排除小黑洞。
    • cv2.MORPH_GRADIENT 形态学梯度(morph-grad),可以突出团块(blob)的边缘,保留物体的边缘轮廓。
    • cv2.MORPH_TOPHAT 顶帽(top-hat),将突出比原轮廓亮的部分。
    • cv2.MORPH_BLACKHAT 黑帽(black-hat),将突出比原轮廓暗的部分
  • kernel表示方框的大小

10)sobel算子:

dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
前四个是必须的参数:

  • 第一个参数是需要处理的图像;
  • 第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
  • dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。

其后是可选的参数:

  • ksize是Sobel算子的大小,必须为1、3、5、7。
  • scale是缩放导数的比例常数,默认情况下没有伸缩系数;
  • delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中

11)归一化: http://webdataanalysis.net/data-analysis-method/data-normalization/
12):cv2.matchTemplate:
cv2.matchTemplate(image, templ, method, result=None, mask=None)

  • mage:待搜索图像
  • templ:模板图像
  • result:匹配结果
  • method:计算匹配程度的方法
    • CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。

    • CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。

    • CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。

    • CV_TM_SQDIFF_NORMED 归一化平方差匹配法

    • CV_TM_CCORR_NORMED 归一化相关匹配法

    • CV_TM_CCOEFF_NORMED 归一化相关系数匹配法

13)cv2.minMaxLoc(src, mask=None):
src是一个矩阵。
函数功能:假设有一个矩阵a,现在需要求这个矩阵的最小值,最大值,并得到最大值,最小值的索引。函数返回的四个值就是上述所要得到的。
14)cv2.rectangle(img,(x1,y1),(x2,y2),(0,255,0),3)

  • img:要作用的图片
  • (x1,y1):矩形框的左上角坐标
  • (x2,y2):矩形框的右下角坐标
  • (0,255,0):矩形框的RGB颜色(绿色)
  • 3:所画线的宽度

15)cv2.putText:
cv2.putText(img,xy,(x1,y1), cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255), thickness=2)

  • img:要作用的图片
  • xy:显示的文本内容(字符串)
  • (x1,y1):文本显示在图片上的位置坐标
  • cv2.FONT_HERSHEY_PLAIN:字体类型
  • 2:字体大小
  • (0,0,255):显示的文本颜色(红色)
  • thickness = 2:字体粗细,数值表示占几个像素

项目实战-信用卡识别相关推荐

  1. android项目实战-人脸识别接口应用

    android项目实战-人脸识别接口应用 1.face++接口: 2.源码: 3.效果: 4.App下载: 5.代码解读: FaceUtils.java FaceAdapter.java ImageR ...

  2. Opencv项目实战-信用卡数字识别

    Opencv项目实战:信用卡数字识别 导入库,定义展示函数 import cv2 import numpy as np from imutils import contours import myut ...

  3. AttributeError: module ‘myutils‘ has no attribute ‘sort_contours‘,项目实战-信用卡数字识别--pychram如何配置相应的参数

    1,打开pycharm软件 2,新建一个.py文件(注意:不要出现中文名) 3,配置: (1)点击file (2)点击 settings- (3)点击 4,配置参数 右键点击自己新建的python文件 ...

  4. python之逻辑回归项目实战——信用卡欺诈检测

    信用卡欺诈检测 1.项目介绍 2.项目背景 3.分析项目 4.数据读取与分析 4.1 加载数据 4.2 查看数据的标签分布 5.数据预处理 5.1 特征标准化 5.2. 使用下采样解决样本数据不均衡 ...

  5. 机器学习项目实战----信用卡欺诈检测

    一.任务基础 数据集包含由欧洲人于2013年9月使用信用卡进行交易的数据.此数据集显示两天内发生的交易,其中284807笔交易中有492笔被盗刷.数据集非常不平衡,正例(被盗刷)占所有交易的0.172 ...

  6. 机器学习项目实战----信用卡欺诈检测(一)

    一.任务基础 数据集包含由欧洲人于2013年9月使用信用卡进行交易的数据.此数据集显示两天内发生的交易,其中284807笔交易中有492笔被盗刷.数据集非常不平衡,正例(被盗刷)占所有交易的0.172 ...

  7. opencv项目实战信用卡的检测

    第一步先梳理一下我们的项目逻辑: 一. 找素材 (数字模板,银行卡照片等) 二. 识别数字则需要我们对数字模板进行处理.因此下面我们开始处理数字模板. 1.将数字模板处理成灰度图,再进行二值处理.这样 ...

  8. 机器学习项目实战----信用卡欺诈检测(二)

    六.混淆矩阵: 混淆矩阵是由一个坐标系组成的,有x轴以及y轴,在x轴里面有0和1,在y轴里面有0和1.x轴表达的是预测的值,y轴表达的是真实的值.可以对比真实值与预测值之间的差异,可以计算当前模型衡量 ...

  9. 【项目实战课】基于Pytorch的3DCNN视频分类与行为识别实战

    欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的3DCNN视频分类与行为识别实战>. 所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代 ...

最新文章

  1. 正则数字和小数点_Python中的正则表达式【不断补充~】
  2. iOS 滚动图滚动到顶部汇总
  3. 【分析】2014移动互联网数据报告(终极版必收!)
  4. mysql里面integer默认宽度_MySQL中关于数据类型指定宽度之后的情况
  5. 数据类型,运算符和表达式02 - 零基础入门学习C语言03
  6. BigDecimal 往左移动两位小数_一课研究之“让问题意识成为学生深度学习的钥匙——除数是整数的小数除法例谈”20190830...
  7. Codechef Yet another cute girl
  8. ji计算机一级题库,全国计算机等级考试一级题库0l0ji.doc
  9. Duplicated Numbers (10分)
  10. 最后一战 源代码_我们的故事 | 一枚“铁渣”的一战成名
  11. C++ STL容器之string--常用接口
  12. react的单文件编写方式
  13. 一次Pmbus 调试经验
  14. w3cschool实战答案
  15. OPPO手机刷机解锁救砖解账户锁方法
  16. Shiro笔记 教程
  17. 大话设计模式之爱你一万年:第十四章 行为模式:命令模式:烧烤天天吃:1.命令模式之烧烤店
  18. 抓包安卓7以上ca证书安装方法
  19. 白小小的可爱伤感空间日志发布:有些人,注定只是过客
  20. 6款经典BI项目报表表单风格配色方案

热门文章

  1. python可以这样学豆瓣_豆瓣程序员如何利用Python开发出这么成功的社区?
  2. python翻译器怎么用_Python使用百度翻译开发平台实现英文翻译为中文功能示例
  3. Python操作系统
  4. 苹果8防水吗_苹果发布真无线耳机Powerbeats Pro,多彩配色,H1芯片加持
  5. 题目:类Test1、类Test2定义如下:
  6. 农业气象站在农业气象监测系统领域的应用
  7. 2021年第十二届蓝桥杯省赛B组C/C++部分填空题解
  8. 蓝桥杯2021年省赛:卡片(填空)
  9. 浦发银行 计算机 笔试题,浦发银行笔试经验2017
  10. 2008-05-12 日志:佛祖诞生,惊天动地