【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读)

这篇具有很好参考价值的文章主要介绍了【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

所有订阅专栏的同学可以私信博主获取源码文件

0.背景介绍

接下来我们正式进入项目实战部分,这一章要介绍的是一个信用卡号识别的项目。首先,我们来明确一下研究的问题,假设我们有一张信用卡如下所示,我们要做的就是识别出这上面卡号信息,然后会输出一个序列,第一个序列就是4020,第二序列是3400,第三个序列0234,第四个序列5678,也就是说此时我们不光是把这个数输出来,我们还要知道对应的位置。

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

之前我们已经介绍了Opencv的各种图像基本操作,例如形态学操作、模板匹配、轮廓检测,我们现在要做的就是把这些方法全部应用到一起,相当于把我们以前所学的知识点全部穿插到咱们这个项目当中了。

我们先来看一下要完成这个项目的基本思路。

思考一: 首先最核心的问题是我们如何判断一个数字是几呢?这里我们要用到模板匹配

假设我们有一个数字模板如下:

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

现在我们要做的就是将信用卡上每一个数字和模板上的数字进行匹配,看一下它与模板上的哪一个数字最接近,我们就把这个数字输出。因此我们第一步需要得到一个与目标信用卡数字字体非常接近的一个模板。

思考二: 如何每一个数字单独拿出来?

我们之前介绍轮廓检测,但是直接得到的轮廓各个数字之间非常不规则,我们可以利用轮廓的外接矩形或者外接圆来进行操作。

总体就是分为以上两个步骤,具体过程我们还需要对图像进行各种预处理操作,我们在后面在代码中细致介绍。

以下是项目的主要框架,想要源码的可以私信我获取。

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

1.模板处理

1.1模板读取

首先我们将目标模板读取

# 导入工具包
from imutils import contours
import numpy as np
import argparse
import cv2
import myutils


# 指定模板和目标图像位置
target = 'images/credit_card_02.png'
template = 'images/ocr_a_reference.png'

# 定义图像展示函数
def cv_show(name,img):
	cv2.imshow(name, img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

# 读取模板图像
img = cv2.imread(template)

cv_show(im)

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

1.2预处理

接下来对模板进行预处理,转换为二值图,因为我们后续轮廓检测时只接受二值图输入。

# 灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('ref',ref)

# 二值图像
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1] #阈值设为10
cv_show('ref',ref)

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

现在得到了二值图像之后我们就可以进行图像轮廓检测了。

1.3轮廓计算

在这里我们使用cv2.findContours()函数,其只接收一个二值图像,cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标。返回参数我们只需要用refCnts即可,它返回的是我们的轮廓信息

# 计算轮廓

#返回的list中每个元素都是图像中的一个轮廓

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

cv2.drawContours(img,refCnts,-1,(0,0,255),3) # -1表示绘制所有轮廓
cv_show('img',img) #展示轮廓


【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

现在我们得到了0-9每个数字的外轮廓信息,但是直接返回的轮廓顺序不一定是按照我们模板从左到右排序的,接下来我们需要对轮廓进行排序,让它按照从左到右0,1,2,3,4…9的顺序排列,这里我们定义了函数,sort_contours,我们直接根据我们的坐标排序,就可以得到按照0-9排列的轮廓

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

现在得到了排序好后的轮廓,接下来我们需要把模板中每个数字轮廓单独拿出来放到一个字典中方便我们后续进行匹配,通过cv.boundingRect()得到轮廓坐标和长宽信息,然后利用我们之前的ROI读取方法即可,最后我们更改一下轮廓的大小。

refCnts = sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右
digits = {}

# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):
	# 计算外接矩形并且resize成合适大小
	(x, y, w, h) = cv2.boundingRect(c)
	roi = ref[y:y + h, x:x + w]
	roi = cv2.resize(roi, (57, 88))

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

接下来我们就得到了每个数字模板的轮廓信息,并保留在digits字典中,接下来我们需要对输入图像进行处理。

