opencv 之 实战项目 识别银行卡上的数字

news2024/9/23 7:33:08

OpenCV 之 实战项目:识别银行卡上的数字

引言

在日常生活中,银行卡的识别是一个常见的需求,特别是在金融领域。本实战项目旨在使用 OpenCV 库来识别银行卡上的数字。我们将通过模板匹配的方法,结合图像处理技术,来准确识别银行卡上的数字序列。

项目准备

本项目需要安装 Python 和 OpenCV 库。确保已经安装了必要的库,并准备好银行卡图像和数字模板图像。

        实验素材


        定义函数
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))
    #zip(*...)使用星号操作符解包排序后的元组列表,并将其重新组合成两个列表:一个包含所有轮廓,另一个包含所有边界框。
    return cnts, boundingBoxes

def resize(image,width=None,height=None ,inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized=cv2.resize(image,dim,interpolation=inter)    #默认为cV2.INTER_AREA,即面积插值,适用于缩放图像。
    return resized
        传入参数
        
代码详解
  1. 导入库和设置参数
    import numpy as np
    import argparse
    import cv2
    import myutils
    
    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())

    解释:

    • 导入必要的库。
    • 使用 argparse 库来设置命令行参数,包括输入图像路径和模板图像路径。
    • 解析命令行参数并将结果存储在 args 字典中。
  2. 指定信用卡类型
    FIRST_NUMBER = {"3": "American Express",
                    "4": "Visa",
                    "5": "MasterCard",
                    "6": "Discover Card"}

    解释:

    • 定义一个字典,根据银行卡号的第一个数字来确定其类型。
  3. 模板图像处理
    img = cv2.imread(args["template"])
    ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
    _, refCnts, _ = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    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))
        digits[i] = roi

    解释:

    • 读取模板图像并转换为灰度图。
    • 将灰度图转换为二值图。
    • 计算模板图像中的轮廓,并按照从左到右的顺序排序。
    • 提取每个数字的 ROI(感兴趣区域),并将其存储在 digits 字典中。
  4. 银行卡图像处理
    image = cv2.imread(args["image"])
    image = myutils.resize(image, width=300)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
    sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
    closeX = cv2.morphologyEx(tophat, cv2.MORPH_CLOSE, rectKernel)
    thresh = cv2.threshold(closeX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
    _, threshCnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = threshCnts
    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 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])

    解释:

    • 读取银行卡图像并调整大小。
    • 转换为灰度图。
    • 使用顶帽操作增强图像中的数字区域。
    • 使用形态学闭操作连接数字区域。
    • 计算阈值并进一步处理图像。
    • 计算图像中的轮廓,并筛选出符合条件的数字区域。
    • 将数字区域按照从左到右的顺序排序。
  5. 数字识别
    output = []
    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))
            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(image, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
        output.extend(groupOutput)

    解释:

    • 对每个数字区域进行处理,提取每个数字的 ROI。
    • 使用模板匹配计算每个数字区域与模板的匹配得分。
    • 将得分最高的模板对应的数字添加到结果中。
    • 在图像上绘制矩形框和识别结果。
  6. 打印结果
    print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
    print("Credit Card #:{}".format("".join(output)))
    cv2.imshow("Image", image)
    cv2.waitKey(0)

    解释:

    • 打印识别出的信用卡类型和号码。
    • 显示处理后的图像。
  7. 输出结果:
总结

通过本实战项目,我们展示了如何使用 OpenCV 进行银行卡上数字的识别。整个过程包括模板图像处理、银行卡图像预处理、数字区域定位、模板匹配以及结果展示。这种技术在金融领域有着广泛的应用,可以帮助自动化处理大量的银行卡识别任务。通过适当的图像处理技术和模板匹配方法,我们可以准确地识别出银行卡上的数字序列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2126968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络安全】基础知识详解(非常详细)零基础入门到精通

一、什么是网络安全&#xff1f; 百度上对“网络安全”是这么介绍的&#xff1a; “网络安全是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然的或者恶意的原因而遭受到破坏、更改、泄露、系统连续可靠正常地运行&#xff0c;网络服务不中断。” 嗯…是不…

Xubuntu22.04之四种方式:查看U盘、硬盘格式(二百六十七)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

【操作系统】二、进程管理:4.死锁(银行家算法、系统安全状态、静态分配策略、资源有序分配法)

五、死锁 文章目录 五、死锁1.产生1.1产生情况1.2产生的4个必要条件 2.处理方式2.1预防死锁2.1.1破坏互斥条件2.1.2破坏请求和保持条件2.1.3破坏不可抢占条件2.1.4破坏循环等待条件 2.2避免死锁2.2.1系统安全状态❗2.2.2银行家算法 2.3检测死锁2.4解除死锁 死锁&#xff1a;资源…

用centos安装远程迅雷失败,重写程序做一台下载服务器

安装远程迅雷的时候&#xff0c;要不是安装包地址过期&#xff0c;就是出现64不兼容32的libz.so.1的包&#xff0c;而且32位的libz包也是好多网站过期。 没办法用仅有的python3&#xff0c;用flask搭建了一个小型的内网下载服务器&#xff0c;当然&#xff0c;只要路由器做映射…

软件测试认知篇

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 今天给大家带来的是 软件测试的认知篇, 从什么是软件测试出发, 其次是测试和开发之间的区别, 软件测试有哪些岗位, 以及测试人员需求具备的素质, 最后是3道软件测试的面试题~ &#xff0…

如何将 Electron 项目上架 Apple Store

前言 Electron 是一个开源框架,它允许开发者使用 Web 技术(HTML、CSS 和 JavaScript)来构建跨平台的桌面应用程序。 Electron 应用程序可以运行在 Windows、macOS 和 Linux 上,为用户提供了一种统一的方式来开发和维护软件。 本文将探讨如何将 Electron 构建的桌面应用程…

R语言进行无序多分类Logistic回归

在临床研究中&#xff0c;接触最多的是二分类数据&#xff0c;如淋巴癌是否转移&#xff0c;是否死亡&#xff0c;这些因变量最后都可以转换成二分类0与1的问题。然后建立二元logistic回归方程&#xff0c;可以得到影响因素的OR值。但有时我们也会接触到多分类结局数据&#xf…

re题(18)BUUCTF-简单注册器

BUUCTF在线评测 (buuoj.cn) 放到jadx找主函数 也可以用Jeb打开&#xff0c;Tab反编译成java 写个脚本 str[d,d,2,9,4,0,c,0,4,4,6,2,b,4,d,d,7,c,4,5,0,5,2,8,8,3,5,c,c,a,1,5]str[2]chr(ord(str[2])ord(str[3])-50) str[4]chr( ord(str[2])ord(str[5])-0x30 ) str[30]chr( ord…

JS设计模式之外观模式:简化复杂系统调用的利器

一、了解外观模式 概念 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它提供了一个简单的接口&#xff0c;隐藏了一个复杂系统的内部复杂性&#xff0c;使得客户端可以通过该接口与系统进行交互&#xff0c;而无需了解系统内部的具体实现…

vue3 一次二次封装element-plus组件引发的思考

前言 在开发 Vue 项目中我们一般使用第三方 UI 组件库进行开发&#xff0c;如 Element-Plus、Element-ui、Ant-design等, 但是这些组件库提供的组件并不一定都能满足我们的日常开发需求&#xff0c;有时候我们需要实现的效果是直接使用组件库无法实现的&#xff0c;那么这时我…

TMS320F28335的基本电路设计

1.电源电路 2.时钟电路 3.复位电路 4.JTAG电路 5.外扩RAM电路 6.外扩Flash电路 7.GPIO电平转换电路 8.ADC调理电路 9.串口通信电路 10.CAN电路 11.I2C电路 12.BOOT启动电路 12.调试注意事项

如何判断一个系统的大小端的存储模式

1、什么是大小端 大小端&#xff1a;是指在计算机系统中&#xff0c;多字节数据&#xff08;如整数、浮点数等&#xff09;存储顺序的不同而不同的称呼。 在计算机内存中&#xff0c;数据是以字节为单位存储的。对于多字节数据&#xff0c;如4字节的整数&#xff0c;存储的时…

基于JAVA+SpringBoot+Vue的前后端分离企业oa管理系统

基于JAVASpringBootVue的前后端分离企业oa管理系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1…

化工原料环保能源网站模板整站打包下载

图片在最下面 响应式新能源化工研究院网站模板.zip 营销型硅胶制品原料网站模板.zip 环境水务治理网站模板.zip 响应式新能源清洁能源公司网站模板.zip 环保废气废水处理工程类网站模板.zip 活性炭净化炭企业网站模板.zip 响应式新能源开发企业网站模板.zip 营销型塑料…

leaflet【十】实时增加轨迹点轨迹回放效果实现

实时轨迹回放 在前面有用leaflet-trackplayer实现了一个轨迹回放的效果&#xff0c;单击前往&#xff1a;轨迹回放效果&控制台控制轨迹运动效果 这篇文章主要是实现一下实时增加轨迹点&#xff0c;不改变原来运行轨迹和速度。这里是简易做了一个demo效果&#xff0c;大概…

django学习入门系列之第十点《A 案例: 员工管理系统5》

文章目录 7 模板的继承7.1 继承指令-占位符7.2 继承指令 - 继承符7.3 **想用继承的html的文件**7.4 简单模板的例子 8 用户管理8.1 展示日期数据8.2 转义文字&#xff08;应该会常用&#xff09;8.3 搜索并跨表8.4 模板语法 往期回顾 7 模板的继承 部门列表添加部门编辑部门 …

如何使用ChatGPT,完成学术论文文献综述的编写?

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 在学术研究中&#xff0c;文献综述是了解研究现状、辨识研究空白并为自己的研究奠定理论基础的关键环节。ChatGPT 可以在文献综述的编写过程中提供有效的支持&#xff0c;从文献搜集、批…

51单片机快速入门之延时代码 STC 51单片机

51单片机快速入门之延时代码 时序周期:简单的举例(早 中 晚) 时间基准:一个机器周期有 12个 振荡周期(晶振) 假设我们现在手上为12MHz晶振 单个振荡周期计算公式:T(时间周期)1/f(晶振的频率) 在处理频率相关的计算时&#xff0c;通常会使用赫兹&#xff08;Hz&#xff09;…

【Linux】【Vim】Vim 基础

Vim/Gvim 基础 文本编辑基础编辑操作符命令和位移改变文本重复改动Visual 模式移动文本(复制、粘贴)文本对象替换模式 光标移动以 word 为单位移动行首和行尾行内指定单字符移动到匹配的括号光标移动到指定行滚屏简单查找 /string标记 分屏vimdiff 文本编辑 基础编辑 Normal 模…

Unity让摄像机跟随物体的方法(不借助父子关系)

在Unity中&#xff0c;不使用子对象的方式让相机跟随物体移动&#xff0c;我们通过编写脚本来实现。下面放一个从工程中摘出来的的C#脚本示例&#xff0c;用于将相机绑定到一个Target对象上并跟随其移动&#xff1a; using UnityEngine; public class FollowCamera : MonoBeh…