做有趣的网站,青海专业网站建设推广平台建设,wordpress 后台首页,网站 seo 优化建议任务 信用卡数字识别
穿插之前学的知识点 形态学操作 模板匹配 等
总体流程与方法
1.有一个模板 2 用轮廓检测把模板中数字拿出来 外接矩形#xff08;模板和输入图像的大小要一致
#xff09;3 一系列预处理操作 问题的解决思路
1.分析准备#xff1a;准备模板#…任务 信用卡数字识别
穿插之前学的知识点 形态学操作 模板匹配 等
总体流程与方法
1.有一个模板 2 用轮廓检测把模板中数字拿出来 外接矩形模板和输入图像的大小要一致
3 一系列预处理操作 问题的解决思路
1.分析准备准备模板读取文件——转化为灰度图——转化为二值图——提取轮廓——遍历每一个轮廓 得到每个数字的模板排序大小裁剪为指定大小57*88digits[i] roi
2.处理输入的带数字的银行卡 1预处理 我们需要拿到的是 一组一组的数字 一共四组 读取文件——变换大小——转化为灰度图——形态学操作礼帽操作突出明亮区域——梯度操作计算轮廓信息——闭操作将数字连在一起——二值化操作寻找合适阈值——再来一个闭操作——计算轮廓——遍历轮廓选择合适区域 排除不是数字的轮廓——轮廓排序——遍历轮廓的每一个数字——预处理计算每一组轮廓——计算每一组中的每一个值——匹配得分——得到数字画出来——得到结果——打印结果
#设置参数
ap argparse.ArgumentParser()#编写命令行接口
ap.add_argument(-i, --image, requiredTrue,helppath to input image)#添加命令行参数
ap.add_argument(-t, --template, requiredTrue,helppath to template OCR-A image)
args vars(ap.parse_args())#解析参数 将参数转化为字典的形式 img cv2.imread(args[template])
def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)# waitKey()#是在一个给定的时间内(单位ms)等待用户按键触发 0 无限等待 按任意键继续cv2.destroyAllWindows()
1.cv2.cvtColor颜色空间转换函数 cv2.imread()和cv2.cvtColor() 的使用-CSDN博客
ref cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#颜色空间转换函数
2.cv2.threshold 二值化函数 [OpenCV] cv2.threshold二值化函数使用方法总结_cv2.threshold函数-CSDN博客
ref cv2.threshold(ref, 100, 255, cv2.THRESH_BINARY_INV)[1]#二值化函数3.计算轮廓
refCnts, hierarchy cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#查找轮廓函数 只检测外轮廓 只保留四个点轮廓信息4.画出轮廓
cv2.drawContours(img,refCnts,-1,(0,0,255),3) #画出轮廓函数
5.轮廓排序
refCnts myutils.sort_contours(refCnts, methodleft-to-right)[0] #排序从左到右从上到下6.遍历轮廓
digits {}
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):# 计算外接矩形并且resize成合适大小(x, y, w, h) cv2.boundingRect(c)roi ref[y:y h, x:x w]roi cv2.resize(roi, (57, 88))# 每一个数字对应每一个模板digits[i] roi
2.0初始化卷积核
rectKernel cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
2.1 对要识别的图像进行大小灰度处理
#读取输入图像预处理
image cv2.imread(args[image])
cv_show(image,image)
image myutils.resize(image, width300)
gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show(gray,gray)
2.2 #礼帽操作突出更明亮的区域
#礼帽操作突出更明亮的区域
tophat cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv_show(tophat,tophat)
#
gradX cv2.Sobel(tophat, ddepthcv2.CV_32F, dx1, dy0, #ksize-1相当于用3*3的ksize-1)gradX np.absolute(gradX)
(minVal, maxVal) (np.min(gradX), np.max(gradX))
gradX (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX gradX.astype(uint8)print (np.array(gradX).shape)
cv_show(gradX,gradX)
2.3#通过闭操作先膨胀再腐蚀将数字连在一起
gradX cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show(gradX,gradX)
#THRESH_OTSU会自动寻找合适的阈值适合双峰需把阈值参数设置为0
thresh cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show(thresh,thresh)#再来一个闭操作thresh cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show(thresh,thresh)2.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_show(img,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, keylambda x:x[0])
output []# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):# initialize the list of group digitsgroupOutput []# 根据坐标提取每一个组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)# 计算每一组的轮廓digitCnts,hierarchy cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)digitCnts contours.sort_contours(digitCnts,methodleft-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)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)# 得到结果output.extend(groupOutput)# 打印结果
print(Credit Card Type: {}.format(FIRST_NUMBER[output[0]]))
print(Credit Card #: {}.format(.join(output)))
cv2.imshow(Image, image)
cv2.waitKey(0)
总的代码
# 导入工具包
from imutils import contours
import numpy as np
import argparse
import cv2
import myutils# 设置参数
ap argparse.ArgumentParser()#编写命令行接口
ap.add_argument(-i, --image, requiredTrue,helppath to input image)#添加命令行参数
ap.add_argument(-t, --template, requiredTrue,helppath to template OCR-A image)
args vars(ap.parse_args())#解析参数 将参数转化为字典的形式# 指定信用卡类型
FIRST_NUMBER {3: American Express,4: Visa,5: MasterCard,6: Discover Card
}
# 绘图展示
def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)# waitKey()–是在一个给定的时间内(单位ms)等待用户按键触发 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, 100, 255, cv2.THRESH_BINARY_INV)[1]#二值化函数
cv_show(ref,ref)# 计算轮廓
#cv2.findContours()函数接受的参数为二值图即黑白的不是灰度图,cv2.RETR_EXTERNAL只检测外轮廓cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓refCnts, hierarchy cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#查找轮廓函数 只检测外轮廓 只保留四个点轮廓信息cv2.drawContours(img,refCnts,-1,(0,0,255),3) #画出轮廓函数
cv_show(img,img)
print (np.array(refCnts).shape)
refCnts myutils.sort_contours(refCnts, methodleft-to-right)[0] #排序从左到右从上到下
digits {}
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):# 计算外接矩形并且resize成合适大小(x, y, w, h) cv2.boundingRect(c)roi ref[y:y h, x:x w]roi cv2.resize(roi, (57, 88))# 每一个数字对应每一个模板digits[i] roi# 初始化卷积核
rectKernel cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))#读取输入图像预处理
image cv2.imread(args[image])
cv_show(image,image)
image myutils.resize(image, width300)
gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show(gray,gray)#礼帽操作突出更明亮的区域
tophat cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv_show(tophat,tophat)
#
gradX cv2.Sobel(tophat, ddepthcv2.CV_32F, dx1, dy0, #ksize-1相当于用3*3的ksize-1)gradX np.absolute(gradX)
(minVal, maxVal) (np.min(gradX), np.max(gradX))
gradX (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX gradX.astype(uint8)print (np.array(gradX).shape)
cv_show(gradX,gradX)#通过闭操作先膨胀再腐蚀将数字连在一起
gradX cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show(gradX,gradX)
#THRESH_OTSU会自动寻找合适的阈值适合双峰需把阈值参数设置为0
thresh cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show(thresh,thresh)#再来一个闭操作thresh cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show(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)
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, keylambda x:x[0])
output []# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):# initialize the list of group digitsgroupOutput []# 根据坐标提取每一个组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)# 计算每一组的轮廓digitCnts,hierarchy cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)digitCnts contours.sort_contours(digitCnts,methodleft-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)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)# 得到结果output.extend(groupOutput)# 打印结果
print(Credit Card Type: {}.format(FIRST_NUMBER[output[0]]))
print(Credit Card #: {}.format(.join(output)))
cv2.imshow(Image, image)
cv2.waitKey(0)