【项目实战】基于python+pycharm+OpenCV的信用卡数字识别

2023-11-10

一、pycharm实现参数配置

直接运行程序会报错:
usage: ocr_template_match.py [-h] -i IMAGE -t TEMPLATE
ocr_template_match.py: error: the following arguments are required: -i/–image

1、找到如图所示位置,点击script parameters 进行参数设置
在这里插入图片描述
2、参数的内容设置如下,导入匹配图片的位置和待匹配图片,其中两张图片均在python文件夹下的images中
在这里插入图片描述

二、信用卡数字识别的图片

信用卡图片:

在这里插入图片描述
匹配模板:

在这里插入图片描述

三、代码实现

这个代码的通用性不强,对于匹配模板要求较高,并且匹配效率较低,可以应用在汽车车牌的匹配中。
代码如下:
ocr_template_match.py

# 导入工具包
from imutils import contours
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())

# 指定信用卡类型
FIRST_NUMBER = {
	"3": "American Express",
	"4": "Visa",
	"5": "MasterCard",
	"6": "Discover Card"
}
# 绘图展示,定义一个显示图像的函数,方便后期输出每一步的图像
def cv_show(name,img):
	cv2.imshow(name, img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

# 读取一个模板图像,即用来匹配的数字模板,0-9
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只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓 hierachy(所有的轮廓)

refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

#drawCountours绘制轮廓 三个参数分别为,被绘制的图像,获取的轮廓信息,-1表示所有的图像的轮廓,颜色标记为R,
cv2.drawContours(img,refCnts,-1,(0,0,255),3) 
cv_show('img',img)
#输出refcnts的形状,为10,获取到10个轮廓
print (np.array(refCnts).shape)
#对十个轮廓进行排序
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {}

# 遍历每一个轮廓 其中i表示轮廓索引,c表示找到的轮廓
for (i, c) in enumerate(refCnts):
	# 计算外接矩形并且resize成合适大小 ,x,y表示矩形的起点坐标,w,h,表示矩形的长宽
	(x, y, w, h) = cv2.boundingRect(c)
	roi = ref[y:y + h, x:x + w]
	roi = cv2.resize(roi, (57, 88))

	# 每一个数字对应每一个模板
	digits[i] = roi

# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

#读取输入图像,预处理,待匹配图像
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)

#礼帽操作,突出更明亮的区域,三个参数分别表示,传入的图片,变化的方式(顶帽运算),矩形核的大小
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) 
cv_show('tophat',tophat) 
# sobel算子,参数表示为:需处理的图像,图像深度,dx,dy,求导的阶数,算子的大小
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的
	ksize=-1)


gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")

print (np.array(gradX).shape)
cv_show('gradX',gradX)

#通过闭操作(先膨胀,再腐蚀)将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) 
cv_show('gradX',gradX)
#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,
	cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] 
cv_show('thresh',thresh)

#再来一个闭操作

thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show('thresh',thresh)

# 计算轮廓 经过处理后的待匹配图像,其中threshcnts表示找到的轮廓, cv2.RETR_EXTERNAL表示只检测外轮廓,
# cv2.CHAIN_APPROX_SIMPLE,压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
#和匹配图像的处理方式一样
threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
	cv2.CHAIN_APPROX_SIMPLE)

cnts = threshCnts
cur_img = image.copy()
#画出找到的待匹配图像轮廓
cv2.drawContours(cur_img,cnts,-1,(0,0,255),3) 
cv_show('img',cur_img)
#存储符合条件的轮廓信息,包括四部分,起点终点和长宽。形成一个列表的形式存储
locs = []

# 遍历轮廓 其中i表示索引,c表示每一个轮廓,通过两个判断语句(具体情况)去除一部分轮廓
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:

		if (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])
output = []