2.输入图像处理

2.1图形读取

这里我们初始化了两个卷积核,分别为9×35×5的,这里大家可以根据自己的任务更换别的卷积核大小。然后我们把目标图像读取进来并转换为灰度图

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


#读取输入图像,预处理

image = cv2.imread(target)
cv_show('image',image)
image = myutils.resize(image, width=300)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 转换为灰度图
cv_show('gray',gray)

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

2.2预处理

得到灰度图之后,我们需要进行更细节的预处理,因为我们想要检测的是银行卡号,我们关注的是这样的数字部分,也就是更亮的区域,因此我们在这里进行了礼帽操作,来突出我们想要研究的信息,在实际应用中,可以根据具体想要研究的任务来选择其他的处理方式

#礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) 
cv_show('tophat',tophat) 

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

接下来我们进一步的利用sobel算子来进行边缘检测

gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的
	ksize=-1) # 使用Sobel算子处理


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)

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

得到边缘之后,我们希望将这些数字分块放到一起,每四个数字为一个小方块。我们可以利用之前介绍过的先膨胀,再腐蚀的操作。

#通过闭操作(先膨胀,再腐蚀)将数字连在一起
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)

首先经过一个闭操作后,得到下列结果

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

然后我们进一步使用二值化处理,将图片转换为二值图像

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

现在得到的结果中,还有一部分空隙,我们再进行一次闭操作,得到结果如下:

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

现在得到的结果是一个完全闭合的状态了,此时我们再检测它的外轮廓,会更准确一些。

2.3轮廓计算

接下来我们计算轮廓,和之前在处理模板一样,我们调用cv2.findContours()函数计算轮廓信息。

# 计算轮廓

thresh_, 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)

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

这里需要说明的是,我们这里是用经过一切预处理后得到的轮廓信息,然后绘制在原始图像中。但是我们得到的轮廓有点多,且有一些不太规则的形状,有些可能不是我们想要轮廓,我们需要把这些轮廓过滤,我们只要四组数字轮廓。我们可以根据他们的坐标位置进行筛选,具体的筛选范围大家要根据自己的实际任务选择.

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: #这里需要根据具体的任务更改,我这里是经过几次尝试测试出来的

		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])
locs
[(34, 111, 47, 14), (95, 111, 48, 14), (157, 111, 47, 14), (219, 111, 48, 14)]

可以看到我们现在得到了四个轮廓,并且进行了排序,接下来我们怎么进行模板匹配呢?我们不是拿这四个大轮廓去匹配,而是在每一个大轮廓中,再去分隔成小轮廓,然后去和我们之前保存的10个数的模板进行匹配。

2.4计算匹配得分

接下来我们要做的是去遍历每一个轮廓当中的数字,然后将其与模板中的10个数字计算匹配得分,从而识别出对于的数字,我们先来看第一个轮廓:

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

有了这个之后,就和我们最开始处理模板一样,先进行二值化处理,得到下图

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

然后计算每一组的轮廓,并按照从左到右的顺序排列,以第一个数字为例,得到结果如下

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

然后我们就是将这每一个数字与模板上的10个数字进行对比,看一下和哪一个最相似。具体做法跟之前都是一样的吧,先去找到外接矩形,然后对外接矩形进行resize。然后我们就要计算得分了,我们利用模板匹配中的方法,使用cv2.TM_CCOEFF计算得分,然后找到最匹配的数字,这样就完成了我们所有的步骤了

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)
	# 计算每一组的轮廓
	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: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)
Credit Card: 4020340002345678

【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读),《Opencv入门到项目实战》,opencv,人工智能,计算机视觉,原力计划

3.小结

我们这个项目主要分两步。第一步,定位到目标数字在什么位置。第二步,基于定位好的区域,在模板当中去匹配它到底是一个什么样的值。中间利用了我们之前介绍过的各种图像处理方法。今天我们这个项目是做一个信用卡号识别,如果说大家想做车牌识别、学生卡、身份证识别,都是一个类似的做法,我们主需要更改一下对于的照片模板以及其中的一些参数即可。

