任务说明


将银行卡卡号打印输出

实现

、思路
1、定位银行卡卡号数字区域
2、将银行卡每个卡号数字单独提取出来
3、处理模板图片,将每个模板数字单独提取出来
4、通过模板匹配来识别每个卡号

、具体代码实现
1、处理模板
卡号数字模板

# 读取模板图片
img_m = cv2.imread("ocr_a_reference.png",1)
img_m_g = cv2.cvtColor(img_m,cv2.COLOR_BGR2GRAY)
# 反二值化处理,常见的二值图像一般前景为白色,背景为黑色
img_m_g = cv2.threshold(img_m_g,0,255,cv2.THRESH_OTSU|cv2.THRESH_BINARY_INV)[1]
# 查找图像的轮廓
img_m_g_con = cv2.findContours(img_m_g,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0]
img_m_g_dst = cv2.drawContours(img_m.copy(),img_m_g_con,-1,(0,0,255),2)
imshow(img_m_g_dst)


将每个模板数字分割开,并保存到字典中

# 画模板图片的矩形包围盒
l1 = []
for con in img_m_g_con:(x,y,w,h) = cv2.boundingRect(con)l1.append(x)# 将其包围盒按照x坐标排序,这样就得到了按序排列的0~9模板数字图片,
#(因为查找得到的模板是无序的,排序后可以确认每个模板对应的数字)
(img_m_g_con,l1) = zip(*sorted(zip(img_m_g_con,l1),key=lambda x :x[1],reverse=False))
# 将模板数字图像分割开
digits = {}
for i,con in enumerate(img_m_g_con):(x,y,w,h) = cv2.boundingRect(con)roi = img_m_g[y:y+h,x:x+w]
#     (57,88)为调整后的模板图像的大小,也可以设置为其他大小digits[i] = cv2.resize(roi,(57,88))
#     imshow(digits[i])
# 至此,从0到9的模板图像已经保存在了digits中,模板图像就处理完了。

2、处理银行卡图片

# 加载
img_card = cv2.imread("credit_card_01.png",1)
img_card_gray = cv2.cvtColor(img_card,cv2.COLOR_BGR2GRAY)# 顶帽操作,原始图像-开运算图像,作用:提取噪音、高亮的区域。
kernel = np.ones((5,5))
tophat = cv2.morphologyEx(img_card_gray,cv2.MORPH_TOPHAT,kernel)
imshow(tophat)


求图像的梯度(边缘)的目的是方便之后的形态学操作,将目标区域连通在一起。

#求图像梯度
grady =  cv2.Sobel(tophat,ddepth = cv2.CV_32F,dx=0,dy=1,ksize = 3)
# Sobel计算出来的像素值类似为float,需要将其规范到(0~255),并且将其格式转为Uint8
grady = cv2.convertScaleAbs(grady)
# imshow(grady)
gradx = cv2.Sobel(tophat,ddepth = cv2.CV_32F,dx=1,dy=0,ksize=3)
gradx = cv2.convertScaleAbs(gradx)
# imshow(gradx)
# 将X方向的梯度和Y方向的梯度融合。
# 只用单方向梯度也可以达到目的
grad = cv2.addWeighted(gradx,0.5,grady,0.5,0)
imshow(grad)
#使用Canny边缘检测,也可以得到类似的效果


形态学操作,将目标区域连通在一起

# 接下来执行闭操作(先腐蚀后膨胀)一是为了去除一些白色小点噪音,二是将单独的数字给连接成一个小区域
kernel = np.ones((3,3))
grad_close = cv2.morphologyEx(grad,cv2.MORPH_CLOSE,kernel,iterations = 1)
imshow(grad_close)
grad_dst = cv2.threshold(grad_close,0,255,cv2.THRESH_OTSU)[1]
# imshow(grad_dst)
# 注意到第三个区域还没有连通,继续进行闭操作
grad_close = cv2.morphologyEx(grad_dst,cv2.MORPH_CLOSE,kernel,iterations=8)
imshow(grad_close)

闭操作执行的次数和银行卡的格式是严格相关的,不同格式的银行卡要设置不用的参数,参数值通过实验经验获得。
其主要目的是将目标区域联通在一起,并且要求连通后的区域不可以包含额外区域,比如参数设置过大会导致左侧目标区域与下方区域连通,设置过小会导致目标区域无法连通。