# 遍历每一个轮廓中的数字,索引及详细信息
for (i, (gX, gY, gW, gH)) in enumerate(locs):
	# initialize the list of group digits
	groupOutput = []

	# 根据坐标提取每一个组,将每一组的轮廓适当的上下左右均扩大
	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,hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
		cv2.CHAIN_APPROX_SIMPLE)
	digitCnts = contours.sort_contours(digitCnts,
		method="left-to-right")[0]

	# 计算每一组中的每一个数值
	for c in digitCnts:
		# 找到当前数值的轮廓,resize成合适的的大小
		(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.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[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)

mutils.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] #用一个最小的矩形,把找到的形状包起来x,y,h,w
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
                                        key=lambda b: b[1][i], reverse=reverse))

    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)
    return resized

结果:
模板图像:
在这里插入图片描述
模板外轮廓图像:
在这里插入图片描述
待匹配图像:
在这里插入图片描述
识别结果图像:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【项目实战】基于python+pycharm+OpenCV的信用卡数字识别 的相关文章

  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • OpenCV Python cv2.mixChannels()

    我试图将其从 C 转换为 Python 但它给出了不同的色调结果 In C Transform it to HSV cvtColor src hsv CV BGR2HSV Use only the Hue value hue create
  • 如何在flask中使用g.user全局

    据我了解 Flask 中的 g 变量 它应该为我提供一个全局位置来存储数据 例如登录后保存当前用户 它是否正确 我希望我的导航在登录后在整个网站上显示我的用户名 我的观点包含 from Flask import g among other
  • 为 Anaconda Python 安装 psycopg2

    我有 Anaconda Python 3 4 但是每当我运行旧代码时 我都会通过输入 source activate python2 切换到 Anaconda Python 2 7 我的问题是我为 Anaconda Python 3 4 安
  • 如何从网页中嵌入的 Tableau 图表中抓取工具提示值

    我试图弄清楚是否有一种方法以及如何使用 python 从网页中的 Tableau 嵌入图形中抓取工具提示值 以下是当用户将鼠标悬停在条形上时带有工具提示的图表示例 我从要从中抓取的原始网页中获取了此网址 https covid19 colo
  • 是否可以忽略一行的pyright检查?

    我需要忽略一行的pyright 检查 有什么特别的评论吗 def create slog group SLogGroup data Optional dict None SLog insert one SLog group group da
  • SQLALchemy .query:类“Car”的未解析属性引用“query”

    我有一个这里已经提到的问题https youtrack jetbrains com issue PY 44557 https youtrack jetbrains com issue PY 44557 但我还没有找到解决方案 我使用 Pyt
  • 使用 Tkinter 显示 numpy 数组中的图像

    我对 Python 缺乏经验 第一次使用 Tkinter 制作一个 UI 显示我的数字分类程序与 mnist 数据集的结果 当图像来自 numpy 数组而不是我的 PC 上的文件路径时 我有一个关于在 Tkinter 中显示图像的问题 我为
  • Python 函数可以从作用域之外赋予新属性吗?

    我不知道你可以这样做 def tom print tom s locals locals def dick z print z name z name z guest Harry print z guest z guest print di
  • AWS EMR Spark Python 日志记录

    我正在 AWS EMR 上运行一个非常简单的 Spark 作业 但似乎无法从我的脚本中获取任何日志输出 我尝试过打印到 stderr from pyspark import SparkContext import sys if name m
  • 在Python中获取文件描述符的位置

    比如说 我有一个原始数字文件描述符 我需要根据它获取文件中的当前位置 import os psutil some code that works with file lp lib open path to file p psutil Pro
  • 在f字符串中转义字符[重复]

    这个问题在这里已经有答案了 我遇到了以下问题f string gt gt gt a hello how to print hello gt gt gt f a a gt gt gt f a File
  • 使用 \r 并打印一些文本后如何清除控制台中的一行?

    对于我当前的项目 有一些代码很慢并且我无法使其更快 为了获得一些关于已完成 必须完成多少的反馈 我创建了一个进度片段 您可以在下面看到 当你看到最后一行时 sys stdout write r100 80 n I use 80覆盖最终剩余的
  • 向 Altair 图表添加背景实心填充

    I like Altair a lot for making graphs in Python As a tribute I wanted to regenerate the Economist graph s in Mistakes we
  • 对年龄列进行分组/分类

    我有一个数据框说df有一个柱子 Ages gt gt gt df Age 0 22 1 38 2 26 3 35 4 35 5 1 6 54 我想对这个年龄段进行分组并创建一个像这样的新专栏 If age gt 0 age lt 2 the
  • 如何在 Python 中追加到 JSON 文件?

    我有一个 JSON 文件 其中包含 67790 1 kwh 319 4 现在我创建一个字典a dict我需要将其附加到 JSON 文件中 我尝试了这段代码 with open DATA FILENAME a as f json obj js
  • 解释 Python 中的数字范围

    在 Pylons Web 应用程序中 我需要获取一个字符串 例如 关于如何做到这一点有什么建议吗 我是 Python 新手 我还没有找到任何可以帮助解决此类问题的东西 该列表将是 1 2 3 45 46 48 49 50 51 77 使用
  • 使用 Python 绘制 2D 核密度估计

    I would like to plot a 2D kernel density estimation I find the seaborn package very useful here However after searching
  • Scrapy:如何使用元在方法之间传递项目

    我是 scrapy 和 python 的新手 我试图将 parse quotes 中的项目 item author 传递给下一个解析方法 parse bio 我尝试了 request meta 和 response meta 方法 如 sc
  • 在 Qt 中自动调整标签文本大小 - 奇怪的行为

    在 Qt 中 我有一个复合小部件 它由排列在 QBoxLayouts 内的多个 QLabels 组成 当小部件调整大小时 我希望标签文本缩放以填充标签区域 并且我已经在 resizeEvent 中实现了文本大小的调整 这可行 但似乎发生了某