🔎本章的介绍到此介绍,如果文章对你有帮助,请多多点赞、收藏、评论、订阅支持!!《Opencv入门到项目实战》文章来源地址https://www.toymoban.com/news/detail-641034.html

到了这里,关于【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器学习:基于XGBoost对信用卡欺诈行为的识别

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 大家好,我

    2024年02月08日
    浏览(70)
  • 数据挖掘实战(2):信用卡诈骗分析

    ⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者: 秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们 点赞👍🏻、收藏

    2024年02月07日
    浏览(57)
  • 机器学习:基于AdaBoost算法模型对信用卡是否违约进行识别

    作者:i阿极 作者简介:数据分析领域优质创作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 大家

    2024年02月08日
    浏览(52)
  • 【银行测试】银行项目,信用卡业务测试+常问面试(三)

    银行测试-信用卡业务 1、信用卡额度如何测试? 正常测试场景: 在ATM取款,取款的金额≤信用卡额度/2(例如:信用卡额度为:2W,在ATM可成功取款10000); 在POS机上刷卡消费金额,单笔金额≤信用卡额度,交易成功; 消费的金额,超过信用卡正常额度(1-10%)交易成功(例

    2024年01月16日
    浏览(60)
  • 机器学习:基于AdaBoost算法对信用卡精准营销建立模型(附案例实战)

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 订阅专栏案

    2023年04月09日
    浏览(49)
  • 【Python机器学习】SVM解决非线性问题和信用卡欺诈检测实战(附源码和数据集)

    需要全部源码和数据集请点赞关注收藏后评论区留言私信~~~ 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的 间隔最大的线性分类器 ,间隔最大使它有别于感知机;SVM还包括 核技巧 ,这使它成为实质上的非线性分类器。SVM的的学

    2024年02月06日
    浏览(56)
  • 【postgresql 基础入门】数据表的创建,永久数据放普通表,中间结果放临时表,附带信用卡业务案例SQL设计

    ​ 专栏内容 : postgresql内核源码分析 手写数据库toadb 并发编程 ​ 开源贡献 : toadb开源库 个人主页 :我的主页 管理社区 :开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 入门准备 postgrersql基础架构 快速使用 初始化集群 数据库服务管理 psql客户

    2024年02月07日
    浏览(254)
  • 信用卡 3D 认证是怎么回事

    信用卡分为: 3D 和非 3D。 3D(3D: 3 domain)信用卡(10%, 集中在东南亚地区)); 非 3D(90%, 集中在欧美地区) 1.1.1. 什么是 3D 信用卡 卡组织为了保证交易的安全性为信用卡添加了密码验证。不同的卡组织为这服务的叫法都不相同: Visa: verified by visa service(VBV)。在 Mastercard: MasterCard secure cod

    2023年04月19日
    浏览(51)
  • 删除AWS绑定的信用卡账户

    前言 想使用aws的免费一年的ec2服务,所以必须先绑定信用卡,试了绑定储蓄卡还不行。绑定信用卡的时候只需要写卡号,卡片到期日期以及户头名即可。买上面的服务都不需要输入密码就可以购买。如果你用的免费服务,如果到期1年之后有其他费用,会悄无声息的扣款你的

    2024年02月12日
    浏览(63)
  • MATLAB朴素贝叶斯(德国信用卡案例)

    我们matlab建模课的案例 数据以及代码 链接:https://pan.baidu.com/s/18qpV2qsHzwbnOgZBMBHdGQ?pwd=r8g2  提取码:r8g2 参考书:MATLAB数学建模方法与实践(第三版)p63-p66 导入数据及分类 计算数据的x和y 例: 数据大小为1000x25 x = 1000 y =  25 最后一列为是否失约 原数据1代表失约 2代表未失约 例

    2024年02月06日
    浏览(112)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包