欢迎光临
我们一直在努力

【计算机视觉】OpenCV 模板匹配银行卡数字识别---上

文章目录

  • 前言
  • 一、项目整体介绍与环境准备
  • 二、代码详解与介绍
  • 代码整体执行流程
  • 导入库
  • 命令行参数
  • 业务字典
  • 自定义图像显示函数 cv_show
  • 图像预处理
  • 轮廓检测
  • 轮廓排序、单个数字区域提取
  • 总结

前言

本文基于 OpenCV + Python ,实现银行卡卡号数字提取、模板数字匹配功能,面向编程、计算机视觉零基础学习者。


一、项目整体介绍与环境准备

日常生活中银行卡卡号由固定字体、固定大小的数字组成,我们先准备一张标准数字模板图(0~9 十个数字依次排列),通过 OpenCV 图像处理技术:

  • 读取数字模板图片;

  • 对图片做灰度、二值化预处理,让数字和背景区分更明显;

  • 检测图片中每一个数字的轮廓;

  • 对轮廓从左到右排序,保证数字顺序不乱;

  • 逐个截取 0~9 单个数字,保存为模板,供后续识别真实银行卡图片使用。

  • 银行卡图片: 请添加图片描述 卡号图片: 请添加图片描述 首先安装环境:

    # 安装OpenCV、数值计算库
    pip install opencvpython numpy

    然后再准备两个文件: 图片文件:card1.png(待识别银行卡)、kahao.png(数字模板图,0-9 横向排列) myutils.py(自定义工具脚本,用作轮廓排序)。 myutils.py:

    import cv2

    def sort_contours(cnts, method="left-to-right"):
    reverse = False
    i = 0
    # 判断排序方式
    if method == "right-to-left" or method == "bottom-to-top":
    reverse = True
    if method == "top-to-bottom" or method == "bottom-to-top":
    i = 1
    # 计算外接矩形并排序
    boundingBoxes = [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

    二、代码详解与介绍

    代码整体执行流程

  • 导入所有依赖库;

  • 创建命令行参数,接收银行卡图片和数字模板图片路径;

  • 定义银行卡卡号首位数字与卡种的映射字典;

  • 定义自定义窗口显示函数;

  • 读取数字模板图片;

  • 图像预处理:彩色图 → 灰度图 → 二值黑白图;

  • 检测图像中所有数字轮廓,并绘制轮廓;

  • 对轮廓从左到右排序,保证数字顺序为 0~9;

  • 逐个截取单个数字区域,统一尺寸,存入字典;

  • 打印最终提取的数字模板字典,程序结束。

  • 导入库

    import numpy as np
    import argparse
    import cv2
    import myutils

    import argparse是Python 内置命令行参数解析模块。

    import myutils会导入自定义工具脚本 myutils.py。 把重复使用的工具函数(轮廓排序、图像缩放、旋转等)单独封装,简化主代码。

    命令行参数

    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 OCR-A image')

    args = vars(ap.parse_args())

    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 OCR-A image')

    -i:短参数名(命令行简写,使用方便);–image:长参数名(代码内部使用的变量名,语义清晰);required=True:必传参数。运行代码时必须传入该参数,否则程序直接报错,强制用户输入图片路径;help:参数说明,输入 –help 时会展示提示文字,方便使用者理解参数作用。

    args = vars(ap.parse_args())

    vars():将解析后的参数对象,转为 Python 字典; 我们进入程序后右击鼠标,进去设置脚本形参: 在这里插入图片描述 在这里插入图片描述 设置结束点击‘Apply’应用即可,否则程序将会报错。

    业务字典

    FIRST_NUMBER={'3':'American Express',
    '4':"Visa",
    "5": "MasterCard",
    "6":"Discover Card"}

    卡号以 3 开头 → American Express 卡号以 4 开头 → Visa 卡号以 5 开头 → MasterCard 卡号以 6 开头 → Discover Card 根据银行卡第一位卡号数字判断银行卡类型。

    自定义图像显示函数 cv_show

    def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)

    封装为工具函数,一行调用。 使用格式:

    cv_show('xxx', 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)

    读取图像

    img = cv2.imread(args['template'])

    从命令行参数字典中,取出数字模板图 kahao.png 的路径。 请添加图片描述 彩色图转灰度图

    ref = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    即使图片是黑白色的,我们依旧要使用转灰度图,这是因为彩图有3个颜色通道,灰度图只有一个通道,计算快捷,简化运算。

    图像二值化

    ref = cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]

    将灰度图只保留两种像素值:纯黑 (0)、纯白 (255)。 但是代码使用的是反向二值化,这是为了边缘检测时不会检测到边缘的那一圈轮廓 在这里插入图片描述 使用反向二值化就可以避免这个问题。 在这里插入图片描述

    轮廓检测

    refCnts = cv2.findContours(ref,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[2]
    cv2.drawContours(img,refCnts,1,(0,0,255),3)

    只检测最外层轮廓,忽略内部嵌套轮廓,数字内部也是有轮廓的。 refCnts是上一步检测到的轮廓列表,-1绘制所有轮廓,(0,0,255):绘制颜色,OpenCV BGR 格式 → (0,0,255) = 红色,3:轮廓线条宽度,数值越大线条越粗。

    轮廓排序、单个数字区域提取

    refCnts = myutils.sort_contours(refCnts,method='lert=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('roi',roi)
    digits[i] = roi
    print(digits)

    调用自定义工具 myutils.sort_contours,对轮廓排序,排序规则 从左到右。 在这里插入图片描述 检测到10个最小外接矩阵,对x排序进行排序,x越小,数字越小。

    截取感兴趣区域 ROI 对图片进行切片,截取单个数字。

    roi = ref[y:y+h,x:x+w]

    统一数字尺寸 resize

    roi = cv2.resize(roi,(57,88))

    将所有数字统一缩放为 宽 57、高 88

    在这里插入图片描述 在这里插入图片描述


    总结

    读者朋友们可以通过学习前半段代码,熟练掌控模块匹配算法,后续会有完整项目放出,请耐心等待,谢谢。

    赞(0)
    未经允许不得转载:171主机测评 » 【计算机视觉】OpenCV 模板匹配银行卡数字识别---上
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址