当前位置: 首页 > news >正文

基于opencv-python模板匹配的银行卡号识别(附源码)

目录

介绍

数字模板处理

银行卡图片处理 

导入数字模板

模板匹配及结果


介绍

我们有若干个银行卡图片和一个数字模板图片,如下图

我们的目的就是通过对银行卡图片进行一系列图像操作使得我们可以用这个数字模板检测出银行卡号。

数字模板处理

首先我们先对数字模板进行处理,处理的目的是将数字模板中的每个数字分割开来。

先导入需要用到的包

import cv2
import os
import numpy as np
import matplotlib.pyplot as plt

然后再定义一个修改图片尺寸的函数

#修改尺寸
def img_resize(img, hight):(h, w) = img.shape[0], img.shape[1]r = h / hightwidth = w / rimg = cv2.resize(img, (int(width), int(hight)))    return img

接下来,我们读入数字模板图片并对其进行灰度化,二值化和轮廓检测

#读入总模板
img = cv2.imread('images/ocr_a_reference.png')
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ref,thresh= cv2.threshold(ref, 127, 255, cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

由于模板比较简单,故用这些操作即可分割出来数字模板中的每个数字,我们可以看一下操作完后的结果

for i in range(len(contours)):x, y, w, h = cv2.boundingRect(contours[i])plt.subplot(3, 4, i + 1)plt.imshow(thresh[y:y + h, x:x + w], cmap=plt.cm.gray)plt.xticks([])plt.yticks([])plt.show()

接下来,我们将各个模板保存起来,以便于后期读取使用

#保存模板
if not os.path.exists('data'):os.mkdir('data')for i in range(len(contours)):x, y, w, h = cv2.boundingRect(contours[i])cv2.imwrite(os.path.join('data', str(9-i)+'.jpg'), thresh[y:y+h, x:x+w])

保存完后会生成一个data文件夹,可以看到每个数字都已经单独分割保存为单张图片了

到这里,数字模板处理就完成了

银行卡图片处理 

我们是要基于模板匹配去识别具体的银行卡号,而且我们在上述操作中已经得到了每个数字的模板,所以我们现在只需要从银行卡里面切割处理每个银行卡号,就可以进行模板匹配,那么怎么切割出银行卡里的每个号码呢,这里小编尝试过直接用图像处理技术进行单个切割,但发现效果并不好。此时我们发现银行卡号共有16位,其中每4位离的都比较近,那我们可不可以先画出整体四个,然后再对四个进行单独切割呢,显然,这样做的效果是比较好的。

 我们首先读入银行卡图片并修改尺寸和做灰度化处理

#灰度化
img = cv2.imread('images/credit_card_01.png')
img = img_resize(img, 200)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(gray, cmap=plt.cm.gray)

 然后对灰度图进行礼貌操作,用来突出银行卡中的数字

#礼貌操作
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 5))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
plt.imshow(tophat, cmap=plt.cm.gray)

然后利用sobel算子增强图片的边缘信息,即增强数字信息

#sobel边缘检测
sobel = cv2.Sobel(tophat, cv2.CV_64F,dx=1, dy=0, ksize=3)
sobel = cv2.convertScaleAbs(sobel)
minval, maxval = np.min(sobel), np.max(sobel)
sobel = (255 * ((sobel - minval) / (maxval - minval)))
sobex = sobel.astype('uint8')
plt.imshow(sobex, cmap=plt.cm.gray)

 再对图像进行膨胀和腐蚀的操作,使得每四个数字连接在一起

#膨胀腐蚀
dilate = cv2.dilate(sobel, rectKernel, 10)
erosion = cv2.erode(dilate, rectKernel, 10)
plt.imshow(erosion, cmap=plt.cm.gray)

此时发现图像上有些噪声,所以我们对图像进行二值化操作,以去除这些白点

#二值化
erosion = cv2.convertScaleAbs(erosion)
ret, thresh = cv2.threshold(erosion, 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
plt.imshow(thresh, cmap=plt.cm.gray)

 

进行完二值化操作后,再进行一次膨胀腐蚀操作,加深数字区域信息

#膨胀腐蚀
dilate = cv2.dilate(thresh, sqKernel, 10)
erosion = cv2.erode(dilate, sqKernel, 10)
plt.imshow(dilate, cmap=plt.cm.gray)

现在效果就比较好了,我们就可以在此图像上画轮廓了

#画轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cur_img = img.copy()
cur_img = cv2.cvtColor(cur_img, cv2.COLOR_BGR2RGB)
cv2.drawContours(cur_img,contours,-1,(0,0,255),3)
plt.imshow(cur_img)

 

但是我们发现,这个轮廓不仅廓住了数字区域,还廓住了其他区域,此时我们将数字区域轮廓过滤出来,并画出来数字区域显示一下(数字是棕色的是因为此时显示的BGR图像)

#过滤轮廓
locs = []
for(i,c) in enumerate(contours):(x,y,w,h) = cv2.boundingRect(c)ar = w/float(h)if ar>2.5 and ar<4.0:if(w>40 and w<60) and (h>10 and h<20):locs.append((x,y,w,h))
print(len(locs))for i in range(len(locs)):x,y,w,h = locs[3-i]contour = img[y:y+h, x:x+w,:]plt.subplot(2, 2, i+1)plt.imshow(contour)plt.xticks([])plt.yticks([])plt.show()

 

此时没有银行卡上其他信息的干扰,我们可以很简单的使用灰度化,二值化和轮廓检测来廓住每个单独的数字

#进行最后的处理
results = []
for i in range(len(locs)):x,y,w,h = locs[3-i]img_new = img[y:y+h, x:x+w,:]gray = cv2.cvtColor(img_new, cv2.COLOR_BGR2GRAY)ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)res = img_new.copy()for j in range(len(contours)):x, y, w, h = cv2.boundingRect(contours[3-j])res = cv2.rectangle(res, (x, y), (x+w, y+h), (255, 0, 0), 1)results.append(thresh[y:y+h, x:x+w])plt.subplot(2, 2, i+1)plt.imshow(res, cmap=plt.cm.gray)plt.xticks([])plt.yticks([])plt.show()

最后我们就可以得到银行卡中的每个单独号码

#可以看一下results
for i in range(16):results[i] = cv2.resize(results[i], (10, 15))plt.subplot(2, 8, i+1)plt.imshow(results[i], cmap=plt.cm.gray)plt.xticks([])plt.yticks([])plt.show()

 

导入数字模板

在处理完银行卡后,我们导入我们一开始获得的数字模板,进行最后的模板匹配

#引入模板
digits = {}
for i in range(10):digits[i] = cv2.resize(cv2.imread('data/{}.jpg'.format(i)), (10, 15))digits[i] = cv2.cvtColor(digits[i], cv2.COLOR_BGR2GRAY)ref, digits[i] = cv2.threshold(digits[i], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)for i in range(10):plt.subplot(2, 5, i+1)plt.imshow(digits[i], cmap=plt.cm.gray)plt.xticks([])plt.yticks([])plt.show()

模板匹配及结果

导入数字模板后,就可以进行模板匹配得到结果了

#模板匹配得出结果
res = ''
for i in results:scores = []for j in range(10):result = cv2.matchTemplate(i, digits[j], cv2.TM_CCOEFF)  # result为一个输出矩阵(_, score, _, _) = cv2.minMaxLoc(result)  # 这个方法会返回最小值,最大值,最小值位置和最大值位置scores.append(score)res = res + str(np.argmax(scores))
print(res)plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show

我们也可以看一下其他银行卡的匹配结果 

 

其中有一张银行卡号的识别好像因为环境等因素出了点问题,其他的识别都是没问题的,大体来说结果还算可以

源码及文件请查看:https://github.com/jvyou/Bank-card-number-identification

效果演示请查看:https://www.bilibili.com/video/BV1hK421C7Bk/?spm_id_from=333.999.0.0&vd_source=ea64b940c4e46744da2aa737dca8e183

相关文章:

基于opencv-python模板匹配的银行卡号识别(附源码)

目录 介绍 数字模板处理 银行卡图片处理 导入数字模板 模板匹配及结果 介绍 我们有若干个银行卡图片和一个数字模板图片&#xff0c;如下图 我们的目的就是通过对银行卡图片进行一系列图像操作使得我们可以用这个数字模板检测出银行卡号。 数字模板处理 首先我们先对数…...

JAVA设计模式之建造者模式详解

建造者模式 1 建造者模式介绍 建造者模式 (builder pattern), 也被称为生成器模式 , 是一种创建型设计模式. 定义: 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 **建造者模式要解决的问题 ** 建造者模式可以将部件和其组装过程分开…...

ElasticSearch查询语句用法

查询用法包括&#xff1a;match、match_phrase、multi_match、query_string、term 1.match 1.1 不同字段权重 如果需要为不同字段设置不同权重&#xff0c;可以考虑使用bool查询的should子句来组合多个match查询&#xff0c;并为每个match查询设置不同的权重 {"query&…...

美国服务器如何

美国服务器在被选择名单里排名很高&#xff0c;那么美国服务器如何&#xff0c;美国服务器 适用于哪些场景&#xff0c;认可度高吗?接下来小编为您整理发布美国服务器如何的详细情况。 美国服务器通常以其高性能、高可靠性和安全性而受到认可&#xff0c;它们适用于多种业务场…...

远程主机可能不符合glibc和libstdc++ VS Code服务器的先决条件

报错信息 VSCode无法连接远程服务器&#xff0c;终端一直提醒&#xff1a; [22:46:01.906] > Waiting for server log... [22:46:01.936] > Waiting for server log... [22:46:01.951] > [22:46:01.967] > Waiting for server log... [22:46:01.982] > [22:…...

【python基础】sys.argv[]的使用方法

文章目录 前言一、sys.argv是什么&#xff1f;二、实例 前言 本文主要讲解sys.argv[]的使用方法。 一、sys.argv是什么&#xff1f; sys.arg[]的作用就是存储在运行python脚本时候从外部往被运行的py文件里面传递的参数&#xff0c;是一个列表对象。利用好这个属性可以极大的增…...

Element-Ui el-date-picker日期传值异常问题解决办法

首先&#xff0c;只要非常简单的组件引入写法&#xff1a; 然后myDate在data()中是字符串类型 myDate: ‘’ 然后增加一个方法在提交表单到后台的时候&#xff0c;用来转化日期对应到myDate成字符串类型&#xff0c;并且对应到java类 function checkType(value) {if (typeo…...

GO语言集成开发 JetBrains GoLand 2023 中文

JetBrains GoLand 2023是一款专为Go语言开发者打造的集成开发环境&#xff08;IDE&#xff09;。它基于IntelliJ IDEA平台&#xff0c;提供了丰富的功能和工具&#xff0c;旨在提高开发效率和质量。GoLand 2023具备强大的Go语言支持&#xff0c;包括语法高亮、自动补全、代码提…...

详细关于如何解决mfc140.dll丢失的步骤,有效修复mfc140.dll文件丢失的问题。

mfc140.dll文件是Microsoft Visual Studio 2015程序集之一&#xff0c;它包含用于支持多种功能的代码和库。当这个mfc140.dll文件丢失时&#xff0c;可能会导致相关程序运行出错甚至无法运行。很多用户可能会遇到mfc140.dll丢失的问题&#xff0c;但是这并不是不可解决的困难。…...

聚簇索引、非聚簇索引、回表、索引下推、覆盖索引

聚簇索引&#xff08;主键索引&#xff09; 非叶子节点上存储的是索引值&#xff0c;叶子节点上存储的是整行记录。 非聚簇索引&#xff08;非主键索引、二级索引&#xff09; 非叶子节点上存储的都是索引值&#xff0c;叶子节点上存储的是主键的值。非聚簇索引需要回表&…...

ES实战-book笔记1

#索引一个文档,-XPUT手动创建索引, curl -XPUT localhost:9200/get-together/_doc/1?pretty -H Content-Type: application/json -d {"name": "Elasticsearch Denver","organizer": "Lee" } #返回结果 {"_index" : "g…...

高防服务器出租的优势及特点

高防服务器出租是指租用具备高防御能力的服务器&#xff0c;用于应对网络攻击、保护网站和数据安全。那么为什么会选择高防服务器出租&#xff0c;小编为您整理发布高防服务器出租的优势及特点。 高防服务器通常具备以下特点&#xff1a; 1. 高性能硬件配置&#xff1a;高防服务…...

NTLM||LM算法lsasswinlogon进程

来填坑了&#xff0c;这篇blog我们就来讲一下mimikatz能抓到开机的密码的原理 1.lsass&&winlogon 不知道大家有没有好奇过&#xff0c;我们每次开机输入密码之后&#xff0c;电脑又怎么知道我们是否输入正确呢&#xff1f; &#xff1a;这就要的得益于我们的两个进程…...

transformer剪枝论文汇总

文章目录 NN Pruning摘要实验 大模型剪枝LLM-PrunerSparseGPT LTPVTPWidth & Depth PruningPatch SlimmingDynamicViTSPViTDynamicBERTViT SlimmingFastFormersNViTUVCPost-training pruning NN Pruning 《Block Pruning For Faster Transformers》 《为更快的transformer…...

使用 Ant Design 的 Upload 组件实现图片

文章目录 使用 Ant Design 的 Upload 组件实现图片Upload组件itemRender自定义上传列表项的渲染方式修改图片名上传图片上传链接中添加 Bearer Token 的请求头onPreview{handlePreview}上传成功后&#xff0c;如何隐藏上传列表 使用 Ant Design 的 Upload 组件实现图片 Upload…...

【知识图谱--第二讲知识图谱的表示】

知识图谱的表示 知识表示Knowledge Representation 知识表示方法知识图谱的符号表示基于图的知识表示与建模简单图建模-最简单的无向图有向标记图OWL与Ontology 知识图谱的向量表示 知识表示 Knowledge Representation 知识表示&#xff08;KR&#xff09;就是用易于计算机处…...

C语言---计算n的阶乘

阶乘的概念&#xff1a;一个正整数的阶乘&#xff08;factorial&#xff09;是所有小于及等于该数的正整数的积&#xff0c;且0的阶乘为1&#xff0c;自然数n的阶乘写作n! 。 任何大于等于1 的自然数n 阶乘表示方法&#xff1a; n!123…(n-1)n 或 n!n(n-1)! 0&#xff01;1 …...

材料非线性Matlab有限元编程:初应力法与初应变法

导读:本文主要围绕材料非线性问题的有限元Matlab编程求解进行介绍,重点围绕牛顿-拉普森法(切线刚度法)、初应力法、初应变法等三种非线性迭代方法的算法原理展开讲解,最后利用Matlab对材料非线性问题有限元迭代求解算法进行实现,展示了实现求解的核心代码。这些内容都将收…...

QT+OSG/osgEarth编译之八十二:osgdb_obj+Qt编译(一套代码、一套框架,跨平台编译,版本:OSG-3.6.5插件库osgdb_obj)

文章目录 一、osgdb_obj介绍二、文件分析三、pro文件四、编译实践一、osgdb_obj介绍 OBJ格式是一种标准的3D模型文件格式,它以纯文本形式存储关于3D模型的信息。这种格式最初由Wavefront Technologies为其高级可视化系统开发,后来被广泛应用于3D软件之间的数据交换。OBJ格式…...

[office] excel求乘积的公式和方法 #媒体#笔记#经验分享

