Opencv实现提取卡号(数字识别)

2024-09-04 00:44

本文主要是介绍Opencv实现提取卡号(数字识别),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

直接开始

实行方法

  1. 解析命令行参数:使用argparse库来解析命令行输入,确保用户提供了输入图像和模板图像的路径。

  2. 读取模板图像:使用cv2.imread()函数读取模板图像的路径,并显示原始图像。

  3. 图像预处理

    • 将图像转换为灰度图,以简化后续处理。
    • 应用二值化操作(使用阈值10)将图像转换为二值图像(黑白图),并通过cv2.THRESH_BINARY_INV反转颜色,使前景(数字)为白色,背景为黑色。
    • 显示预处理后的二值图像。
  4. 轮廓检测

    • 使用cv2.findContours()函数在二值图像上检测轮廓。这里只检测外部轮廓,并使用cv2.CHAIN_APPROX_SIMPLE方法来简化轮廓形状。
    • 在原始图像上绘制检测到的轮廓,并显示结果。
  5. 轮廓排序

    • 使用自定义的myutils.sort_contours()函数对检测到的轮廓进行排序,这里假设该函数按照从左到右的顺序排序轮廓。

自定义的myutils库

import cv2def sort_contours(cnts, method='left to-right'):reverse = Falsei = 0if method == 'right-to-left' or method == 'bottom-to-top':reverse = Trueif method == 'top-to-bottom' or method == 'bottom-to-top':i = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts](cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxesdef 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 imageif 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. 数字模板提取

    • 遍历排序后的轮廓,对每个轮廓计算其外接矩形,并裁剪出相应的区域(ROI,Region of Interest)。
    • 将每个裁剪出的ROI区域缩放到固定大小(57x88),以便于后续与输入图像中的数字进行匹配。
    • 将每个缩放后的ROI存储到digits字典中,其中键为轮廓的索引,值为对应的数字模板图像。

接下来,你可能会想要使用这些数字模板与输入图像中的数字进行匹配,以确定输入图像中每个数字的具体值。这通常涉及到模板匹配技术,如使用cv2.matchTemplate()函数。

  • 读取输入图像。
  • 对输入图像进行类似的预处理步骤。
  • 在输入图像上检测可能的数字区域。
  • 对每个检测到的数字区域,使用提取的模板进行匹配,以确定其值。
  • 根据识别出的数字进行进一步的处理或分析(如确定信用卡类型等)。
import argparse
import cv2
import myutilsap = 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())#创建ArgumentParser对象来解析命令行参数。
#添加两个必需的参数:-i/--image(输入图像路径)和-t/--template(模板图像路径)。
#使用parse_args()解析命令行输入,并将结果转换为字典存储在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)
# 计算轮廓:cv2.findcontours()函数接受的参数为二值图,
# 即黑白的(不是灰度图)CV2.RETR_EXTERNAL只检测外轮廓,
# CV2.CHAIN_APPROX_SIMPLE只保留终点坐标
_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
cv_show('img', img)#使用findContours函数检测二值图像中的轮廓。
#在原始图像上绘制检测到的轮廓。
#假设myutils.sort_contours函数存在,并按从左到右的顺序对轮廓进行排序。注意这里[0]可能是为了处理#sort_contours返回值的格式,具体取决于该函数的实现。
#refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]digits = {}
for (i, c) in enumerate(refCnts):  # 遍历每一个轮廓(x, y, w, h) = cv2.boundingRect(c)  # 计算外接矩形并且resize成合适大小roi = ref[y:y + h, x:x + w]roi = cv2.resize(roi, (57, 88))  # 缩放到指定的大小digits[i] = roi  # 每一个数字对应每一个模板
#遍历排序后的轮廓。
#对每个轮廓,计算其外接矩形,并裁剪出相应的区域(ROI)。
#将每个ROI缩放到固定大小(57x88)。
#将缩放后的ROI存储在digits字典中,键为轮廓的索引

代码效果:

这篇关于Opencv实现提取卡号(数字识别)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134515

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja