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

计算机视觉opencv----银行卡号码识别

信用卡卡号识别系统的整体设计思路详解

本系统旨在通过图像处理与模板匹配技术,实现从信用卡图片中自动提取并识别卡号的功能。其核心思路借鉴了人类识别卡号的认知过程:首先观察信用卡整体找到卡号所在区域,然后聚焦该区域逐个辨认数字,最后整合结果。具体可拆解为 **"模板准备 - 目标定位 - 特征提取 - 匹配识别"** 四个核心环节,形成一套完整的图像识别流水线。

设计思路的底层逻辑
  1. 模板匹配的选择依据:信用卡数字通常采用标准化字体(如 OCR-A 字体),形状固定且差异显著,适合通过模板匹配进行识别。相比深度学习方法,模板匹配无需大量标注数据,实现简单且对清晰图像的识别效率高。

  2. 分步处理的必要性:直接对整张信用卡图片进行数字识别会受到卡面图案、背景纹理、光照等干扰,因此系统采用 "先定位、后识别" 的策略:

    • 第一步:从复杂背景中分离出卡号区域(减少干扰)
    • 第二步:在孤立的卡号区域中提取单个数字(简化识别对象)
    • 第三步:将单个数字与标准模板比对(实现精准识别)
  3. 特征筛选的关键作用:信用卡卡号具有显著的物理特征(如 4 组数字排列、固定宽高比、统一字体),系统通过这些特征筛选有效区域,排除签名栏、logo 等无关信息,提高识别效率。

系统详细步骤解析

1. 环境配置与参数设置
import numpy as np
import argparse
import cv2
import myutils  # 自定义工具模块# 命令行参数设置
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="信用卡图片路径")
ap.add_argument("-t", "--template", required=True, help="数字模板图片路径")
args = vars(ap.parse_args())
  • 参数解析:使用argparse库允许用户在运行程序时灵活指定输入图片和模板图片的路径,无需修改代码即可处理不同图片,增强了程序的通用性。
  • 依赖说明cv2(OpenCV)负责核心图像处理,numpy用于数值计算,myutils是自定义工具库(通常包含图像缩放、轮廓排序等功能)。
2. 基础定义与辅助函数
# 信用卡类型映射表(根据卡号首位判断)
FIRST_NUMBER = {"3": "American Express", "4": "Visa", "5": "MasterCard", "6": "Discover Card"}# 图像显示函数
def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)  # 等待按键输入后关闭窗口,便于分步查看处理效果
  • 信用卡类型判断:国际通用的信用卡号编码规则中,首位数字代表卡组织(如 4 开头是 Visa 卡),通过映射表可快速识别卡类型。
  • 显示函数:封装了 OpenCV 的图像显示功能,方便在开发过程中查看每一步的处理结果,用于调试和验证。
3. 数字模板库的创建(核心准备工作)

模板库是识别数字的 "参照物",需要先从模板图片中提取 0-9 的标准数字样式:

# 读取模板图片并预处理
img = cv2.imread(args["template"])  # 模板图片通常包含0-9的数字(如OCR-A字体,银行常用)
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转为灰度图(简化计算,去除颜色干扰)
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]  # 反相二值化(让数字为白色,背景为黑色)# 提取模板中的数字轮廓
_, refCnts, hierarchy = cv2.findContours(ref, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 轮廓排序:从左到右排列(确保提取的数字顺序是0-9)
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:感兴趣区域)roi = cv2.resize(roi, (57, 88))  # 统一尺寸(确保后续匹配时大小一致)digits[i] = roi  # 存储:键为数字(0-9),值为对应的模板图像
  • 模板预处理关键步骤
    • 灰度化:将彩色图像转为黑白,减少计算量(彩色图有 3 个通道,灰度图仅 1 个)。
    • 反相二值化:通过阈值分割将数字和背景分离,反相处理确保数字为白色(便于后续轮廓检测)。
  • 轮廓提取与排序findContours函数能识别图像中的连续边缘(数字的轮廓),通过排序确保提取的轮廓从左到右对应 0-9 的顺序,避免数字错乱。
  • 标准化尺寸:不同数字的原始大小可能有差异,统一缩放为 57×88 像素,保证后续模板匹配的准确性。
4. 输入图像预处理(突出卡号特征)

对用户输入的信用卡图片进行处理,目的是去除干扰,突出卡号区域:

# 读取信用卡图片并调整大小
image = cv2.imread(args["image"])
image = myutils.resize(image, width=300)  # 固定宽度为300像素(便于统一处理,避免尺寸差异影响结果)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 转为灰度图# 顶帽操作:突出图像中的亮区域(卡号通常为白色/亮色,背景较暗)
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))  # 矩形卷积核(宽9,高3,适合水平方向的卡号)
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)  # 顶帽 = 原始图 - 开运算结果(保留亮细节)
  • 图像缩放:统一输入图像尺寸,避免因图片大小不同导致后续处理参数(如卷积核尺寸)失效。
  • 顶帽操作:信用卡卡号通常是浅色(如白色),背景(如蓝色卡面)颜色较深,顶帽操作能有效增强浅色区域的对比度,抑制背景干扰。
5. 卡号区域定位(找到数字所在位置)

通过形态学操作和轮廓筛选,精准定位卡号在图片中的位置:

# 闭操作:将分散的数字连接成一个整体(便于识别卡号块)
closeX = cv2.morphologyEx(tophat, cv2.MORPH_CLOSE, rectKernel)  # 闭操作 = 先膨胀后腐蚀(填补数字间的缝隙)
# 二值化:进一步增强卡号与背景的对比
thresh = cv2.threshold(closeX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 二次闭操作:消除小噪点,强化卡号区域的完整性
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 方形卷积核
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)# 查找图像中的所有轮廓(可能包含卡号、卡面图案等)
_, threshCnts, h = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
locs = []  # 存储筛选后的卡号区域# 筛选符合卡号特征的轮廓
for (i, c) in enumerate(threshCnts):(x, y, w, h) = cv2.boundingRect(c)  # 计算轮廓的外接矩形ar = w / float(h)  # 宽高比(卡号区域的关键特征)# 信用卡卡号通常为4组数字,每组4位,宽高比约3-4,尺寸在特定范围if ar > 3 and ar < 4.0 and (w > 40 and w < 55) and (h > 10 and h < 20):locs.append((x, y, w, h))  # 符合条件的区域保留# 按水平位置排序(确保卡号从左到右识别)
locs = sorted(locs, key=lambda x: x[0])
  • 形态学操作的作用
    • 第一次闭操作:将同一组内的 4 个数字连接成一个矩形块(原本数字间有间隙)。
    • 二次闭操作:消除小面积噪点(如卡面花纹产生的干扰轮廓),确保轮廓的完整性。
  • 轮廓筛选依据:信用卡卡号的物理特征(宽高比、尺寸范围)是筛选的关键,不符合特征的轮廓(如卡面 logo、签名栏)会被排除。
6. 数字识别与结果输出(核心匹配过程)

对定位到的卡号区域逐个识别数字,并输出最终结果:

output = []  # 存储最终识别的卡号# 遍历每个卡号区域(通常4组)
for (i, (gX, gY, gW, gH)) in enumerate(locs):groupOutput = []  # 存储当前组的识别结果# 提取当前组的数字区域(适当扩大范围,避免裁剪到数字边缘)group = gray[gY-5:gY+gH+5, gX-5:gX+gW+5]# 二值化:将当前组的数字转为黑白(便于提取单个数字轮廓)group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]# 提取当前组内的单个数字轮廓_, digitCnts, _ = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)digitCnts = myutils.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))  # 缩放为与模板相同的尺寸(57×88)# 模板匹配:计算当前数字与模板库中每个数字的匹配度scores = []for (digit, digitROI) in digits.items():# 用TM_CCOEFF方法计算匹配得分(值越高,匹配度越好)result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)(_, score, _, _) = cv2.minMaxLoc(result)  # 提取最高得分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, 0, 255), 2)output.extend(groupOutput)  # 将当前组结果加入总结果# 输出最终结果
print("信用卡类型: {}".format(FIRST_NUMBER[output[0]]))  # 根据首位数字判断类型
print("信用卡号: {}".format("".join(output)))  # 拼接所有数字
cv2.imshow("识别结果", image)  # 显示标注后的图片
cv2.waitKey(0)
  • 模板匹配原理:通过cv2.matchTemplate计算待识别数字与模板的相似度(得分),得分最高的模板对应的数字即为识别结果。这类似于 "找相同"—— 将提取的数字与标准模板逐一比对,最相似的就是答案。
  • 结果可视化:在原图上用矩形框标记卡号位置,并显示识别的数字,便于人工核对结果。
  • 卡号类型判断:利用卡号首位数字与卡组织的对应关系,自动识别信用卡类型(如 Visa、MasterCard 等)。

