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 08 Python
MySQL适配器PyMySQL详解
Sep 20 Python
Python使用tkinter库实现文本显示用户输入功能示例
May 30 Python
numpy的文件存储.npy .npz 文件详解
Jul 09 Python
深入浅析Python获取对象信息的函数type()、isinstance()、dir()
Sep 17 Python
Python面向对象基础入门之设置对象属性
Dec 11 Python
Python3 Tkinter选择路径功能的实现方法
Jun 14 Python
Python使用matplotlib 模块scatter方法画散点图示例
Sep 27 Python
pytorch常见的Tensor类型详解
Jan 15 Python
python同义词替换的实现(jieba分词)
Jan 21 Python
Python itertools.product方法代码实例
Mar 27 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
Nov 17 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解析url的三个示例
2014/01/20 PHP
推荐5款跨平台的PHP编辑器
2014/12/25 PHP
学习php设计模式 php实现装饰器模式(decorator)
2015/12/07 PHP
php+flash+jQuery多图片上传源码分享
2020/07/27 PHP
PHP基于XMLWriter操作xml的方法分析
2017/07/17 PHP
laravel 中如何使用ajax和vue总结
2017/08/16 PHP
PHP memcache在微信公众平台的应用方法示例
2017/09/13 PHP
清空上传控件input file的值
2010/07/03 Javascript
jQuery hover 延时器实现代码
2011/03/12 Javascript
JS调试必备的5个debug技巧
2014/03/07 Javascript
Firefox下无法正常显示年份的解决方法
2014/09/04 Javascript
js防止页面被iframe调用的方法
2014/10/30 Javascript
jQuery的观察者模式详解
2014/12/22 Javascript
DOM事件阶段以及事件捕获与事件冒泡先后执行顺序(图文详解)
2015/08/18 Javascript
JavaScript 是什么意思
2016/09/22 Javascript
浅谈Javascript中的函数、this以及原型
2016/10/09 Javascript
jquery获取input type=text中的值的各种方式(总结)
2016/12/02 Javascript
Vue+Element实现表格编辑、删除、以及新增行的最优方法
2019/05/28 Javascript
JavaScript HTML DOM元素 节点操作汇总
2019/07/29 Javascript
微信小程序使用 vant Dialog组件的正确方式
2020/02/21 Javascript
利用python程序帮大家清理windows垃圾
2017/01/15 Python
对python 命令的-u参数详解
2018/12/03 Python
python下PyGame的下载与安装过程及遇到问题
2019/08/04 Python
python cv2读取rtsp实时码流按时生成连续视频文件方式
2019/12/25 Python
Python使用文件操作实现一个XX信息管理系统的示例
2020/07/02 Python
Bose法国官网:购买耳机、扬声器、家庭影院、专业音响
2017/12/21 全球购物
Exception类的常用方法
2012/06/16 面试题
内刊编辑求职自荐书范文
2014/02/19 职场文书
电话客服专员岗位职责
2014/06/28 职场文书
出纳工作检讨书
2014/10/18 职场文书
医学生自荐信范文(2016精选篇)
2016/01/28 职场文书
某药房的新员工入职告知书!
2019/07/15 职场文书
你会写报告?产品体验报告到底该怎么写?
2019/08/14 职场文书
python tkinter模块的简单使用
2021/04/07 Python
SQL实现LeetCode(180.连续的数字)
2021/08/04 MySQL
2021年国产动漫公司排行前十名,玄机科技上榜,第二推出过铠甲勇士
2022/03/18 杂记