Opencv项目实战:信用卡数字识别

导入库,定义展示函数

import cv2
import numpy as np
from imutils import contours
import myutils # 自定义的库def img_show(img, name):cv2.imshow('name', img)cv2.waitKey(0)cv2.destroyAllWindows()

读取模板图片,进行轮廓检测。

而轮廓检测cv2.findContours()接收是二值图像,所以先对模板进行灰度和二值处理,由于原图像是白底黑图,所以进行反二值处理为黑底白图。

# 读取数字图片
number = cv2.imread('./images/ocr_a_reference.png')
# 转换为灰度图片 色彩空间转换
number_gray = cv2.cvtColor(number, cv2.COLOR_BGR2GRAY)
# 转化为二值图像 图像阈值处理
# 其返回值为两个,【0】表示返回阈值 【1】表示返回图像
number_gray = cv2.threshold(number_gray, 10, 255, cv2.THRESH_BINARY_INV)[1]


轮廓检测

外轮廓,并绘出轮廓

# 轮廓检测 外轮廓
# 新版本opencv只有两个返回值,分别是轮廓和轮廓的层次信息
refCnts, hierarchy = cv2.findContours(number_gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
# 参数:图像,轮廓,边缘索引,颜色,厚度
cv2.drawContours(number, refCnts, -1, (0, 0, 255), 3)  # -1表示绘出所有轮廓

轮廓进行排序

应用自定义库myutils对绘出的轮廓进行排序

def 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 = 1# 用一个最小的矩形,把找到的形状包起来x,y,h,w对外接矩形取左上点的横坐标,通过对横坐标的排序即可实现对数字的排序# boundingBoxes是一个由元组构成的列表,其中每个元组包含x、y、h、w四个值boundingBoxes = [cv2.boundingRect(c) for c in cnts]  # zip[iterable,...]函数返回一个以元组为元素的列表,zip()和*操作符一起操作可以用来unzip(分解)一个列表为多个元组# zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse)这里首先将cnts, boundingBoxes合成# 为(cnts, (x, y, w, h))又根据自定义函数lambada函数提取b[1]=(x, y, w, h)根据i值确定x,y值排序,最后zip(*)拆分# 返回cnts和boundingBoxes值(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes)key=lambda b: b[1][i], reverse=reverse))  # 使用其X进行判断return cnts, boundingBoxes  # 返回值为排序完的轮廓# 排序从左到右,从上到下,根据method,则轮廓为根据x值升序进行排序
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]

定义一个空字典进行模板匹配

digits={}

对轮廓进行遍历

得到(x, y, w, h)值做外接矩形,并将外接矩形轮廓加入到字典中,其字典的key就是轮廓所代表的值

# 遍历每一个轮廓
for i, c in enumerate(refCnts):# 计算外界矩形并relize的合适大小(x, y, w, h) = cv2.boundingRect(c)roi = number_gray[y: y+h, x: x+w]roi = cv2.resize(roi, [57, 88])# 每一个数字对应一个模板digits[i] = roi

定义形态学操作所需要的卷积核

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

读取信用卡图片

引用myutils中的函数缩小尺寸,并进行灰度处理

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 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)return resized# 读取信用卡图像
card_01 = cv2.imread('./images/credit_card_01.png')
card_01 = myutils.resize(card_01, width=300)
card_01_gray = cv2.cvtColor(card_01, cv2.COLOR_BGR2GRAY)

礼帽操作

对图像进行礼帽操作(原始图像-(开运算结果(先腐蚀后膨胀))),作用:获得图像的噪声信息或者比原始图像边缘更亮的边缘部分。

# 礼帽操作 突出更明亮的区域(白色部分)
card_tophat = cv2.morphologyEx(card_01_gray, cv2.MORPH_TOPHAT, ntKernel)

Sobel算子

进行Sobel算子进行梯度运算,对噪声具有平滑作用,能很好的消除噪声的影响。

gradX = cv2.Sobel(card_tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradX = np.absolute(gradX)  # 绝对值
# 将边界归一化处理,看的更清楚
minVal, maxVal = np.min(gradX), np.max(gradX)
gradX = 255 * (gradX - minVal) / (maxVal - minVal)
#转化为8位无符号数
gradX = gradX.astype('uint8')

闭操作

进行闭操作(先膨胀在腐蚀),可以填充白色物体内细小黑色空洞的区域、连接临近物体

# 填充白色区域内细小黑色空洞的区域, 将数字连在一起,形成白色块状
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, ntKernel)

