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使用爬虫猜密码
Feb 19 Python
Python中的数学运算操作符使用进阶
Jun 20 Python
详解Python中最难理解的点-装饰器
Apr 03 Python
浅析使用Python操作文件
Jul 31 Python
详解Python 协程的详细用法使用和例子
Jun 15 Python
tensorflow saver 保存和恢复指定 tensor的实例讲解
Jul 26 Python
PyQt4实时显示文本内容GUI的示例
Jun 14 Python
Python搭建代理IP池实现接口设置与整体调度
Oct 27 Python
python 实现兔子生兔子示例
Nov 21 Python
Python return语句如何实现结果返回调用
Oct 15 Python
Python爬虫后获取重定向url的两种方法
Jan 19 Python
使用opencv-python如何打开USB或者笔记本前置摄像头
Jun 21 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 str_replace的替换漏洞
2008/03/15 PHP
PHP中Date获取时间不正确怎么办
2008/06/05 PHP
PHP 飞信好友免费短信API接口开源版
2010/07/22 PHP
解析php中反射的应用
2013/06/18 PHP
一个PHP针对数字的加密解密类
2014/03/20 PHP
PHP实现抓取迅雷VIP账号的方法
2015/07/30 PHP
WordPress开发中的get_post_custom()函数使用解析
2016/01/04 PHP
使用 JScript 创建 .exe 或 .dll 文件的方法
2011/07/13 Javascript
jquery在IE、FF浏览器的差别详细探讨
2013/04/28 Javascript
JavaScript 数组详解
2013/10/10 Javascript
jQuery的:parent选择器定义和用法
2014/07/01 Javascript
Angular2中Bootstrap界面库ng-bootstrap详解
2016/10/18 Javascript
JavaScript仿百度图片浏览效果
2016/11/23 Javascript
AngularJS指令中的绑定策略实例分析
2016/12/14 Javascript
详解JavaScript按概率随机生成事件
2017/08/02 Javascript
bootstrap table实现双击可编辑、添加、删除行功能
2017/09/27 Javascript
vue父组件向子组件(props)传递数据的方法
2018/01/02 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
React Native悬浮按钮组件的示例代码
2018/04/05 Javascript
简单的Python的curses库使用教程
2015/04/11 Python
教你使用python画一朵花送女朋友
2018/03/29 Python
Windows下python3.7安装教程
2018/07/31 Python
Python3实现爬取简书首页文章标题和文章链接的方法【测试可用】
2018/12/11 Python
Python Flask 搭建微信小程序后台详解
2019/05/06 Python
python2.7实现复制大量文件及文件夹资料
2019/08/31 Python
python环境下安装opencv库的方法
2020/03/05 Python
python 给图像添加透明度(alpha通道)
2020/04/09 Python
matplotlib对象拾取事件处理的实现
2021/01/14 Python
CSS3之背景尺寸Background-size使用介绍
2013/10/14 HTML / CSS
HTML5 Canvas中使用路径描画二阶、三阶贝塞尔曲线
2015/01/01 HTML / CSS
html5页面结构_动力节点Java学院整理
2017/07/10 HTML / CSS
促销活动总结报告
2014/04/26 职场文书
戒毒悔改检讨书
2014/09/21 职场文书
2016年“七一建党节”广播稿
2015/12/18 职场文书
oracle表分区的概念及操作
2021/04/24 Oracle
「海贼王」112.9万粉丝纪念图标公布
2022/03/21 日漫