《Opencv》信用卡信息识别项目
目录
一、项目介绍
二、数据材料介绍
1、模板图片(1张)
2、需要处理的信用卡图片(5张)
三、实现过程
1、导入需要用到的库
2、设置命令行参数
3、模板图像中数字的定位处理
4、信用卡图像处理
5、模板匹配
四、总结
一、项目介绍
项目的主要目标是实现信用卡号码和类型的识别。通过图像处理技术,从信用卡图像中提取出卡号,将每个数字与模板数字进行比对,从而得出信用卡号码。并根据卡号的第一位数字判断信用卡的类型。
二、数据材料介绍
1、模板图片(1张)

2、需要处理的信用卡图片(5张)
三、实现过程
1、导入需要用到的库
import numpy as np
import argparse
import cv2
import myutils
其中myutils模块为自己编写的工具模块,里面包含了对轮廓进行排序的函数以及自动变换图片大小的函数,内容如下:
"""myutil.py"""import cv2# 排序函数
def sort_contours(cnts, method='left-to-right'):# 初始化排序方向和索引reverse = Falseaxis_index = 0 # 默认按 x 轴排序(从左到右或从右到左)# 根据排序方法设置排序方向和索引if method == 'right-to-left' or method == 'bottom-to-top':reverse = True # 反向排序if method == 'top-to-bottom' or method == 'bottom-to-top':axis_index = 1 # 按 y 轴排序(从上到下或从下到上)# 计算每个轮廓的边界框bounding_boxes = [cv2.boundingRect(c) for c in cnts]# 将轮廓和边界框组合在一起combined = list(zip(cnts, bounding_boxes))# 根据边界框的坐标进行排序sorted_combined = sorted(combined, key=lambda x: x[1][axis_index], reverse=reverse)# 解包排序后的轮廓和边界框sorted_cnts = [item[0] for item in sorted_combined]sorted_bounding_boxes = [item[1] for item in sorted_combined]return sorted_cnts, sorted_bounding_boxes# 变换图片大小的函数
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)#参数interpolation指定了在图像大小调整过程中如何处理像素插值的方法。cv2.INTER_AREA具体意味着使用面积插值方法。return resized
2、设置命令行参数
- --image为信用卡图片
- --template为模板图片
ap = argparse.ArgumentParser()
ap.add_argument('-i','--image',required=True,help='')
ap.add_argument('-t','--template',required=True,help='')
args = vars(ap.parse_args())# 信用卡号码开头对应信用卡的类型
FIRST_NUMBER = {"3":"American Express","4":"Visa","5":"MasterCard","6":"Discover Card"}
# 定义显示图片函数
def cv_show(name, image):cv2.imshow(name, image)cv2.waitKey(0)
3、模板图像中数字的定位处理
-
读取模板图像(包含 0-9 的数字)。
-
对模板图像进行灰度化、二值化处理。
-
使用轮廓检测提取每个数字的轮廓,并将每个数字裁剪出来,保存为模板。
"""模板图像中数字的定位处理"""
# img为模板图像
img = cv2.imread(args['template'])
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)
# 轮廓
refCnts = cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
cv2.drawContours(img,refCnts,-1,(0,0,255),2)
cv_show('img',img)
# 对轮廓进行从左到右排序
refCnts = myutils.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] = roicv_show('roi',roi)
print(len(digits))
4、信用卡图像处理
-
读取信用卡图像。
-
对信用卡图像进行灰度化、顶帽操作(去除背景)、闭操作(将数字连在一起)、自适应二值化等处理。
-
使用轮廓检测找到信用卡上的数字区域。
"""信用卡的图像处理"""
image = cv2.imread(args['image'])
cv_show('image',image)
# 变换图片大小
image = myutils.resize(image,width=300)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show('gray',gray)
# 设置核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
# 顶帽
tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
# 开运算
open = cv2.morphologyEx(gray,cv2.MORPH_OPEN,rectKernel)
cv_show('open',open)
cv_show('tophat',tophat)# 找数字边框
# 闭操作,将数字连在一起
closeX = cv2.morphologyEx(tophat,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)# 闭操作
thresh = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel)
cv_show('thresh1',thresh)# 计算轮廓
threshCnts = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
cnts = threshCnts
cur_img = image.copy()
cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)
cv_show('img',cur_img)# 遍历轮廓,找到数字部分
locs = [] # 存放每组数字的x,y,w,h
for (i,c) in enumerate(cnts):(x,y,w,h) = cv2.boundingRect(c)ar = w/float(h)if 2.5 < ar < 4.0:if (40 < w < 55) and (10 < h < 20):locs.append((x,y,w,h))
locs = sorted(locs,key=lambda x: x[0])