二值化处理

二值化处理,将两种主题明显分隔开,用THRESH_OTSU自动做判断

# THRESH_OTSU自动寻找合适的阈值, 需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

闭操作

图像中白色块内有出先黑色空洞,再次使用闭操作填充黑色空洞部分

# 在执行一个闭操作,白色填充黑色区域
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, ffKernel)
img_show(gradX, "gradx")

轮廓检测, 绘制轮廓

# 绘制轮廓
threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = threshCnts
cur_img = card_01.copy()
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)

过滤轮廓

选出需要的4个数字轮廓,并定义空列表添加所需轮廓

locs = []
# 遍历轮廓
for i, c in enumerate(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))
print(len(locs))  # 数量为4
# 通过轮廓的x值从左到右排序(升序)
locs = sorted(locs, key=lambda x: x[0])

得到每一个轮廓

先定义一个空列表output = []储存信用卡的数字

遍历locs列表里4个轮廓的每一个轮廓,对每一个轮廓的图像进行,轮廓检测与排序,从而的每一个轮廓中每一个数字的轮廓

for (i, (gx, gy, gw, gh)) in enumerate(locs):group_out = []# 往外扩展group = card_01_gray[gy - 5: gy + gh + 5, gx - 5: gx + gw + 5]# img_show(group, 'group')# 轮廓检测找到每一个小轮廓group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]# 得到每一个数字的轮廓digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 排序从左到右digitCnts = contours.sort_contours(digitCnts, method="left to right")[0]

阈值处理得到的每一个轮廓图像




得到每一个数字

遍历每一个轮廓中的数字

for (i, (gx, gy, gw, gh)) in enumerate(locs):passfor c in digitCnts:# 得到每一个数字的轮廓值(x, y, w, h) = cv2.boundingRect(c)# 提取每个数字图像roi = group[y:y + h, x:x + w]roi = cv2.resize(roi, (57, 88))  # 获得每个数字的轮廓并将其resize为和模板一样大小的图片以便于模式匹配

模板匹配

将信用卡得到的数字图像与模板数字图像进行模板匹配

for (i, (gx, gy, gw, gh)) in enumerate(locs):passfor c in digitCnts:pass# 计算匹配得分scores = []# 在匹配中计算每一个得分for (digit, digitROI) in digits.items():# 模板匹配, 得到匹配程度result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)# 取最大值为完全匹配# (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(result)(_, score, _, _) = cv2.minMaxLoc(result)# 每一个轮廓匹配的最大值加入scores列表scores.append(score)# np.argmax(a)这个函数是返回a中最大值的索引group_out.append(str(np.argmax(scores)))cv2.rectangle(card_01, (gx - 5, gy - 5), (gx + gw + 5, gy + gh + 5), (0, 0, 255), 1)# "str".join(item) str表示字符串(字符),item表示一个成员,注意括号里必须只能有一个成员# 得到item的每一个成员以str字符分隔在拼成一个字符串cv2.putText(card_01, "".join(group_out), (gx, gy - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)# 得到结果output.extend(group_out)

这里由于result是与模板里的数字轮廓相匹配的程度,而其模板图片中轮廓所代表的值与scores的索引相同,顺序都为【0-9】,转换为字符即为正确数字。然后绘出矩形和数字在图像中即可完成。

结果

最后打印输出结果。

print('Card number :{}'.format("".join(output)))
img_show(card_01, 'card_01')

others:


