Python开发之基于模板匹配的信用卡数字识别功能


Posted in Python onJanuary 13, 2020

环境介绍

Python 3.6 + OpenCV 3.4.1.15

原理介绍

首先,提取出模板中每一个数字的轮廓,再对信用卡图像进行处理,提取其中的数字部分,将该部分数字与模板进行匹配,即可得到结果。

模板展示

Python开发之基于模板匹配的信用卡数字识别功能

完整代码

# !/usr/bin/env python
# —*— coding: utf-8 —*—
# @Time: 2020/1/11 14:57
# @Author: Martin
# @File: utils.py
# @Software:PyCharm
import cv2


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]
 (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):
 (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
# !/usr/bin/env python
# —*— coding: utf-8 —*—
# @Time: 2020/1/11 14:57
# @Author: Martin
# @File: template_match.py
# @Software:PyCharm
"""
基于模板匹配的信用卡数字识别
"""
import cv2
import utils
import numpy as np

# 指定信用卡类型
FIRST_NUMBER = {
 '3' : 'American Express',
 '4' : 'Visa',
 '5' : 'MasterCard',
 '6' : 'Discover Card'
}


# 绘图显示
def cv_show(name, image):
 cv2.imshow(name, image)
 cv2.waitKey(0)
 cv2.destroyAllWindows()


# 读取模板图像
img = cv2.imread('./images/ocr_a_reference.png')
cv_show('img', img)
# 转化成灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('ref', ref)
# 转化成二值图像
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('ref', ref)
# 计算轮廓
ref_, 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)
print(np.array(refCnts).shape)
# 排序,从左到右,从上到下
refCnts = utils.sort_contours(refCnts, method='left-to-right')[0]
digits = {}
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):
 (x, y , w, h) = cv2.boundingRect(c)
 roi = ref[y:y+h, x:x+w]
 roi = cv2.resize(roi, (57, 88))
 digits[i] = roi
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 读取输入图像,预处理
img_path = input("Input the path and image name: ")
image_input = cv2.imread(img_path)
cv_show('image', image_input)
image_input = utils.resize(image_input, width=300)
gray = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY)
cv_show('gray', gray)
# 礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv_show('tophat', tophat)

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)
# 闭操作
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show('gradX', gradX)
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('thresh', thresh)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
cv_show('thresh', thresh)
# 计算轮廓
thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = threshCnts
cur_img = image_input.copy()
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
cv_show('img', cur_img)
locs = []
# 遍历轮廓
for (i, c) in enumerate(cnts):
 (x, y, w, h) = cv2.boundingRect(c)
 ar = w / float(h)

 if 2.5 < ar < 4.0 and (40 < w < 55) and (10 < h < 20):
 locs.append((x, y, w, h))
# 将符合的轮廓从左到右排序
locs = sorted(locs, key=lambda ix: ix[0])
output = []
# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):
 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_OTSU)[1]
 cv_show('group', group)
 # 计算每一组轮廓
 group_, digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
 digitCnts = utils.sort_contours(digitCnts, method='left-to-right')[0]
 # 计算每一组的每个数值
 for c in digitCnts:
 (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_input, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
 cv2.putText(image_input, "".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)))
cv2.imshow("Image", image_input)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果展示

Python开发之基于模板匹配的信用卡数字识别功能

Credit Card Type: Visa
Credit Card #: 4020340002345678

总结

以上所述是小编给大家介绍的Python开发之基于模板匹配的信用卡数字识别功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python实现bitmap数据结构详解
Feb 17 Python
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
Oct 20 Python
对python3 Serial 串口助手的接收读取数据方法详解
Jun 12 Python
python实现两个文件夹的同步
Aug 29 Python
Python动态导入模块和反射机制详解
Feb 18 Python
python对指定字符串逆序的6种方法(小结)
Apr 02 Python
PyInstaller运行原理及常用操作详解
Jun 13 Python
python如何导出微信公众号文章方法详解
Aug 31 Python
python 列表推导和生成器表达式的使用
Feb 01 Python
python实现web邮箱扫描的示例(附源码)
Mar 30 Python
python 爬取京东指定商品评论并进行情感分析
May 27 Python
单身狗福利?Python爬取某婚恋网征婚数据
Jun 03 Python
python中的itertools的使用详解
Jan 13 #Python
python3读取csv文件任意行列代码实例
Jan 13 #Python
pytorch程序异常后删除占用的显存操作
Jan 13 #Python
Python跑循环时内存泄露的解决方法
Jan 13 #Python
PyTorch使用cpu加载模型运算方式
Jan 13 #Python
Python如何读取文件中图片格式
Jan 13 #Python
详解python破解zip文件密码的方法
Jan 13 #Python
You might like
微信支付开发教程(一)微信支付URL配置
2014/05/28 PHP
gearman中任务的优先级和返回状态实例分析
2020/02/27 PHP
(推荐一个超好的JS函数库)S.Sams Lifexperience ScriptClassLib
2007/04/29 Javascript
JSQL SQLProxy 的 php 版本代码
2010/05/05 Javascript
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
js动画效果制件让图片组成动画代码分享
2014/01/14 Javascript
使用jquery写个更改表格行顺序的小功能
2014/04/29 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
2015/03/30 Javascript
Bootstrap实现响应式导航栏效果
2015/12/28 Javascript
AngularJs页面筛选标签小功能
2016/08/01 Javascript
vue项目优化之通过keep-alive数据缓存的方法
2017/12/11 Javascript
微信网页授权并获取用户信息的方法
2018/07/30 Javascript
Websocket 向指定用户发消息的方法
2020/01/09 Javascript
解析Python编程中的包结构
2015/10/25 Python
Python函数中*args和**kwargs来传递变长参数的用法
2016/01/26 Python
python 自动重连wifi windows的方法
2018/12/18 Python
Python Web版语音合成实例详解
2019/07/16 Python
python实现日志按天分割
2019/07/22 Python
django rest framework vue 实现用户登录详解
2019/07/29 Python
Python 通过微信控制实现app定位发送到个人服务器再转发微信服务器接收位置信息
2019/08/05 Python
Python pickle模块常用方法代码实例
2020/10/10 Python
浅析HTML5 meta viewport参数
2020/10/28 HTML / CSS
高级销售员求职信
2013/10/25 职场文书
阳光体育活动方案
2014/02/16 职场文书
三八节主持词
2014/03/17 职场文书
农民工工资发放承诺书
2014/03/31 职场文书
市场总经理岗位职责
2014/04/11 职场文书
个人投资合作协议书
2014/10/12 职场文书
工作检讨书怎么写
2015/01/23 职场文书
2015年端午节活动策划书
2015/05/05 职场文书
给男朋友的道歉短信
2015/05/12 职场文书
小学生家长意见
2015/06/03 职场文书
实习证明模板
2015/06/16 职场文书
小学音乐课教学反思
2016/02/18 职场文书
解决Navicat for Mysql连接报错1251的问题(连接失败)
2021/05/27 MySQL
springboot读取resources下文件的方式详解
2022/06/21 Java/Android