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 + openpyxl处理excel2007文档思路以及心得
Jul 14 Python
Python备份目录及目录下的全部内容的实现方法
Jun 12 Python
Pyqt实现无边框窗口拖动以及窗口大小改变
Apr 19 Python
详解python Todo清单实战
Nov 01 Python
Python QQBot库的QQ聊天机器人
Jun 19 Python
python提取xml里面的链接源码详解
Oct 15 Python
Python发送手机动态验证码代码实例
Feb 28 Python
Python run()函数和start()函数的比较和差别介绍
May 03 Python
pytorch  网络参数 weight bias 初始化详解
Jun 24 Python
使用Python实现NBA球员数据查询小程序功能
Nov 09 Python
Python基本知识点总结
Apr 07 Python
Python中的 No Module named ***问题及解决
Jul 23 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
一个简单实现多条件查询的例子
2006/10/09 PHP
php使用数组填充下拉列表框的方法
2015/03/31 PHP
PHP图像裁剪缩略裁切类源码及使用方法
2016/01/07 PHP
几款极品的javascript压缩混淆工具
2007/05/16 Javascript
JavaScript 异步方法队列链实现代码分析
2010/06/05 Javascript
jsonp原理及使用
2013/10/28 Javascript
jquery实现带二级菜单的导航示例
2014/04/28 Javascript
JavaScript中的Web worker多线程API研究
2014/12/06 Javascript
jQuery中:button选择器用法实例
2015/01/04 Javascript
JavaScript控制listbox列表框的项目上下移动的方法
2015/03/18 Javascript
JavaScript快速切换繁体中文和简体中文的方法及网站支持简繁体切换的绝招
2016/03/07 Javascript
jQuery中$.each()函数的用法引申实例
2016/05/12 Javascript
js利用clipboardData实现截屏粘贴功能
2016/10/12 Javascript
纯JS代码实现隔行变色鼠标移入高亮
2016/11/23 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
2017/05/01 jQuery
基于casperjs和resemble.js实现一个像素对比服务详解
2018/01/10 Javascript
JavaScript正则表达式函数总结(常用)
2018/02/22 Javascript
Express的HTTP重定向到HTTPS的方法
2018/06/06 Javascript
Vue.Draggable拖拽功能的配置使用方法
2020/07/29 Javascript
vuex actions异步修改状态的实例详解
2019/11/06 Javascript
Vue 解决路由过渡动画抖动问题(实例详解)
2020/01/05 Javascript
vue 调用 RESTful风格接口操作
2020/08/11 Javascript
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
[01:47]2018年度DOTA2最具人气解说-完美盛典
2018/12/16 DOTA
python将字母转化为数字实例方法
2019/10/04 Python
Python迷宫生成和迷宫破解算法实例
2019/12/24 Python
Python 使用office365邮箱的示例
2020/10/29 Python
css3 自定义字体font-face使用介绍
2014/05/14 HTML / CSS
澳大利亚在线奢侈品时尚零售平台:Azura Runway
2021/01/13 全球购物
赔偿协议书范本
2014/04/15 职场文书
关于热爱祖国的演讲稿
2014/05/04 职场文书
常务副县长“四风”个人对照检查材料思想汇报
2014/10/02 职场文书
车辆年检委托书范本
2014/10/14 职场文书
升学宴家长答谢词
2015/09/29 职场文书
python实现大文本文件分割成多个小文件
2021/04/20 Python
科普 | 业余无线电知识-波段篇
2022/02/18 无线电