随机推荐

  • java/php/net/python健身房管理系统设计

    本系统带文档lw万字以上 答辩PPT 查重 如果这个题目不合适 可以去我上传的资源里面找题目 找不到的话 评论留下题目 或者站内私信我 有时间看到机会给您发 系统设计 4 1 系统体系结构 健身房管理系统的结构图4 1所示
  • mysql localhost值_jdbc:mysql://localhost:3306/mysql这句话中localhost具体指什么的localhost?能修改么?在哪里配置的?...

    展开全部 jdbc mysql 是指JDBC连接方式 localhost 是指你的本机地址 3306 SQL数据库的端口 jdbc 就是你要连接的32313133353236313431303231363533e59b9ee7ad94313
  • Mysql 8.0修改密码

    1 mysql u root p 原来的密码 进入数据库中 2 show databases 3 use mysql 4 使用下面的语句修改密码 ALTER USER root localhost IDENTIFIED WITH mysql
  • 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接

    驱动程序无法通过使用安全套接字层 SSL 加密与 SQL Server 建立安全连接 错误 The server selected protocol version TLS10 is not accepted by client prefe
  • STM32初始化结构体变量时成员排序的问题

    平台 STM32F103RCT6 MDK 笔者在调试时发现 结构体不同类型成员的定义顺序对于程序运行过程中的取值可能会产生很大的BUG 开始时定义 输入参数结构体 typedef struct u8 TempRange 温度最大值 floa
  • 日期格式‘YYYY-MM-DD’中的BUG

    1 日期格式 先来看一下日期格式主要有下面三种 US style Euro style RFC 3389 Layout Format string Example US style Dec 29 2019 MM DD YYYY 12 29
  • yolo格式数据转换为coco格式

    只需要有图片和yolo格式的标签就可以转换为coco格式的标签 第一步 将yolo格式的标签 classId xCenter yCenter w h转换为coco格式 classId xMin yMim xMax yMax格式 coco的i
  • 【产品设计】电商后台系统设计--订单管理

    电商后台产品 涉及众多模块 而以商品 订单 库存 为核心模块 模块之间存在大量交互 订单较为重要 它记录了所有的交易数据 对电商公司来讲 最核心最难做的有三部分 商品 订单 库存 商品与店铺 营销 评价等相关 订单与会员 营销 支付 库存
  • C# WPF MVVM设计模式下ComboBox的数据源更新的一个问题

    C WPF MVVM设计模式下ComboBox的数据源问题 问题的出现 解决 问题的出现 我在设计一个基于C MVVM 的WPF应用 当我对MainWindow的一个ComboBox进行数据绑定时候 发现当数据源更新后 前台的ComboBo
  • BSN武汉链对接说明

    项目说明 我们项目需要把ETH合约功能迁移到国内链上来 然后基于开发成本等多方面考虑 最终选择了BSN 武汉链接入 相关的BSN文档 BSN 文档地址 对接说明 1 创建BSN帐号 注册并登录bsn官网 网址 BSN官网 点击开放联盟链 g
  • 【Qt】控件探幽——QLineEdit

    注1 本系列文章使用的Qt版本为Qt 6 3 1 注2 本系列文章常规情况下不会直接贴出源码供复制 都以图片形式展示 所有代码 自己动手写一写 记忆更深刻 本文目录 QLineEdit探幽 1 设置数据 获取数据 2 只读 readOnly
  • 2023年华为od机试Java【人气最高的店铺】

    题目 某城市有m个商店和n位市民 现在要举行一场活动 通过投票来选出最受欢迎的商店 每位市民只能投一票 他们将根据自己的喜好为指定的商店投票 然而 1号商店有一个特殊的优势 它可以给每位市民发放补贴 使他们改变投票意向 投票给1号商店 请你
  • 超级计算机是几近制,进制

    进制也就是进位计数制 是人为定义的带进位的计数方法 有不带进位的计数方法 比如原始的结绳计数法 唱票时常用的 正 字计数法 以及类似的tally mark计数 对于任何一种进制 X进制 就表示每一位置上的数运算时都是逢X进一位 十进制是逢十
  • 第 5 章 HBase 优化

    5 1 RowKey 设计 一条数据的唯一标识就是 rowkey 那么这条数据存储于哪个分区 取决于 rowkey 处于 哪个一个预分区的区间内 设计 rowkey的主要目的 就是让数据均匀的分布于所有的 region 中 在一定程度上防止
  • git原理探索实验1——git的三种对象

    背景知识 git的三个区域 working directory 也就是你当前所能操作的那些目录和文件 history 你所提交的所有记录 文件历史内容等等 git是个分布式版本管理系统 在你本地有项目的所有历史提交记录 文件历史记录 提交日
  • MR 从 mysql中 读取 和 写入 数据

    1 编写DBWritable类 import org apache hadoop io Writable import org apache hadoop mapred lib db DBWritable import java io Da
  • ROS Qt环境的搭建及基础知识介绍

    ROS Qt环境的搭建及基础知识介绍 文章目录 ROS Qt环境的搭建及基础知识介绍 1 开发环境搭建 1 1 qtcreator安装 1 2 catkin create qt pkg环境配置 1 3 配置功能包 2 Qt基础 3 Qt编译
  • Python知识点(史上最全)

    Python期末考试知识点 史上最全 python简介 Python是一种解释型语言 Python使用缩进对齐组织代码执行 所以没有缩进的代码 都会在载入时自动执行 数据类型 整形 int 无限大 浮点型 float 小数 复数 compl
  • 区块链节点和用户的介绍

    用户身份 用户身份的概念 用户身份是由用户的公钥地址 用户私钥共同组成 私钥签名 公钥验签 公钥加密 私钥解密 公钥是对外公布的密钥 私钥由用户个人保存 发送交易时用接收方公钥进行加密 发送方私钥进行签名 接收交易时用接收方私钥进行解密 发
  • 【项目实战】基于python+pycharm+OpenCV的信用卡数字识别

    一 pycharm实现参数配置 直接运行程序会报错 usage ocr template match py h i IMAGE t TEMPLATE ocr template match py error the following arg