系统特点与局限性

  • 优点:实现简单,对清晰的信用卡图片识别准确率高,无需复杂的机器学习模型。
  • 局限性
    1. 依赖模板字体:如果信用卡数字字体与模板差异大(如艺术字体),识别会失效。
    2. 受图像质量影响:图片模糊、光照不均或有遮挡时,定位和识别效果会明显下降。
    3. 固定特征筛选:卡号区域的宽高比、尺寸等筛选条件是固定的,对非标准信用卡可能不适用。


文章转载自:

http://HzIdZaX0.wgkqq.cn
http://AHBmCGeO.wgkqq.cn
http://w1qqNgZl.wgkqq.cn
http://5ZF1cCHA.wgkqq.cn
http://EB4C5yle.wgkqq.cn
http://EiGq45ju.wgkqq.cn
http://5V8MvchH.wgkqq.cn
http://28u0OEWJ.wgkqq.cn
http://MQaIdyIl.wgkqq.cn
http://JdaozWR0.wgkqq.cn
http://tB1AUYZE.wgkqq.cn
http://oUF91MSz.wgkqq.cn
http://TXjuoenv.wgkqq.cn
http://bx7zMqog.wgkqq.cn
http://sH5xcnRK.wgkqq.cn
http://5KMQilfn.wgkqq.cn
http://Vf7aH0ey.wgkqq.cn
http://uEyFjtvH.wgkqq.cn
http://ynJ2p1zF.wgkqq.cn
http://351YFasl.wgkqq.cn
http://GWEG9Ra3.wgkqq.cn
http://XegpxRrX.wgkqq.cn
http://K5nEiwkm.wgkqq.cn
http://KzcSihBy.wgkqq.cn
http://axADWlak.wgkqq.cn
http://4ZpNgACn.wgkqq.cn
http://I25OhjWj.wgkqq.cn
http://Vxit4mtZ.wgkqq.cn
http://aOqPZH0U.wgkqq.cn
http://JFfxjuBg.wgkqq.cn
http://www.dtcms.com/a/372713.html

相关文章:

  • 第六章、从transformer到nlp大模型:编码器-解码器模型 (Encoder-Decoder)
  • pymodbus启动一个简单的modbus tcp server
  • 【NowCoder】牛客周赛 Round 108 EF (背包问题 | SOSDP)
  • 【ARMday02】
  • OFDR设备开机到出图的5个关键操作步骤
  • ArcGIS学习-19 实战-表面分析
  • 【算法】双指针(二)复写零
  • 视频串行解串器(SerDes)介绍
  • PyTorch 动态图的灵活性与实用技巧
  • 【P01_AI测试开发课程-导论】
  • 从社交破冰到学习规划,鸿蒙5开启智慧校园新生活
  • 【Linux操作系统】简学深悟启示录:文件fd
  • Kata Container 部署与应用实践
  • 【CentOS7】docker安装成功后测试,报Unable to find image ‘hello-world:latest‘ locally
  • springboot配置请求日志
  • 2-ATSAMV71Q21-BOOT
  • 【Qt开发】显示类控件(一)-> QLabel
  • 把不确定变成确定性收益:电力交易未来场景的预测、优化与实操
  • 大数据毕业设计选题推荐-基于大数据的国家药品采集药品数据可视化分析系统-Spark-Hadoop-Bigdata
  • 如何在Linux上使用Docker在本地部署开源PDF工具Stirling PDF:StirlingPDF+cpolar让专业操作像在线文档一样简单
  • 7,000 星!AutoMQ 开源再创里程碑
  • 四大金刚之计算机操作系统
  • 深入剖析 MyBatis 核心原理模块一:快速入门
  • 【Ansible】的介绍
  • VMware共享文件夹设置
  • YOLO11实战 第009期-基于yolo11的咖啡叶病害目标检测实战文档(yolo格式数据免费获取)
  • MATLAB可以实现的各种智能算法
  • PPP协议及其消息传播机制
  • 从全栈工程师视角解析Java与前端技术在电商场景中的应用
  • SQL注入7----(盲注与回显)