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

Written by

in

文章目录
  • 采用经典的图像处理流程,主要分为两个核心阶段: 模板预处理阶段:预先处理标准OCR-A字体模板,提取并存储每个数字的特征模板 卡号识别阶段:对输入的银行卡图像进行多步处理,定位卡号区域,分割单个数字,通过模板匹配实现识别 整个系统基于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) 这是一个简单的图像显示封装函数,便于在开发过程中可视化各个处理阶段的结果。
  • # 输出银行卡类型和完整卡号 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银行卡卡号识别的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: Python实现批量识别银行卡号码以及自动写入Excel表格步骤详解 Python如何识别银行卡卡号? Python OpenCV实现识别信用卡号教程详解 python计算机视觉opencv卡号识别示例详解 Python OpenCV招商银行信用卡卡号识别的方法
  • 目录
    • 一、流程概述
    • 二、环境配置与参数设置
    • 三、命令行参数配置
    • 四、银行卡类型定义
    • 五、辅助函数定义
    • 六、模板图像预处理
      • 6.1 模板加载与初步处理
      • 6.2 轮廓提取与数字模板建立
    • 七、银行卡图像处理流程
      • 7.1 图像加载与初步调整
      • 7.2 形态学处理突出数字区域
      • 7.3 数字区域定位与提取
      • 7.4 数字组轮廓检测与筛选
    • 八、数字识别核心算法
      • 8.1 单个数字组处理
      • 8.2 模板匹配识别数字
      • 8.3 结果可视化
    • 九、最终结果输出

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

      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)
      

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

      # 读取并显示模板图像
      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:反向二值化,生成黑底白字效果

      # 检测轮廓(只检测外轮廓)
      _, 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像素,确保后续匹配的准确性

      # 读取待识别图像
      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像素,既保证处理速度,又维持足够的分辨率。

      # 定义形态学操作的卷积核
      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)
      

      形态学操作原理:

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

      # 第一次闭操作:连接相近的数字
      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)
      

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

      # 检测轮廓
      _, 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像素:匹配标准尺寸

      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]
      

          # 识别组内每个数字
          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):返回最高得分的索引,即识别出的数字

          # 绘制数字组矩形框(红色)
          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银行卡卡号识别的资料请关注风君子博客其它相关文章!

      您可能感兴趣的文章:

      • Python实现批量识别银行卡号码以及自动写入Excel表格步骤详解
      • Python如何识别银行卡卡号?
      • Python OpenCV实现识别信用卡号教程详解
      • python计算机视觉opencv卡号识别示例详解
      • Python OpenCV招商银行信用卡卡号识别的方法

      站内搜索