excel求乘积的公式和方法 本文首先给出两个常规的excel求乘积的链接&#xff0c;然后再例举了一个文字和数字在同一单元格里面的excel求乘积的公式写法。 excel求乘积的方法分为两种&#xff0c;第一种是直接用四则运算的*来求乘积&#xff0c;另外一种就是使用PRODUCT乘积函数…...

OpenEuler20.03LTS SP2 上安装 OpenGauss3.0.0 单机部署过程(二)

开始安装 OpenGauss 数据库 3.1.7 安装依赖包 (说明:如果可以联网,可以通过网络 yum 安装所需依赖包,既可以跳过本步骤。如果网络无法连通,请把本文档所在目录下的依赖包上传到服务器上,手工安装后,即无需通过网络进行 Yum 安装了): 上传:libaio-0.3.111-5.oe1.x8…...

从零开始手写mmo游戏从框架到爆炸(十)— 集成springboot-jpa与用户表

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 集成springboot-jpa&#xff0c;不用mybatis框架一个是方便对接不同的数据源。第二个目前规划的游戏内容可能对数据库的依赖不是很大&#xff0c;jpa应该肯定能满足要求了…...

Python算法题集_两两交换链表中的节点

Python算法题集_两两交换链表中的节点 题24&#xff1a;两两交换链表中的节点1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【四节点法】2) 改进版一【列表操作】3) 改进版二【三指针法】4) 改进版三【递归大法】 4. 最优算法 本文为Python算法…...

米贸搜|Facebook在购物季使用的Meta广告投放流程

一、账户简化 当广告系列开始投放后&#xff0c;每个广告组都会经历一个初始的“机器学习阶段”。简化账户架构可以帮助AI系统更快获得广告主所需的成效。例如&#xff1a; 每周转化次数超过50次的广告组&#xff0c;其单次购物费用要低28%&#xff1b;成功结束机器学习阶段的…...

前端滚动组件分享

分享一个前端可视化常用的卡片列表滚动组件&#xff0c;常用于可视化项目左右两侧的卡片列表的滚动。效果如下图所示&#xff1a; 组件描述 当鼠标移入滚动区域时&#xff0c;滚动行为停止当鼠标再次离开时&#xff0c;滚动继续 源码展示 <template><div ref"…...

【linux开发工具】vim详解

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 “学如逆水行舟&#xff0…...

Compose | UI组件(十四) | Navigation-Data - 页面导航传递数据

文章目录 前言传参流程实例说明普通方式传值定义接受参数格式定义接受参数类型获取参数传入参数传参和接受参数效果图 结合 ViewModel 传递参数定义ViewModel在 navigation 定义 ViewModel 实例&#xff0c;并且传入 LoginScreen传入输入框中的值&#xff0c;并且跳转传值获取值…...

部署一个在线OCR工具

效果 安装 1.拉取镜像 # 从 dockerhub pull docker pull mmmz/trwebocr:latest 2.运行容器 # 运行镜像 docker run -itd --rm -p 10058:8089 --name trwebocr mmmz/trwebocr:latest 使用 打开浏览器输入 http://192.168.168.110:10058/ 愉快滴使用吧...

【北邮鲁鹏老师计算机视觉课程笔记】01 introduction

1 生活中的计算机视觉 生活中的各种计算机视觉识别系统已经广泛地应用起来了。 2 计算机视觉与其他学科的关系 认知科学和神经科学是研究人类视觉系统的&#xff0c;如果能把人类视觉系统学习得更好&#xff0c;可以迁移到计算机视觉。是计算机视觉的理论基础。 算法、系统、框…...

maven依赖报错处理(或者maven怎么刷新都下载不了依赖)

maven依赖报错&#xff0c;或者不报错&#xff0c;但是怎么刷新maven都没反应&#xff0c;可以试一下以下操作 当下载jar的时候&#xff0c;如果断网&#xff0c;或者连接超时的时候&#xff0c;会自动在文件夹中创建一个名为*lastupdate的文件&#xff0c;当有了这个文件之后…...