# 目标区域已经完全连通,接下来进行轮廓检测,画包围盒,然后再进行筛选
gradcon = cv2.findContours(grad_close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0]
dst = cv2.drawContours(img_card.copy(),gradcon,-1,(0,0,255),2)
imshow(dst)
# 筛选合适的轮廓,筛选参数值是通过经验获取的,可以将各个轮廓的w,h打印后观察。
losc = []
for con in gradcon:(x,y,w,h) = cv2.boundingRect(con)ar = w/h#print(x,y,w,h)if ar >2.4 and ar <3.5: if w>155 or w<85:continue losc.append((x,y,w,h))
# 对矩形包围框按照坐标进行排序,排序目的和前面对模板数字图片的排序目的相同。
sort_losc = sorted(losc,key = lambda x :x[0],reverse=False)
# 排序后的包围盒顺序
# for i in sort_losc:
#     x,y,w,h = i[0],i[1],i[2],i[3]
#     con = np.array([[[x,y],[x+w,y],[x+w,y+h],[x,y+h]]])
#     dst = cv2.drawContours(img_card.copy(),con,-1,(0,0,255),2)
#     imshow(dst)
# 得到了每个目标的包围框,然后把包围框包围的区域截取出一下
img_part = []
for i in sort_losc:x,y,w,h = i[0],i[1],i[2],i[3]con = np.array([[[x,y],[x+w,y],[x+w,y+h],[x,y+h]]])img_part.append(img_card[y:y+h,x:x+w])imshow(img_card[y:y+h,x:x+w])


再对每个小区域处理,获取每个卡号数字区域

# 接下来获取每个数字。
digital = []
def f(img):img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)img_2 = cv2.threshold(img_gray,0,255,cv2.THRESH_OTSU)[1]
#    获取轮廓可以进行先Canny检测,再画轮廓,也可以之前求梯度的方法
#    在这里可以直接进行轮廓查找,因为我们需要查找的是每个数字的轮廓,每个数字都是连通的imgcon = cv2.findContours(img_2,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0]new_con = []#筛选for con in imgcon:(x,y,w,h) = cv2.boundingRect(con) if h>35 or w<15:continuenew_con.append((x,y,w,h))#排序,目的和前面的类似sort_con = sorted(new_con,key = lambda x:x[0]) for i in sort_con:x,y,w,h = i[0],i[1],i[2],i[3]con = np.array([[[x,y],[x+w,y],[x+w,y+h],[x,y+h]]])roi = img_2[y-1:y+h+1,x-1:x+w+1]#注意数字图片区域和模板图片区域要大小要保持一致digital.append(cv2.resize(roi,(57,88)))
for i in img_part:f(i)
# for i in digital:
#     imshow(i)


3、模板匹配

# 接下来进行模板匹配
ans = []
for img_dig in digital:now = []for (dig,digroi) in digits.items():res = cv2.matchTemplate(img_dig,digroi,cv2.TM_CCOEFF_NORMED)now.append(res.item()) ans.append(now.index(max(now)))now.clear()
print(ans)

cv2.matchTemplate是用于模板匹配的函数,第一个参数为待匹配图像,第二个参数为模板图像,模板图像和原图像的大小要保持一致,第三个参数为匹配方式。返回值越大,相似度越高。

存在的问题:
1、不同格式的银行卡图片需要对参数进行幅度较大的改动。
2、没有考虑银行卡图片倾斜的情况,如果输入的银行卡图片在输入的图片中只是倾斜的,可以使用透视变换进行校正,具体做法可以参考上一篇blog(答题卡识别)

