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实现通过pil模块对图片格式进行转换的方法
Mar 24 Python
python根据开头和结尾字符串获取中间字符串的方法
Mar 26 Python
django 使用 request 获取浏览器发送的参数示例代码
Jun 11 Python
python 使用值来排序一个字典的方法
Nov 16 Python
十分钟搞定pandas(入门教程)
Jun 21 Python
python实现生成Word、docx文件的方法分析
Aug 30 Python
pygame实现烟雨蒙蒙下彩虹雨
Nov 11 Python
python目标检测给图画框,bbox画到图上并保存案例
Mar 10 Python
Django静态资源部署404问题解决方案
May 11 Python
python实现AHP算法的方法实例(层次分析法)
Sep 09 Python
python爬虫泛滥的解决方法详解
Nov 25 Python
Python使用pyecharts控件绘制图表
Jun 05 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
php学习 字符串课件
2008/06/15 PHP
php实现微信扫码自动登陆与注册功能
2016/09/22 PHP
windows下的WAMP环境搭建图文教程(推荐)
2017/07/27 PHP
Yii框架视图、视图布局、视图数据块操作示例
2019/10/14 PHP
用 JSON 处理缓存
2007/04/27 Javascript
理解JavaScript中的对象 推荐
2011/01/09 Javascript
JQuery之拖拽插件实现代码
2011/04/14 Javascript
JavaScript中“过于”犀利地for/in循环使用示例
2013/10/22 Javascript
input:checkbox多选框实现单选效果跟radio一样
2014/06/16 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
2015/12/25 Javascript
AngularJs动态加载模块和依赖注入详解
2016/01/11 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
2016/05/12 Javascript
AngularJS ng-app 指令实例详解
2016/07/30 Javascript
微信小程序 基础组件与导航组件详细介绍
2017/02/21 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
2017/03/25 Javascript
谈谈JS中的!!
2017/12/07 Javascript
在Mac下彻底卸载node和npm的方法
2018/05/16 Javascript
js 根据对象数组中的属性进行排序实现代码
2019/09/12 Javascript
node.js实现http服务器与浏览器之间的内容缓存操作示例
2020/02/11 Javascript
RxJS在TypeScript中的简单使用详解
2020/04/13 Javascript
Python代码的打包与发布详解
2014/07/30 Python
python 写入csv乱码问题解决方法
2016/10/23 Python
python人民币小写转大写辅助工具
2018/06/20 Python
详解python metaclass(元类)
2020/08/13 Python
Python实现Excel自动分组合并单元格
2021/02/22 Python
html5视频自动横过来自适应页面且点击播放功能的实现
2020/06/03 HTML / CSS
this关键字的作用
2016/01/30 面试题
设计毕业生简历中的自我评价
2013/10/01 职场文书
人力资源专业推荐信
2013/11/29 职场文书
我的求职计划书
2014/01/10 职场文书
仓库管理制度
2014/01/21 职场文书
双方协议书
2014/04/22 职场文书
甜品店创业计划书
2014/09/21 职场文书
2015年导购员工作总结
2015/04/25 职场文书
李清照的诗词赏析(20首)
2019/08/22 职场文书
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL