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

银行卡号识别案例

代码实现:

import cv2
import numpy as np
import argparse
import myutils
'''
-i moban.png
-t card1.png
'''
ap= argparse.ArgumentParser()
ap.add_argument("-i","--image", required=True,help="path to input image")
ap.add_argument("-t","--template", required=True,help="path to template 0cR-A image")
args = vars(ap.parse_args())
FIRST_NUMBER ={ "3":"American Express","4": "Visa","5":"MasterCard","6":"Discover Card"}
def cv_show(name,img):cv2.imshow(name,img)cv2.waitKey(0)''' --------模板图像中数字的定位处理----------- '''
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, hierarchy = cv2.findContours(ref, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,0,255),3)
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))cv_show('ro',roi)digits[i]= roi
print(digits)
''' --------信用卡的图像处理----------- '''
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)
cv_show('tophat',tophat)
closeX = cv2.morphologyEx(tophat,cv2.MORPH_CLOSE,rectKernel)
cv_show('gradX',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,h = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = threshCnts
cur_img = image.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 ar>2.5 and ar<4.0:if (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])
print(locs)
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)# 计算每一组的轮廓group_, digitCnts, hierarchy = 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:# 找到当前数值的轮廓,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(image, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# cv2.putText()是OpenCV库中的一个函数,用于在图像上添加文本。cv2.putText(image, "".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)
cv2.waitKey(0)

这段代码实现了基于模板匹配的信用卡数字识别,核心流程分为「模板图像预处理」「信用卡图像预处理」「轮廓检测与分组」「数字模板匹配与识别」四个阶段,以下是详细解析:

1. 初始化与参数解析

  • 参数解析:通过 argparse 解析命令行参数,-i 指定信用卡输入图像路径,-t 指定数字模板图像(包含 0-9 数字的参考图)。
  • 信用卡品牌映射FIRST_NUMBER 字典通过卡号首数字映射信用卡品牌(如 Visa 以 4 开头)。
  • 辅助函数cv_show 用于调试时显示图像并等待按键。

2. 模板图像预处理(制备数字模板)

目的是从模板图像中提取 0-9 的标准数字模板,供后续匹配使用:

  1. 读入与灰度转换:读取模板图像并转为灰度图。
  2. 反相二值化cv2.threshold(..., THRESH_BINARY_INV) 将数字转为白色、背景转为黑色,便于轮廓检测。
  3. 轮廓检测与排序
    • cv2.findContours 提取所有外部轮廓(每个数字对应一个轮廓)。
    • myutils.sort_contours(自定义函数)按从左到右排序轮廓,确保数字顺序与视觉一致。
  4. 提取数字 ROI 并标准化:遍历每个轮廓,提取数字区域(ROI),并缩放到统一尺寸 (57, 88),存储到 digits 字典(键为索引,值为数字模板)。

3. 信用卡图像预处理(增强数字区域)

目的是从信用卡图像中突出数字区域,便于后续轮廓检测:

  1. 读入与尺寸调整:读取信用卡图像,按比例缩放到宽度 300(方便统一处理)。
  2. 灰度转换:转为灰度图,消除颜色干扰。
  3. 形态学操作(增强数字)
    • 顶帽操作(TOPHAT):用长方形结构核 rectKernel 突出比背景亮的区域(即数字区域)。
    • 闭运算(CLOSE):先膨胀后腐蚀,用 rectKernel 连接水平方向的数字,使 “4 位一组的数字” 形成整体区域;再用正方形核 sqKernel 连接数字内部间隙,让轮廓更完整。
  4. 二值化(OTSU 自适应阈值)cv2.threshold(..., THRESH_BINARY | THRESH_OTSU) 自动确定阈值,将图像转为黑白二值图(数字为白,背景为黑)。

4. 轮廓筛选与数字分组

目的是从预处理后的图像中,筛选出 ** 信用卡数字组(通常 4 位一组)** 的轮廓:

  • 遍历所有轮廓,通过宽高比(ar宽 / 高的数值范围筛选符合 “数字组特征” 的轮廓(如信用卡数字组宽高比约 2.5-4,宽度 40-55,高度 10-20,需根据实际图像调整)。
  • 按轮廓的 x 坐标排序,确保从左到右处理数字组。

5. 数字模板匹配与识别

对每个筛选出的数字组,逐数字进行模板匹配:

  1. 提取数字组 ROI:扩展数字组的边界(gY -5 等),避免数字被截断。
  2. 数字组二值化:对提取的区域再次二值化,与模板格式一致。
  3. 单数字轮廓检测与排序:提取数字组内的单个数字轮廓,按从左到右排序。
  4. 模板匹配
    • 对每个单数字 ROI,缩放到模板尺寸 (57, 88)
    • 用 cv2.matchTemplate(方法为 TM_CCOEFF)与 digits 中所有数字模板匹配,计算 “匹配得分”。
    • 选择得分最高的模板,其索引对应数字(如索引 0 对应模板中最左侧数字)。
  5. 结果绘制与存储:在原图上绘制数字组的矩形框,并将识别出的数字用 cv2.putText 显示;同时将数字存入 output 列表,最终拼接为完整卡号。

6. 信用卡品牌与卡号输出

  • 从 output 中取首数字,通过 FIRST_NUMBER 字典判断信用卡品牌。
  • 打印品牌与完整卡号,并显示最终图像。

关键注意事项

  • 参数适配:形态学核的尺寸、轮廓筛选的宽高比 / 范围,需根据图像分辨率、数字大小调整。
  • 模板质量:模板图像的清晰度、数字完整性,直接影响匹配准确率。
  • 排序依赖myutils.sort_contours(自定义轮廓排序函数)是确保 “数字顺序正确” 的关键。
  • 匹配方法TM_CCOEFF 适合黑白模板匹配,因它对亮度差异不敏感,更关注形状相关性。

文章转载自:

http://2b3yDI5j.bdwqy.cn
http://qAXdY9qc.bdwqy.cn
http://kplaTR3R.bdwqy.cn
http://G1AIeTj3.bdwqy.cn
http://5ik3mBkZ.bdwqy.cn
http://91tpN2FQ.bdwqy.cn
http://kU78asJE.bdwqy.cn
http://gfcoWWcD.bdwqy.cn
http://VkLpz5sQ.bdwqy.cn
http://xqWH9GBN.bdwqy.cn
http://zXCtmPIk.bdwqy.cn
http://XfFqVppO.bdwqy.cn
http://6ywcoMqi.bdwqy.cn
http://rtsZJBOJ.bdwqy.cn
http://zevJEtHL.bdwqy.cn
http://twNq46T5.bdwqy.cn
http://kJ8ohF67.bdwqy.cn
http://s54q8fQ3.bdwqy.cn
http://avAM3aso.bdwqy.cn
http://z3HFIaXF.bdwqy.cn
http://VxLIol7R.bdwqy.cn
http://znmFIFo9.bdwqy.cn
http://RrChf3RO.bdwqy.cn
http://h81223NQ.bdwqy.cn
http://Hgauz995.bdwqy.cn
http://RSR8JPbY.bdwqy.cn
http://gpuDO2Lh.bdwqy.cn
http://vAb92VC1.bdwqy.cn
http://bWwiCWeY.bdwqy.cn
http://uChJG74L.bdwqy.cn
http://www.dtcms.com/a/373408.html

相关文章:

  • 【golang学习笔记 gin 】1.2 redis 的使用
  • AI提示词(Prompt)基础核心知识点
  • VTK开发笔记(五):示例Cone2,熟悉观察者模式,在Qt窗口中详解复现对应的Demo
  • Excel 表格 - Excel 减少干扰、专注于内容的查看方式
  • Vue3 + Ant Design Vue 全局配置中文指南
  • CSS in JS 的演进:Styled Components, Emotion 等的深度对比与技术选型指引
  • 哈士奇vs网易高级数仓:数据仓库的灵魂是模型、数据质量还是计算速度?| 易错题
  • Windows 命令行:cd 命令2,切换到多级子目录
  • C++ 8
  • GD32入门到实战45--LVGL开发(Code::Blocks)之创建控件
  • 算法题(202):乌龟棋
  • 国产化服务注册与发现工具nacos安装
  • WordPress 性能优化:从插件到 CDN 的全方位缓存设置指南
  • 所有微服务部署都使用一个git地址,并且通过docker部署各个服务的情况下,如何编写mvn指令来处理各个服务。
  • 【AI】乡村振兴计划书:AI智能农业与设备研发销售一体化项目
  • 408 Request Timeout:请求超时,服务器等待客户端发送请求的时间过长。
  • 从车辆中心到用户中心:E/E架构的变革与挑战
  • 基于Mysql+SpringBoot+vue框架-校园商铺管理系统源码
  • SQL MERGE语句实战:高效增量数据处理
  • AI 云再进化,百度智能云新技术与产品全景解读
  • react 面试题 react 有什么特点?
  • PyTorch 模型保存与加载 (速查版)
  • MCU-在SOTA过程中基于TC397的AB-SWAP切换底层原理
  • Python+DRVT 从外部调用 Revit:批量创建带孔洞楼板
  • 如何解决Ubuntu22.04安装Docker后使用Timeshift进行备份非常慢的问题
  • 自适应支撑衣专利拆解:IMU 传感器与线轴引擎的支撑力动态调节机制
  • Linux系统shell脚本(五)
  • 秋招刷题|数据分析岗:Numpy30道核心考点解析
  • 实例分割网络-YOLACT使用
  • PyCharm SSH Autodl