opencv项目实践二(银行卡卡号识别)相关推荐

  1. 学习Opencv+Python之银行卡卡号识别

    学习Opencv+Python之银行卡卡号识别 思路: 获取模板轮廓 获取模板中每个数字的轮廓 获取银行卡卡号轮廓 分别提取卡号中的每个数字的轮廓 对比识别 代码: # 导入工具包 from imut ...

  2. opencv项目实践一(答题卡识别)

    答题卡素材图片 思路 读入图片,做一些预处理工作. 进行轮廓检测,然后找到该图片最大的轮廓,就是答题卡部分. 进行透视变换,以去除除答题卡外的多于部分,并且可以对答题卡进行校正. 再次检测轮廓,定位每 ...

  3. python-openCV实现银行卡卡号识别

    实现效果: code import cv2 as cv import numpy as np# 轮廓排序 默认从左到右 # --cnts 待排序的轮廓列表 # --method 排序方法 自上而下,从 ...

  4. 【项目实战二】基于模板匹配和形态学操作的信用卡卡号识别(OpenCV+Python)

    前言:信用卡卡号识别技术的发展有利于提高银行系统的业务水平和办事效率.相信此次通过学习使用OpenCV中的图像处理方法来实现信用卡卡号识别的项目,能让大家清楚地了解图像处理技术的一般方法与步骤以及如何 ...

  5. Python+OpenCV 识别银行卡卡号

    Python+OpenCV 识别银行卡卡号 今天尝试一下用python+OpenCV,使用模板匹配的方式做个简单地识别银行卡卡号(大部分参考网上的,自己改了一部分,代码写的有点不太好,但是思路很清晰, ...

  6. 招商银行信用卡卡号识别项目(第一篇),Python OpenCV 图像处理取经之旅第 53 篇

    Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧.本篇博客是这个系列的第 53 篇. 该系列文章导航参考:https://blog.csdn.net/hihell/categ ...

  7. 基于Python的Opencv 自动识别银行卡卡号系统

    一. 摘要 此应用功能为自动识别并获取银行卡卡号,通过导入需要识别的银行卡图片,以及跟银行卡上卡号的数字相一致的数字模型,则可以成功实现识别并获取银行卡卡号的功能.如果你对此感兴趣的话,下面将会详细介 ...

  8. 银联银行卡卡号java_编写Java程序,使用单例模式,创建可以生成银联借记卡号的工具类...

    编写Java程序,使用单例模式,创建可以生成银联借记卡号的工具类 编写Java程序,使用单例模式,创建可以生成银联借记卡号的工具类,银联借记卡号是一个 19 位的数字,卡号以"62" ...

  9. 前端JS校验银行卡卡号和身份证号码(附ES6版方法)

    1.银行卡卡号校验方法. function luhnCheck(bankno) { var lastNum = bankno.substr(bankno.length - 1, 1); //取出最后一 ...

  10. 银行卡卡号格式规范 每隔4为一个空格

    最近涉及到一个绑定银行卡的需求,需要格式化银行卡卡号.即:每隔4为做一个空格. 一个很简单的功能,大牛请自动忽略... 做个笔记O(∩_∩)O哈! bankCardNoEditTxt.addTextC ...

最新文章

  1. linux内核 机器码,u-boot与Linux内核机器码问题
  2. IPsec在企业网中的应用
  3. linux运维脚本编写,Linux运维常用shell脚本实例 (转)
  4. python中是干嘛的-你都用Python来做什么,它对你来说有什么作用?
  5. 022_html计算机输出标签
  6. windoes硬盘备份(数据迁移)的方法
  7. struts2 的struts.properties配置详解
  8. 简述dijkstra算法原理_Dijkstra算法之 Java详解
  9. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
  10. 5、mysql中的库操作
  11. java容器02--ArrayList源码分析
  12. 潜意识、读懂行为、说服的艺术
  13. L2-002 链表去重(链表+模拟)
  14. 查看dll或exe文件的依赖项——使用vs自带的dumpbin工具
  15. 解决启动CAD时没有响应
  16. 一张思维导图完成淘宝精细化运营
  17. UI基础二:下拉,F4,OP等
  18. 上门洗车APP --- Android客户端开发 之 项目结构介绍,大厂面试必备技能
  19. google jib容器打包工具
  20. gedit文本编辑器的设置

热门文章

  1. 阿里云网盘资源免费分享论坛正式上线
  2. sqli-labs靶场第八关
  3. BZOJ2794 Cloakroom【有限制的背包问题】
  4. curl: (6) Could not resolve host: www.huobi.me; Unknown error
  5. 【EXLIBRIS】墙上的坏人
  6. 开源项目学习之(一)------zheng环境搭建
  7. 机器人理论简介—— 台湾交通大学机器人学公开课(一)
  8. 【数据结构】二叉树经典习题
  9. MaaS出行即服务简单介绍
  10. kinetis FTM 分析笔记