引言

在现代金融科技应用中,银行卡号的自动识别是一项重要技术。本文将详细介绍如何使用Python和OpenCV库构建一个完整的银行卡号识别系统。该系统能够从银行卡图像中提取卡号信息,并根据卡号首数字判断银行卡类型。

技术栈

  • OpenCV: 计算机视觉库,用于图像处理和特征提取
  • NumPy: 科学计算库,用于数组操作和数值计算
  • argparse: 命令行参数解析库
  • 自定义工具函数: 用于轮廓处理和图像调整

创造函数

这里为了优化主函数的简洁性,我们另写了一个py文件,然后在主函数内导入。

这里写了一个排序函数,是我们对我们在图像中得到的轮廓进行从左到右排。

import cv2def sort_contours(cnts, method="left-to-right"):reverse = Falsei=0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i=1boundingBoxes = [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

还一个resize函数,这个和最初的resize不一样,这个变大变小是等比变化的。

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 imageif 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

系统架构

主要思路:

        先对模板图像(包含数字的图像)进行灰度图处理,二值化。然后找出全部轮廓(这里轮廓是乱序的,我们用我们写的函数,对顺序进行整理),找出轮廓的的外接矩形。然后对轮廓进行裁剪,然后把用字典把图像和对应数字保存下来。

        再对我们要检测的图像进行处理。灰度图,二值化,然后进行图像形态学处理(把我们的数字变的更明显,然后把背景给去除),找出我们的所在位置。然后裁剪出来,然后对每一个图像再进行每一个数字的定位。然后再对比,找出最大值的对应的索引,然后再保存就ok了。

代码详解

1 模板处理

image=cv2.imread(args["template"])
cv_show("image", image)
ref=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show("ref", ref)

先进行二值化处理,不过我们的的图像原本就是二值化的,所以没啥区别

这里进行了一次图像转化,因为轮廓检测对白色检测。原本是黑色的。

ref=cv2.threshold(ref,127,255,cv2.THRESH_BINARY_INV)[1]
cv_show("ref", ref)

refCount,_=cv2.findContours(ref,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image,refCount,-1,(0,255,0),3)
cv_show("ref", image)
refCnts=myfun.sort_contours(refCount,method='left-to-right')[0]

把每个轮廓画出,并进行排序。


digits={}
for (i, cnt) in enumerate(refCnts):(x, y, w, h) = cv2.boundingRect(cnt)roi = ref[y:y+h, x:x+w]roi=cv2.resize(roi,(57,88))cv2.imshow("ROI", roi)digits[i] = roi
print(digits)

然后把每个数字的轮廓找外界矩形,然后保存下来

裁剪成这样,然后再保存下来。

2 图片处理

传入图片进行展示

进行二值化处理

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show("gray", gray)

定义核

rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
squareKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

这里比较大,效果好。

进行顶帽处理

        顶帽操作是原图像与开运算之间的差。开运算是先腐蚀后膨胀,顶帽操作用于突出比周围亮的区域,常用于增强图像中的细小亮细节或去除不均匀光照。如下图,我们用原图减去我们进行开运算的图,就可以看到我们数字的地方消失了,只剩背景了,减去之后就刚好只剩数字了。

tophat=cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
cv_show("tophat", tophat)

进行腐蚀

closeX=cv2.morphologyEx(gray,cv2.MORPH_CLOSE,rectKernel)
cv_show("closeX", closeX)

这样我们的数字就更好选取一点了,然后这里四个一组可以直接选取了,注意这里我们要观察数字的特征,以便于我们对轮廓更好选取。

进行二值处理

thresh=cv2.threshold(closeX,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show("thresh", thresh)

画出轮廓

threshCnts,h=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts=threshCnts
cur_img=img.copy()
cv2.drawContours(cur_img,cnts,-1,(0,255,0),3)

对数字部分排序

cv_show("cur_img", cur_img)
locs=[]
for (i, cnt) in enumerate(cnts):(x, y, w, h) = cv2.boundingRect(cnt)ar=w/float(h)if ar>2.5 and ar<4.0:if (w>40 and h<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):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 = myfun.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(img, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)cv2.putText(img, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)output.extend(groupOutput)  # 得到结果,将一个列表的元素添加到另一个列表的末尾。

结果展示

结论

本文介绍的银行卡号识别系统展示了传统计算机视觉技术在金融科技中的应用。通过合理的图像预处理、特征提取和模板匹配,实现了较高的识别准确率。这种技术不仅适用于银行卡识别,还可推广到其他卡证识别场景,具有广泛的应用前景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/98447.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/98447.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/98447.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

概率论第三讲——多维随机变量及其分布

文章目录考纲n维随机变量及其分布函数联合分布函数边缘分布函数二维离散型随机变量的概率分布、边缘分布和条件分布二维连续型随机变量的概率密度、边缘概率密度和条件概率密度常见的二位分布二维均匀分布二维正态分布随机变量的相互独立性概念相互独立的充要条件相互独立的性质…

纯软件实现电脑屏幕录制/存储到硬盘录像机/onvif模拟器/onvif虚拟监控/绿色版双击开箱即用

一、前言说明 在银行、超市、考试中心、工控系统、网课教学、居家办公等场景中&#xff0c;传统监控摄像头难以清晰录制电脑屏幕内容&#xff0c;导致关键操作无法有效追溯。为解决这一难题&#xff0c;我们推出了一套纯软件实现的电子屏幕监控方案&#xff0c;彻底取代依赖硬…

【算法--链表】86.分割链表--通俗讲解

一、题目是啥?一句话说清 给你一个链表和一个值 x,把链表分成两部分:所有小于 x 的节点都放在大于或等于 x 的节点之前,并且保持节点原来的相对顺序。 示例: 输入:head = [1,4,3,2,5,2], x = 3 输出:[1,2,2,4,3,5](所有小于3的节点1、2、2都在大于等于3的节点4、3、5…

707, 设计链表, LinkedList, 单链表, Dummy Head, C++

目录 题意速览解题思路与设计要点C 代码实现&#xff08;单链表 虚拟头结点&#xff09;时间复杂度与空间复杂度常见坑位与边界用例对比&#xff1a;双链表如何优化单元测试样例&#xff08;可直接粘贴运行&#xff09;总结 题意速览 设计一个支持如下操作的链表&#xff1a…

NAS自建笔记服务leanote2

leanote2(GitHub - wiselike/leanote2: leanote2, 适用于NAS自建的笔记服务) 是一个开源的在线笔记应用程序&#xff0c;继承自原 leanote 项目。向原 leanote 的开发者表示深深的感谢与尊重&#xff0c;正是他们的辛勤付出奠定了这个优秀的笔记平台的基础。 但由于 leanote 项…

模型剪枝----ResNet18剪枝实战

剪枝 模型剪枝&#xff08;Model Pruning&#xff09; 是一种 模型压缩&#xff08;Model Compression&#xff09; 技术&#xff0c;主要思想是&#xff1a; 深度神经网络里有很多 冗余参数&#xff08;对预测结果贡献很小&#xff09;。 通过去掉这些冗余连接/通道/卷积核&am…

K8S-Pod(上)

Pod概念 Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。 Pod是一组&#xff08;一个或多个&#xff09;容器&#xff1b;这些容器共享存储、网络、以及怎样运行这些容器的规约。Pod 中的内容总是并置&#xff08;colocated&#xff09;的并且一同调度&am…

Flink TaskManager日志时间与实际时间有偏差

Flink 启动一个任务后&#xff0c;发现TaskManager上日志时间与实际时间相差约 15 小时。 核心原因可能是&#xff1a; 1、 服务器&#xff08;或容器&#xff09;的系统时间配置错误2、 Flink 日志组件&#xff08;如 Logback/Log4j&#xff09;的时间配置未使用系统默认时区…

Webug3.0通关笔记18 中级进阶第06关 实战练习:DisCuz论坛SQL注入漏洞

目录 一、环境搭建 1、服务启动 2、源码解压 3、构造访问靶场URL 4、靶场安装 5、访问论坛首页 二、代码分析 1、源码分析 2、SQL注入分析 三、渗透实战 &#xff08;1&#xff09;判断是否有SQL注入风险 &#xff08;2&#xff09;查询账号密码 Discuz! 作为国内知…

SWEET:大语言模型的选择性水印

摘要背景与问题大语言模型出色的生成能力引发了伦理与法律层面的担忧&#xff0c;于是通过嵌入水印来检测机器生成文本的方法逐渐发展起来。但现有工作在代码生成任务中无法良好发挥作用&#xff0c;原因在于代码生成任务本身的特性&#xff08;代码有其特定的语法、逻辑结构&a…

FastDFS V6双IP特性及配置

FastDFS V6.0开始支持双IP&#xff0c;tracker server和storage server均支持双IP。V6.0新增特性说明如下&#xff1a;支持双IP&#xff0c;一个内网IP&#xff0c;一个外网IP&#xff0c;可以支持NAT方式的内网和外网两个IP&#xff0c;解决跨机房或混合云部署问题。FastDFS双…

笔记本、平板如何成为电脑拓展屏?向日葵16成为副屏功能一键实现

向日葵16重磅上线&#xff0c;本次更新新增了诸多实用功能&#xff0c;提升远控效率&#xff0c;实现应用融合突破设备边界&#xff0c;同时全面提升远控性能&#xff0c;操作更顺滑、画质更清晰&#xff01;无论远程办公、设计、IT运维、开发还是游戏娱乐&#xff0c;向日葵16…

基于Spring Boot + MyBatis的用户管理系统配置

我来为您详细分析这两个配置文件的功能和含义。 一、文件整体概述 这是一个基于Spring Boot MyBatis的用户管理系统配置&#xff1a; UserMapper.xml&#xff1a;MyBatis的SQL映射文件&#xff0c;定义了用户表的增删改查操作application.yml&#xff1a;Spring Boot的核心配置…

80(HTTP默认端口)和8080端口(备用HTTP端口)区别

文章目录**1. 用途**- **80端口**- **8080端口****2. 默认配置**- **80端口**- **8080端口****3. 联系**- **逻辑端口**&#xff1a;两者都是TCP/IP协议中的逻辑端口&#xff0c;用于标识不同的网络服务。- **可配置性**&#xff1a;端口号可以根据需要修改&#xff08;例如将T…

【开题答辩全过程】以 汽车知名品牌信息管理系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

从全栈工程师视角解析Java与前端技术在电商场景中的应用

从全栈工程师视角解析Java与前端技术在电商场景中的应用 面试背景介绍 面试官&#xff1a;你好&#xff0c;很高兴见到你。我叫李明&#xff0c;是这家电商平台的资深架构师。今天我们会聊聊你的技术能力和项目经验。你可以先简单介绍一下自己吗&#xff1f; 应聘者&#xff1a…

【python】python进阶——多线程

引言在现代软件开发中&#xff0c;程序的执行效率至关重要。无论是处理大量数据、响应用户交互&#xff0c;还是与外部系统通信&#xff0c;常常需要让程序同时执行多个任务。Python作为一门功能强大且易于学习的编程语言&#xff0c;提供了多种并发编程方式&#xff0c;其中多…

【JavaEE】(23) 综合练习--博客系统

一、功能描述 用户登录后&#xff0c;可查看所有人的博客。点击 “查看全文” 可查看该博客完整内容。如果该博客作者是登录用户&#xff0c;可以编辑或删除博客。发表博客的页面同编辑页面。 本练习的博客网站&#xff0c;并没有添加注册功能&#xff0c;以及上传作者头像功能…

MySQL全库检索关键词 - idea 工具 Full-Text Search分享

我们经常要在库中查找一个数据&#xff0c;又不知道在哪个表、哪个字段&#xff1b;或者想找到哪里有在用这个数据。我们可以用&#xff1a;idea 的 Database工具 - Full-Text Search打开idea&#xff0c;在工具栏找到 Database 然后新建自己的连接&#xff0c;然后右键&#x…

银行卡号识别案例

代码实现&#xff1a;import cv2 import numpy as np import argparse import myutils-i moban.png -t card1.pngap argparse.ArgumentParser() ap.add_argument("-i","--image", requiredTrue,help"path to input image") ap.add_argument(&quo…