python opencv实现信用卡的数字识别


Posted in Python onJanuary 12, 2020

本项目利用python以及opencv实现信用卡的数字识别

前期准备

  • 导入工具包
  • 定义功能函数

模板图像处理

  • 读取模板图像 cv2.imread(img)
  • 灰度化处理 cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  • 二值化 cv2.threshold()
  • 轮廓 - 轮廓

信用卡图像处理

  • 读取信用卡图像 cv2.imread(img)
  • 灰度化处理 cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  • 礼帽处理 cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
  • Sobel边缘检测 cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
  • 闭操作 cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
  • 计算轮廓 cv2.findContours
  • 模板检测 cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF)

原始数据展示

python opencv实现信用卡的数字识别

python opencv实现信用卡的数字识别

python opencv实现信用卡的数字识别

python opencv实现信用卡的数字识别

python opencv实现信用卡的数字识别

python opencv实现信用卡的数字识别

结果展示

python opencv实现信用卡的数字识别

1 前期准备

# 导入工具包
# opencv读取图片的格式为b g r
# matplotlib图片的格式为 r g b
import numpy as np
import cv2
from imutils import contours
import matplotlib.pyplot as plt
%matplotlib inline
# 信用卡的位置
predict_card = "images/credit_card_01.png"
# 模板的位置
template = "images/ocr_a_reference.png"
# 指定信用卡类型
FIRST_NUMBER = {
  "3": "American Express",
  "4": "Visa",
  "5": "MasterCard",
  "6": "Discover Card"
}
# 定义一些功能函数

# 对框进行排序
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
  (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

# 定义cv2展示函数
def cv_show(name,img):
  cv2.imshow(name,img)
  cv2.waitKey(0)
  cv2.destroyAllWindows()

2 对模板图像进行预处理操作

读取模板图像

# 读取模板图像
img = cv2.imread(template)
cv_show("img",img)
plt.imshow(img)
<matplotlib.image.AxesImage at 0x2b2e04ad128>

python opencv实现信用卡的数字识别

模板图像转灰度图像

# 转灰度图
ref = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show("ref",ref)
plt.imshow(ref)
<matplotlib.image.AxesImage at 0x2b2e25d9e48>

python opencv实现信用卡的数字识别

转为二值图像

ref = cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
cv_show("ref",ref)
plt.imshow(ref)
<matplotlib.image.AxesImage at 0x2b2e2832a90>

python opencv实现信用卡的数字识别

计算轮廓

#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)
plt.imshow(img)
<matplotlib.image.AxesImage at 0x2b2e256f908>

python opencv实现信用卡的数字识别

print(np.array(refCnts).shape)
# 排序,从左到右,从上到下
refCnts = sort_contours(refCnts,method="left-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

(10,)

3 对信用卡进行处理

初始化卷积核

rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

读取信用卡

image = cv2.imread(predict_card)
cv_show("image",image)
plt.imshow(image)
<matplotlib.image.AxesImage at 0x2b2e294c9b0>

python opencv实现信用卡的数字识别

对图像进行预处理操作

# 先对图像进行resize操作
image = resize(image,width=300)
# 灰度化处理
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show("gray",gray)
plt.imshow(gray)
<matplotlib.image.AxesImage at 0x2b2e255d828>

python opencv实现信用卡的数字识别

对图像礼帽操作

  • 礼帽 = 原始输入-开运算结果
  • 开运算:先腐蚀,再膨胀
  • 突出更明亮的区域
tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
cv_show("tophat",tophat)
plt.imshow(tophat)
<matplotlib.image.AxesImage at 0x2b2eb008e48>

python opencv实现信用卡的数字识别

用Sobel算子边缘检测

gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, 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)
plt.imshow(gradX)
(189, 300)
<matplotlib.image.AxesImage at 0x2b2e0797400>

python opencv实现信用卡的数字识别

对图像闭操作

  • 闭操作:先膨胀,再腐蚀
  • 可以将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) 
cv_show("gradX",gradX)
plt.imshow(gradX)
<matplotlib.image.AxesImage at 0x2b2e097cc88>

python opencv实现信用卡的数字识别

#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] 
cv_show("thresh",thresh)
plt.imshow(thresh)
<matplotlib.image.AxesImage at 0x2b2e24a0dd8>

python opencv实现信用卡的数字识别

# 再进行一次闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show("thresh",thresh)
plt.imshow(thresh)
<matplotlib.image.AxesImage at 0x2b2e25fe748>

python opencv实现信用卡的数字识别

