当前位置: 代码网 > it编程>前端脚本>Python > Python使用OpenCV实现银行卡卡号识别

Python使用OpenCV实现银行卡卡号识别

2026年01月22日 Python 我要评论
一、流程概述采用经典的图像处理流程,主要分为两个核心阶段:模板预处理阶段:预先处理标准ocr-a字体模板,提取并存储每个数字的特征模板卡号识别阶段:对输入的银行卡图像进行多步处理,定位卡号区域,分割单

一、流程概述

采用经典的图像处理流程,主要分为两个核心阶段:

  1. 模板预处理阶段:预先处理标准ocr-a字体模板,提取并存储每个数字的特征模板
  2. 卡号识别阶段:对输入的银行卡图像进行多步处理,定位卡号区域,分割单个数字,通过模板匹配实现识别

整个系统基于opencv库实现。

二、环境配置与参数设置

import numpy as np
import argparse
import cv2
import myutils
from imutils import contours

模块作用分析:

  • numpy:提供高效的数值计算和数组操作
  • argparse:python内置库,用于解析命令行参数
  • cv2:opencv库,核心图像处理功能
  • myutils:自定义工具模块,包含轮廓排序等辅助函数
  • imutils.contours:提供轮廓处理的便捷函数

三、命令行参数配置

# 设置参数
ap = argparse.argumentparser()  # 创建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())  # 将参数转换为字典格式,便于访问

# 使用示例:
# python demo47.py -i card1.png -t kahao.png

参数说明:

  • -i/--image:必需参数,指定待识别的银行卡图像路径
  • -t/--template:必需参数,指定ocr-a模板图像路径

四、银行卡类型定义

# 根据卡号首位数字判断银行卡类型
first_number = {
    "3": "american express",   # 美国运通卡
    "4": "visa",              # visa卡
    "5": "mastercard",        # 万事达卡
    "6": "discover card"      # 发现卡
}

这个字典基于银行卡号的行业标准:首位数字3代表美国运通,4代表visa,5代表万事达,6代表发现卡。

五、辅助函数定义

def cv_show(name, img):  # 图像显示函数
    """显示图像并等待按键响应"""
    cv2.imshow(name, img)
    cv2.waitkey(0)

这是一个简单的图像显示封装函数,便于在开发过程中可视化各个处理阶段的结果。

六、模板图像预处理

6.1 模板加载与初步处理

# 读取并显示模板图像
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)

关键步骤解析:

  1. 灰度转换:将彩色 图像转换为单通道灰度图,减少计算复杂度
  2. 二值化:使用阈值处理,将图像转换为纯黑白两色,便于轮廓提取
  3. thresh_binary_inv:反向二值化,生成黑底白字效果

6.2 轮廓提取与数字模板建立

# 检测轮廓(只检测外轮廓)
_, refcnts, hierarchy = cv2.findcontours(ref.copy(), cv2.retr_external, cv2.chain_approx_simple)

# 在原始图像上绘制轮廓(红色)
cv2.drawcontours(img, refcnts, -1, (0, 0, 255), 3)
cv_show('refcnts', 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('roi', roi)
    
    digits[i] = roi  # 存储模板:键为数字,值为模板图像

技术细节:

  • cv2.findcontours():在二值图像中查找轮廓
  • retr_external:仅检测最外层轮廓
  • chain_approx_simple:压缩轮廓点,减少内存使用
  • 模板标准化:将所有数字缩放到57×88像素,确保后续匹配的准确性

七、银行卡图像处理流程

7.1 图像加载与初步调整

# 读取待识别图像
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)

宽度统一调整为300像素,既保证处理速度,又维持足够的分辨率。

7.2 形态学处理突出数字区域

# 定义形态学操作的卷积核
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_img = cv2.morphologyex(gray, cv2.morph_open, rectkernel)
cv_show('open', open_img)
cv_show('tophat', tophat)

形态学操作原理:

  • 顶帽操作:原始图像减去开运算结果,突出比背景亮的细小区域
  • 开运算:先腐蚀后膨胀,消除小物体,平滑边界
  • 银行卡数字通常比背景亮,顶帽操作能有效突出这些数字

7.3 数字区域定位与提取

# 第一次闭操作:连接相近的数字
closex = cv2.morphologyex(tophat, cv2.morph_close, rectkernel)
cv_show('close1', 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('close2', thresh)

闭操作的作用:通过先膨胀后腐蚀,连接相邻的白色区域(数字),将分散的数字点连接成完整的数字组。

7.4 数字组轮廓检测与筛选

# 检测轮廓
_, cnts, _ = cv2.findcontours(thresh.copy(), cv2.retr_external, cv2.chain_approx_simple)

# 可视化所有轮廓
cnts_img = image.copy()
cv2.drawcontours(cnts_img, cnts, -1, (0, 0, 255), 3)
cv_show('cnts_img', cnts_img)

# 筛选符合条件的轮廓(银行卡号区域)
locs = []
for c in 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))

# 按x坐标排序(从左到右)
locs = sorted(locs, key=lambda x: x[0])

筛选逻辑:

  • 宽高比2.5-4.0:匹配银行卡号区域的长条形特征
  • 宽度40-55像素,高度10-20像素:匹配标准尺寸

八、数字识别核心算法

8.1 单个数字组处理

output = []  # 存储最终识别结果

# 遍历每个数字组(通常一组4个数字)
for (gx, gy, gw, gh) in locs:
    groupoutput = []  # 存储当前组的识别结果
    
    # 提取数字组区域,添加5像素边界
    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)
    
    # 检测组内每个数字的轮廓
    _, digitcnts, _ = cv2.findcontours(group.copy(), cv2.retr_external, cv2.chain_approx_simple)
    digitcnts = myutils.sort_contours(digitcnts, method="left-to-right")[0]

8.2 模板匹配识别数字

    # 识别组内每个数字
    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)
            (_, score, _, _) = cv2.minmaxloc(result)
            scores.append(score)
        
        # 选择最高得分的数字
        groupoutput.append(str(np.argmax(scores)))

模板匹配原理:

  • cv2.matchtemplate():在输入图像中搜索与模板匹配的区域
  • tm_ccoeff:相关系数匹配方法,对光照变化鲁棒
  • np.argmax(scores):返回最高得分的索引,即识别出的数字

8.3 结果可视化

    # 绘制数字组矩形框(红色)
    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("credit card type: {}".format(first_number.get(output[0], "unknown")))
print("credit card #: {}".format("".join(output)))

# 显示最终处理结果
cv2.imshow("image", image)
cv2.waitkey(0)
cv2.destroyallwindows()

以上就是python使用opencv实现银行卡卡号识别的详细内容,更多关于python opencv银行卡卡号识别的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com