Opencv项目实战-信用卡数字识别相关推荐

  1. AttributeError: module ‘myutils‘ has no attribute ‘sort_contours‘,项目实战-信用卡数字识别--pychram如何配置相应的参数

    1,打开pycharm软件 2,新建一个.py文件(注意:不要出现中文名) 3,配置: (1)点击file (2)点击 settings- (3)点击 4,配置参数 右键点击自己新建的python文件 ...

  2. OpenCV实践小项目(一): 信用卡数字识别

    1. 写在前面 今天整理一个OpenCV实践的小项目, 前几天整理了一篇OpenCV处理图像的知识笔记,后面,就通过一些小项目把这些知识运用到实践中去,一个是加深理解,另一个是融会贯通,连成整体,因为 ...

  3. opencv项目实战信用卡的检测

    第一步先梳理一下我们的项目逻辑: 一. 找素材 (数字模板,银行卡照片等) 二. 识别数字则需要我们对数字模板进行处理.因此下面我们开始处理数字模板. 1.将数字模板处理成灰度图,再进行二值处理.这样 ...

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

    一.pycharm实现参数配置 直接运行程序会报错: usage: ocr_template_match.py [-h] -i IMAGE -t TEMPLATE ocr_template_match ...

  5. (八)OpenCV入门,代码练习,详细注释【信用卡数字识别】【240行】【原创】

    文章目录 信用卡图片 数字模板图片 一.数字模板图片处理步骤 1,读取模板图片 2,灰度处理图片 3,二值化处理图片 4,检测数字轮廓图片 二.识别信用卡图片处理步骤 1,图片信用卡 2,图片灰度处理 ...

  6. 信用卡数字识别—opencv

    信用卡数字识别:就是识别信用卡的卡号,然后将卡号打印出来! 然后对应的数字模板如下图所示: 接下来我们就一步步的分析程序吧 1.导入相关的包 # 导入工具包 from imutils import c ...

  7. python信用卡客户_Python开发之基于模板匹配的信用卡数字识别功能

    环境介绍 python 3.6 + OpenCV 3.4.1.15 原理介绍 首先,提取出模板中每一个数字的轮廓,再对信用卡图像进行处理,提取其中的数字部分,将该部分数字与模板进行匹配,即可得到结果. ...

  8. Opencv项目实战:14 手势控制音量

    目录 0.项目介绍 1.项目展示 2.项目搭建 3.项目的代码与讲解 4.项目资源 5.项目总结 0.项目介绍 本篇与上一篇有很多联系,大家可以看看这篇Opencv项目实战:13 手部追踪,我们将根据 ...

  9. 【Opencv项目实战】背景替换:动态背景移除与替换(cvzone+MediaPipe)

    文章目录 一.项目思路 二.环境布置 2.1.cvzone安装 2.2.MediaPipe安装 2.3.常见问题 2.4.注意事项 三.算法详解 3.1.segmentor.removeBG():去除 ...

最新文章

  1. MFC中“资源在另一个编译器中打开”报错解决方法
  2. java 操作系统 模拟 daima_求C/C++或java写的比较简单的操作系统的模拟程序
  3. iis里面的mime没有php扩展,IIS - 无后缀(无扩展名)的MIME类型配置
  4. 深入了解java虚拟机(JVM) 第六章 垃圾回收算法
  5. 程序员的自我修养(2)——计算机网络(转) good
  6. 动态切换view视图viewflipper组件
  7. 2021年中国超声波织物切割机市场趋势报告、技术动态创新及2027年市场预测
  8. uniapp app或小程序跳转h5链接
  9. matlab求一个矩阵的逆矩阵的命令,如何用MATLAB求逆矩阵
  10. A Primer on Memory Consistency and Cache Coherence—第五章 Relaxed Memory Model
  11. python职位要求_python 开发工程师职位描述与岗位职责任职要求
  12. 5号字对应的数字字号_五号字体是多少磅的?
  13. geforce experience出现错误尝试重启PC
  14. 颜色拾取器和红蜻蜓截图
  15. ROS turtlebot_follower :让机器人跟随我们移动
  16. 能够做到亚马逊月销售额50w以上的运营,他们有什么共同点 和技巧
  17. linux面试大全最新
  18. 三种常见mq的优缺点比较
  19. 如何提高职场说服力?这本说服力书籍你值得拥有!
  20. 2014-04-25

热门文章

  1. js截取某个字段后面的字符串
  2. 杭州旅游1-2日最佳路线
  3. Java中关于length和length()的问题小结
  4. JAVA从入门到进阶(九)——集合类框架基础一
  5. Word计算机与网络应用原题,计算机应用基础考试试题附答案
  6. 微信小程序引用外部字体
  7. java高级编程之IO流
  8. 2、TWS API接口的使用说明
  9. Inno Setup软件 打包多个安装包程序
  10. 快手年终奖25个月,背后故事你们知道吗?