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 Web框架Flask下网站开发入门实例
Feb 08 Python
Python 探针的实现原理
Apr 23 Python
Linux上安装Python的PIL和Pillow库处理图片的实例教程
Jun 23 Python
浅谈python对象数据的读写权限
Sep 12 Python
Python实现带参数与不带参数的多重继承示例
Jan 30 Python
Python读取数据集并消除数据中的空行方法
Jul 12 Python
浅谈Python在pycharm中的调试(debug)
Nov 29 Python
Python生成一个迭代器的实操方法
Jun 18 Python
Python文件操作函数用法实例详解
Dec 24 Python
python删除某个目录文件夹的方法
May 26 Python
Python趣味实例,实现一个简单的抽奖刮刮卡
Jul 18 Python
浅谈Python中的正则表达式
Jun 28 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 网页过期时间的控制代码
2009/06/29 PHP
PHP异步调用socket实现代码
2012/01/12 PHP
php错误级别的设置方法
2013/06/17 PHP
Yii清理缓存的方法
2016/01/06 PHP
laravel5实现微信第三方登录功能
2018/12/06 PHP
Javascript 继承机制实例
2009/08/12 Javascript
Javascript中获取出错代码所在文件及行数的代码
2010/09/23 Javascript
javascript变量作用域使用中常见错误总结
2013/03/26 Javascript
解析js原生方法创建表格效率测试
2013/07/08 Javascript
随鼠标上下滚动的jquery代码
2013/12/05 Javascript
window.onload追加函数使用示例
2014/03/03 Javascript
javascript发送短信验证码实现代码
2015/11/12 Javascript
详谈JS中实现种子随机数及作用
2016/07/19 Javascript
微信小程序 绘图之饼图实现
2016/10/24 Javascript
node.js中EJS 模板快速入门教程
2017/05/08 Javascript
微信小程序 监听手势滑动切换页面实例详解
2017/06/15 Javascript
node.js博客项目开发手记
2018/03/16 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
2019/01/23 Javascript
微信小程序制作扭蛋机代码实例
2019/09/24 Javascript
vue视频播放插件vue-video-player的具体使用方法
2019/11/08 Javascript
Python性能优化技巧
2015/03/09 Python
Python实现的手机号归属地相关信息查询功能示例
2017/06/08 Python
PyTorch上实现卷积神经网络CNN的方法
2018/04/28 Python
对python中两种列表元素去重函数性能的比较方法
2018/06/29 Python
Numpy数组array和矩阵matrix转换方法
2019/08/05 Python
Python缓存技术实现过程详解
2019/09/25 Python
python 实现二维列表转置
2019/12/02 Python
python文件读取失败怎么处理
2020/06/23 Python
keras.utils.to_categorical和one hot格式解析
2020/07/02 Python
python处理写入数据代码讲解
2020/10/22 Python
CSS3对图片照片进行边缘模糊处理的实现
2018/08/08 HTML / CSS
沙龙级头发造型工具:FOXYBAE
2018/07/01 全球购物
美国波西米亚风格精品店:South Moon Under
2019/10/26 全球购物
毕业生个人求职的自我评价
2013/10/28 职场文书
面试后感谢信
2014/02/01 职场文书
运动会入场解说词
2014/02/07 职场文书