计算轮廓

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)
plt.imshow(cur_img)
<matplotlib.image.AxesImage at 0x2b2eb17c780>

python opencv实现信用卡的数字识别

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)

  # 计算每一组的轮廓
  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)
      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)))
cv_show("Image",image)
plt.imshow(image)
Credit Card Type: Visa
Credit Card #: 4000123456789010





<matplotlib.image.AxesImage at 0x2b2eb040748>

python opencv实现信用卡的数字识别

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
解析Python中的变量、引用、拷贝和作用域的问题
Apr 07 Python
Python实现类似jQuery使用中的链式调用的示例
Jun 16 Python
Python实现的用户登录系统功能示例
Feb 05 Python
python如何修改装饰器中参数
Mar 20 Python
使用Python通过win32 COM实现Word文档的写入与保存方法
May 08 Python
python 实现得到当前时间偏移day天后的日期方法
Dec 31 Python
在Python运行时动态查看进程内部信息的方法
Feb 22 Python
Python闭包和装饰器用法实例详解
May 22 Python
Django ImageFiled上传照片并显示的方法
Jul 28 Python
python 利用pywifi模块实现连接网络破解wifi密码实时监控网络
Sep 16 Python
python Polars库的使用简介
Apr 21 Python
Python爬虫入门案例之爬取二手房源数据
Oct 16 Python
Python 实现递归法解决迷宫问题的示例代码
Jan 12 #Python
Python3.x+迅雷x 自动下载高分电影的实现方法
Jan 12 #Python
tensorflow的计算图总结
Jan 12 #Python
python利用JMeter测试Tornado的多线程
Jan 12 #Python
Django 批量插入数据的实现方法
Jan 12 #Python
python处理RSTP视频流过程解析
Jan 11 #Python
pyftplib中文乱码问题解决方案
Jan 11 #Python
You might like
随时给自己贴的图片加文字的php水印
2007/03/16 PHP
php 文件上传类代码
2011/08/06 PHP
如何在PHP中使用正则表达式进行查找替换
2013/06/13 PHP
Laravel5.4简单实现app接口Api Token认证方法
2019/08/29 PHP
用javascript父窗口控制只弹出一个子窗口
2007/04/10 Javascript
Iframe 自适应高度并实时监控高度变化的js代码
2009/10/30 Javascript
Jquery取得iframe下内容的方法
2013/11/18 Javascript
window.location.hash知识汇总
2015/11/09 Javascript
JavaScript实现替换字符串中最后一个字符的方法
2017/03/07 Javascript
深入理解 JavaScript 中的 JSON
2017/04/06 Javascript
jQuery动态移除与增加onclick属性的方法详解
2018/06/07 jQuery
在React项目中使用Eslint代码检查工具及常见问题
2018/10/10 Javascript
vue element中axios下载文件(后端Python)
2019/05/10 Javascript
jQuery中使用validate插件校验表单功能
2019/05/24 jQuery
django js 实现表格动态标序号的实例代码
2019/07/12 Javascript
解决layui的form里的元素进行动态生成,验证失效的问题
2019/09/14 Javascript
微信小程序报错: thirdScriptError的错误问题
2020/06/19 Javascript
[04:26]2014DOTA2国际邀请赛-Newbee顺利进入胜者组决赛 独家专访战神7
2014/07/19 DOTA
Python中使用ConfigParser解析ini配置文件实例
2014/08/30 Python
Python中的filter()函数的用法
2015/04/27 Python
Python可变参数函数用法实例
2015/07/07 Python
对python list 遍历删除的正确方法详解
2018/06/29 Python
Python面向对象程序设计之私有属性及私有方法示例
2019/04/08 Python
使用Django搭建一个基金模拟交易系统教程
2019/11/18 Python
详解python 内存优化
2020/08/17 Python
有关HTML5 Video对象的ontimeupdate事件(Chrome上无效)的问题
2013/07/19 HTML / CSS
美国在线旅行社:Crystal Travel
2018/09/11 全球购物
中药专业大学生医药工作求职信
2013/10/25 职场文书
旅游与酒店管理的自我评价分享
2013/11/03 职场文书
幼儿园春季开学寄语
2014/04/03 职场文书
勾股定理课后反思
2014/04/26 职场文书
小学优秀辅导员事迹材料
2014/05/11 职场文书
护士节策划方案
2014/05/19 职场文书
导游词怎么写
2015/02/04 职场文书
幼儿园教师暑期培训心得体会
2016/01/09 职场文书
2019入党申请书格式
2019/06/25 职场文书