5、模板匹配
-
将信用卡图像中的每个数字区域与模板中的数字进行匹配,找到最相似的数字。
-
根据匹配结果识别信用卡号码。
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)# 寻找每组数字的轮廓并根据顺序放入digitCntsdigitCnts = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]digitCnts = myutils.sort_contours(digitCnts)[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)# minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(src, mask=None)score = cv2.minMaxLoc(result)[1]scores.append(score)# 得到匹配分数最大值的索引groupOutput.append(str(np.argmax(scores)))cv2.rectangle(image,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)cv2.putText(image,"".join(groupOutput),(gx,gy-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,255,0),2)output.extend(groupOutput)# 打印结果
print("信用卡类型:{}".format(FIRST_NUMBER[output[0]]))
print("信用卡号码:{}".format("".join(output)))
cv_show("Image",image)
四、总结
这个项目通过图像处理和模板匹配技术,实现了信用卡号码的自动识别。它展示了如何结合 OpenCV 和 Python 实现一个实用的图像处理应用。
相关文章:
《Opencv》信用卡信息识别项目
目录 一、项目介绍 二、数据材料介绍 1、模板图片(1张) 2、需要处理的信用卡图片(5张) 三、实现过程 1、导入需要用到的库 2、设置命令行参数 3、模板图像中数字的定位处理 4、信用卡图像处理 5、模板匹配 四、总结 一…...
Matlab贝叶斯估计MCMC分析药物对不同种群生物生理指标数据评估可视化
全文链接:https://tecdat.cn/?p38756 摘要:本文着重探讨了如何利用Matlab实现贝叶斯估计。阐述了具体的实现流程,涵盖数据加载、先验常数设定、马尔可夫链蒙特卡洛(MCMC)属性指定、模型构建、运行链条以及结果查看等环…...
java 转义 反斜杠 Unexpected internal error near index 1
代码: String str"a\\c"; //出现异常,Unexpected internal error near index 1 //System.out.println(str.replaceAll("\\", "c"));//以下三种都正确 System.out.println(str.replace(\\, c)); System.out.println(str.r…...
网络安全常见的问题
1. 什么是 DDoS 攻击?如何防范? 答:DDoS 攻击是指利用大量的计算机或者其他网络设备,同时向目标网络或者服务器 发送 大量的数据流量,以致其无法正常工作,从而导致网络瘫痪或者服务器宕机的攻击行 为。 …...
在ubuntu22.04中使用bear命令追踪内核编译报错的原因分析和解决方案
1.说明 我在ubuntu22.04中使用bear命令追踪内核编译时发生如下报错: 如图,在链接名为libexec.so的动态库时发生错误 2 分析及解决过程 打印变量 LIB 发现其为空,也就是说 bear会去 /usr/bear/ 去找 libexec.so 去看一下 /usr/bear/是否存…...
【软考网工笔记】操作系统管理与配置——Windows
1-域名解析 Cache 域名解析 Cache 即 DNS 快取,DNS 快取需要应用客户机域名解析服务 DNSClient,其进程名为 svchost.exe -k NetworkService,可以输入命令:net stop dnscache 将其结束。原理是在 Windows 系统中,加入了…...
vue3 css实现文字输出带光标显示,文字输出完毕,光标消失的效果
Vue实现过程如下: <template><div ><p ref"dom_element" class"typing" :class"{over_fill: record_input_over}"></p></div> </template> <script setup> import {onMounted, ref} from…...
什么情况会导致JVM退出?
大家好,我是锋哥。今天分享关于【什么情况会导致JVM退出?】面试题。希望对大家有帮助; 什么情况会导致JVM退出? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 JVM(Java Virtual Machine)在不同情况下可能会退出&am…...
CentOS7修改Docker默认存储路径
当你使用Docker时,Docker的默认配置是将镜像、容器和卷存储在系统/var/lib/docker/目录下,如果docker镜像安装的太多会导致磁盘不够,你可以尝试以下方法来释放空间: 清理无用的镜像和容器:使用docker命令删除不再使用…...
OpenCV相机标定与3D重建(46)将三维空间中的点投影到二维图像平面上函数projectPoints()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将3D点投影到图像平面上。 cv::projectPoints 是 OpenCV 库中的一个函数,用于将三维空间中的点投影到二维图像平面上。这个过程涉及到…...
基于Elasticsearch8的向量检索实现相似图形搜索
Elasticsearch8版本增加了KNN向量检索,可以基于此功能实现以图搜图功能。 1、首先创建索引,es提供了类型为dense_vector的字段,用于存储向量,其中dims是向量维度,可以不配置,es会根据第一条插入的向量维度…...
springboot+vue使用easyExcel实现导出功能
vue部分 // 导出计算数据exportDataHandle(id) {this.$http({url: this.$http.adornUrl(/xxx/xxx/exportCalDataExcel),method: post,data: this.$http.adornData({id: id}),responseType: blob, // 重要:告诉axios我们希望接收二进制数据}).then(({data}) > {c…...
ffmpeg-avio实战:打开本地文件或者网络直播流dome
使用ffmpeg打开打开本地文件或者网络直播流的一个小dome。流程产靠ffmpeg4.x系列的解码流程-CSDN博客 #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavformat/avio.h> #include <libavutil/file.h> #include &l…...
css预处理器sass
在前端开发的世界中,CSS 是构建网页样式的基础。然而,随着项目规模的增大,纯 CSS 的编写和维护往往会变得复杂而繁琐。为了解决这些痛点,Sass(Syntactically Awesome Style Sheets)应运而生。Sass 是一种 C…...
VulnHub-Acid(1/100)
参考链接: 【VulnHub】Acid靶场复盘-CSDN博客 靶场渗透(二)——Acid渗透_ambassador 靶场渗透-CSDN博客 网络安全从0到0.5之Acid靶机实战渗透测试 | CN-SEC 中文网 Vulnhub靶场渗透练习(四) Acid - 紅人 - 博客园 红日团队…...
MATLAB语言的正则表达式
MATLAB 中的正则表达式使用指南 引言 在数据处理和文本分析中,正则表达式是一种强大而灵活的工具。MATLAB 作为一种广泛应用于科学计算和数据分析的编程语言,提供了对正则表达式的支持,使得用户可以方便地进行字符串匹配与处理。本文将深入…...
通过 route 或 ip route 管理Linux主机路由
目录 一:route 使用说明1、查看路由信息2、删除指定路由3、增加指定路由 二:ip route 使用说明1、查看主机路由2、新增主机路由3、删除主机路由 通过route 或者ip route修改Linux主机路由后属于临时生效,系统重启后就恢复默认值了,…...
MYSQL--------SQL 注入简介MySQL SQL Mode 简介
SQL 注入简介 定义:SQL 注入是一种常见的安全漏洞,攻击者通过在输入中插入恶意的 SQL 语句,利用应用程序中未正确处理的输入数据,来改变 SQL 查询的逻辑,从而执行非预期的操作,如绕过身份验证、获取未授权…...
第6章——HTTP首部
第六章——HTTP首部 HTTP报文结构 都必有报文首部 HTTP请求报文 HTTP响应报文 HTTP首部字段 ###传递重要信息 首部字段结构 首部字段名:字段值(,字段值,字段值) 首部字段类型 通用首部字段 请求首部字…...
多行输入模式(dquote> 提示符)double quote(双引号)
文章目录 1、引号不匹配具体原因解决办法如何避免此问题 2、double quote(双引号)出现原因解决办法预防措施 ~/Downloads/productqualification-develop git:[main] git commit -m "漏添加到暂存区的代码“ dgqdgqdeMac-mini productqualification-…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
Python爬虫(52)Scrapy-Redis分布式爬虫架构实战:IP代理池深度集成与跨地域数据采集
目录 一、引言:当爬虫遭遇"地域封锁"二、背景解析:分布式爬虫的两大技术挑战1. 传统Scrapy架构的局限性2. 地域限制的三种典型表现 三、架构设计:Scrapy-Redis 代理池的协同机制1. 分布式架构拓扑图2. 核心组件协同流程 四、技术实…...
C++ 使用 ffmpeg 解码 rtsp 流并获取每帧的YUV数据
一、简介 FFmpeg 是一个开源的多媒体处理框架,非常适用于处理音视频的录制、转换、流化和播放。 二、代码 示例代码使用工作线程读取rtsp视频流,自动重连,支持手动退出,解码并将二进制文件保存下来。 注意: 代…...
【学习笔记】深入理解Java虚拟机学习笔记——第5章 调优案例分析与实战
第5章 调优案例分析与实战 5.1 概述 略 5.2 案例分析 5.2.1 大内存硬件上的程序部署策略 为防止大内存一次Full GC时间过长,可以考虑使用响应速度优先的垃圾回收器,还可以通过将一个10GB堆内存的应用分解为5个2GB堆内存应用,并通过负载均…...
关于智能体API参考接口
关于智能体在Flask的源码:请求体(在payload里的是请求体)、请求头(在headers里的i局势请求头)。 我的例子: 我的疑问:为什么没按Coze官方API文档格式,在Apifox里发POST请求却能收到回复? 1. 你…...
