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 相关文章推荐
Hadoop中的Python框架的使用指南
Apr 22 Python
利用Python脚本实现ping百度和google的方法
Jan 24 Python
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
Dec 14 Python
详解Python 函数如何重载?
Apr 23 Python
Python3 Tkinter选择路径功能的实现方法
Jun 14 Python
python基于FTP实现文件传输相关功能代码实例
Sep 28 Python
python文件操作的简单方法总结
Nov 07 Python
Python浮点数四舍五入问题的分析与解决方法
Nov 19 Python
Python sqlalchemy时间戳及密码管理实现代码详解
Aug 01 Python
Python descriptor(描述符)的实现
Nov 15 Python
python中if嵌套命令实例讲解
Feb 25 Python
Python爬虫基础之爬虫的分类知识总结
May 13 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
ThinkPHP实现更新数据实例详解(demo)
2016/06/29 PHP
PHP之图片上传类实例代码(加了缩略图)
2016/06/30 PHP
详解Yii2 之 生成 URL 的方法
2017/06/16 PHP
PHP在同一域名下两个不同的项目做独立登录机制详解
2017/09/22 PHP
jquery 经典动画菜单效果代码
2010/01/26 Javascript
jQuery中append、insertBefore、after与insertAfter的简单用法与注意事项
2020/04/04 Javascript
工作需要写的一个js拖拽组件
2011/07/28 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(五)可移动地图的实现
2013/01/23 Javascript
在页面上用action传递参数到后台出现乱码的解决方法
2013/12/31 Javascript
原生js实现移动端瀑布流式代码示例
2015/12/18 Javascript
BootStrap下jQuery自动完成的样式调整
2016/05/30 Javascript
CSS3 media queries结合jQuery实现响应式导航
2016/09/30 Javascript
分享一个精简的vue.js 图片lazyload插件实例
2017/03/13 Javascript
jQuery日期范围选择器附源码下载
2017/05/23 jQuery
vue 运用mock数据的示例代码
2017/11/07 Javascript
js数据类型检测总结
2018/08/05 Javascript
vue实现的仿淘宝购物车功能详解
2019/01/27 Javascript
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
2019/05/18 Javascript
详解js location.href和window.open的几种用法和区别
2019/12/02 Javascript
[46:55]Ti4 冒泡赛第二轮 LGD vs C9
2014/07/14 DOTA
Python操作json数据的一个简单例子
2014/04/17 Python
Python解析excel文件存入sqlite数据库的方法
2016/11/15 Python
速记Python布尔值
2017/11/09 Python
Python爬虫获取整个站点中的所有外部链接代码示例
2017/12/26 Python
Python使用SQLite和Excel操作进行数据分析
2018/01/20 Python
python 画二维、三维点之间的线段实现方法
2019/07/07 Python
Django的models中on_delete参数详解
2019/07/16 Python
python3.8.1+selenium实现登录滑块验证功能
2020/05/22 Python
Python中and和or如何使用
2020/05/28 Python
Python爬虫实例之2021猫眼票房字体加密反爬策略(粗略版)
2021/02/22 Python
HTML5单页面手势滑屏切换原理
2016/03/21 HTML / CSS
澳洲小众品牌的集合网站:BNKR
2018/02/23 全球购物
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的
2015/07/24 面试题
研究生毕业论文导师评语
2014/12/31 职场文书
幼儿园六一主持词
2015/06/30 职场文书
公司人事管理制度
2015/08/05 职场文书