本文主要介绍通过OpenCV- python实现简单的银行卡卡号识别的思路和具体实现过程。

目录

知识准备

项目概述

实现过程

代码讲解

1.自定义函数

2.模版读入与预处理

3.银行卡读入与形态学操作

4. 卡号筛选与ROI切割

5.模版匹配,得出结果

结语


知识准备

该过程需要用到以下知识:

1.OpenCV图像基础操作,如读取,灰度转换,改变大小等

2.阈值操作,如二值化

3.轮廓检测以及boundingBox构建

4.卷积核构建

5.Sobel算子求梯度,梯度融合

6.形态学操作,如tophat,close操作

7.machTemplate模版匹配

8.用pyplot查看图片,便于debug

项目概述

本项目旨在综合运用OpenCV的各种方法实现对银行卡卡号的自动识别。

主要原理基于模版匹配,故需要提供与银行卡数字字体相同的数字模版作为参照。

实现过程

1.读入模版图片,识别边框,取出各个数字作为参考项。

2.读入银行卡图片,进行形态学操作,识别边框,筛选数字区域。

3.将银行卡的卡号数字割出来,与模版比较,选出相似度最高的答案。

代码讲解

1.自定义函数

import cv2
import matplotlib.pyplot as pltdef read(img, thresh=127, inv=False):origin = cv2.imread(img)gray = cv2.imread(img, 0)binary = cv2.threshold(gray, thresh, 255, cv2.THRESH_BINARY_INV if inv else cv2.THRESH_BINARY)[1]return origin, gray, binarydef unify_size(img_list):outputlist = []xsize, ysize = img_list[0].shapefor img in img_list:outputlist.append(cv2.resize(img, (ysize, xsize)))return outputlist

在本项目中,笔者自定义了两个函数。read()实现了传入一个图片文件名,返回其原图,灰度图以及二值化处理后的结果。unify_size()实现了传入一个由图片构成的列表,对列表中所有元素按照列表第一个图片的大小进行大小统一。

2.模版读入与预处理

template_bgr, template_gray, template_bin = read('template.png', inv=True)
contours, hier = cv2.findContours(template_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
rectangles = []
for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)rectangles.append([x, y, w, h])
rectangles.sort(key=lambda rect: rect[0])
num_template = []
for [x, y, w, h] in rectangles:num_template.append(template_bin[y:y + h, x:x + w])
num_template = unify_size(num_template)

在本段代码中,首先调用自定义的read()方法返回了模版的bgr格式,灰度和二值化(反向)后的结果。然后调用findContours方法识别了模版图片中的所有外边界,储存在contours列表中。在循环中遍历所有外边框,将每个边框的x,y,w,h存储在rectangles列表中,并对其按照从左到右排序,使得下标和数字一一对应。最后截取每个ROI,储存在num_template列表中,并进行大小的统一。

3.银行卡读入与形态学操作

# 读入
idcard_bgr, idcard_gray, idcard_bin = read('1.png', 127)
# 构建三个将来会用到的卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 5))
rectKernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (18, 7))
basicKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 改变大小
idcard_bgr, idcard_gray, idcard_bin = cv2.resize(idcard_bgr, (583, 368)), cv2.resize(idcard_gray,(583, 368)), cv2.resize(idcard_bin,(583, 368))
# 顶帽操作
idcard_gray_tophat = cv2.morphologyEx(idcard_gray, cv2.MORPH_TOPHAT, rectKernel)
plt.imshow(idcard_gray_tophat)
plt.show()
# 梯度计算
gradX = cv2.convertScaleAbs(cv2.Sobel(idcard_gray_tophat, cv2.CV_64F, 1, 0, ksize=3))
gradY = cv2.convertScaleAbs(cv2.Sobel(idcard_gray_tophat, cv2.CV_64F, 0, 1, ksize=3))
grad = cv2.addWeighted(gradX, 0.5, gradY, 0.5, 0)
plt.imshow(grad)
plt.show()
# 闭操作
grad_close = cv2.morphologyEx(grad, cv2.MORPH_CLOSE, rectKernel)
plt.imshow(grad_close)
plt.show()
# 自适应阈值二值化
close_autobin = cv2.threshold(grad_close, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
plt.imshow(close_autobin)
plt.show()
# 闭操作
close2 = cv2.morphologyEx(close_autobin, cv2.MORPH_CLOSE, rectKernel2)
plt.imshow(close2)
plt.show()

这段代码对读入的银行卡图片进行了多次形态学操作,其输出如下:

tophat

tophat操作将图片中的反差较大的信息提取了出来。

grad

梯度操作在tophat的基础上描出了梯度变化较大的部分。

第一次闭操作

闭操作将梯度轮廓进行了粘连。

二值化

第二次闭操作

进一步粘连二值化后的结果,使四个号码成块出现。

需要注意的是,实现上述效果的具体途径不是唯一的,各种操作综合运用是关键所在。在上面给出的例子中,经过反复调整,笔者发现,卷积核大小的设置是至关重要的,卷积核过小的话,进行闭操作无法将数字连在一起,分离的数字不利于下一步的筛选;而卷积核设置过大的话,数字可能会和其他色块粘连在一起,无法通过下一步的像素宽高比和色块大小进行筛选出来,导致特征丢失。

4. 卡号筛选与ROI切割

# 找边界
contours, hier = cv2.findContours(close2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
boundingBoxes = []
# 按照宽高比和像素范围筛选数字组
for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)ar = w / float(h)if 2.6 < ar < 3.8 and 70 < w < 115 and 15 < h < 45:boundingBoxes.append([x, y, w, h])
boundingBoxes.sort(key=lambda box: box[0])
group = []
# ROI
for [x, y, w, h] in boundingBoxes:group.append(idcard_gray[y - 5:y + h + 5, x - 5:x + w + 5])plt.imshow(idcard_gray[y - 5:y + h + 5, x - 5:x + w + 5])plt.show()
group_binary = []
# 对数字组进行形态学操作
for nominee in group:nominee_bin = cv2.threshold(nominee, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]nominee_close = cv2.morphologyEx(nominee_bin, cv2.MORPH_CLOSE, basicKernel)group_binary.append(nominee_close)plt.imshow(cv2.threshold(nominee, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1])plt.show()
num_nominee = []
# 对数字组找边界
for nominee in group_binary:contours, hier = cv2.findContours(nominee, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)rectangles = []for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)rectangles.append([x, y, w, h])rectangles.sort(key=lambda rect: rect[0])# ROI切割出单个数字for [x, y, w, h] in rectangles:if w > 8 and h > 20:num_nominee.append(nominee[y:y + h, x:x + w])plt.imshow(nominee[y:y + h, x:x + w])plt.show()

输出如下:

数字组ROI

形态学操作后

单个数字ROI

本节代码中要注意几点:

1.按照二次闭操作后的结果找到原图的边界后,需要对边界进行筛选,这里按照边界外接矩形的宽高比和像素大小进行筛选,这里的范围自行确定,只要避免错选和漏选。

2.第一次ROI切割要保留几个像素的切割余量。

3.对数字组ROI二值化后又进行闭操作是为了防止单个数字的笔画没有连起来。

4.对单个数字的筛选同1。

5.要注意对轮廓外矩形排序后提取ROI。

5.模版匹配,得出结果

num_nominee = unify_size(num_nominee)
num_standard = []
(x, y) = num_nominee[0].shape
for i in range(len(num_template)):num_standard.append(cv2.resize(num_template[i], (y, x)))
ans = []
for nominee in num_nominee:score = []for standard in num_standard:res = cv2.matchTemplate(nominee, standard, cv2.TM_SQDIFF_NORMED)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)score.append(min_val)ans.append(score.index(min(score)))
print(ans)

首先对模版数字和待匹配数字大小统一化。

外循环遍历待匹配数字,内循环将其与10个模版匹配并打分,这里笔者采用了TM_SQDIFF_NORMED模式,分数越低,相似度越高。然后获取最低分对应的数组下标作为结果输出。

结语

实现这样一个OCR的效果并不难,主要是对OpenCV基础函数的综合运用。本文提到的方法还有大量的改进空间,还存在很大的局限性。

OpenCV OCR实战:卡号识别相关推荐

  1. OpenCv NDK 银行卡/身份证号识别(3) 银行卡/身份证图像处理和卡号区域剪切

    通过前两篇我们已经对Opencv有所了解了,接下来就要真正的来处理我们的图像,然后把卡号给提取出来.首先我们先简单分析以下银行卡然后把处理流程列出来: 由上图我们很容易知道既然我们要找到卡号,银行卡的 ...

  2. Opencv项目实战-信用卡数字识别

    Opencv项目实战:信用卡数字识别 导入库,定义展示函数 import cv2 import numpy as np from imutils import contours import myut ...

  3. mysql通过卡号识别银行_Java 根据银行卡号获取银行名称以及图标

    转 https://blog.csdn.net/N_007/article/details/78835526 一.支付宝接口获取名称 根据 卡号 获取 银行信息 接口 https://ccdcapi. ...

  4. Java使用OpenCV和Tesseract-OCR实现银行卡图片处理与卡号识别

    直接上代码,代码每一步都是解释与插图,一步步实现,如果不清楚opencv的环境如何搭建,可上网查或者参见我的前几篇博客,不多说了, java代码如下: package com.zmx.opencvte ...

  5. OpenCV OCR实战 文档扫描与文字检测

    本文讲述使用OpenCV- python以及easyocr库实现文档扫描与文字检测的思路和具体实现过程. 目录 知识准备 项目概述 实现过程 代码讲解 1.读入图片并进行预处理(灰度转换,高斯滤波) ...

  6. Opencv项目实战之信用卡识别

    任务要求 学了这么久opencv,不做个实战项目怎么行(手动狗头)

  7. openCV+Python实战练习——银行卡号识别

    目录 项目Introduce: 项目名称: 具体操作步骤以及代码: 实现结果展示: 代码整体展示: 项目Introduce: 项目名称: 通过导入模板数字,对银行卡面上的数字进行识别,提取出银行卡面上 ...

  8. 文本的检测、识别实战:使用 Tesseract 进行 OpenCV OCR 和文本识别

    在本篇文章中,我们将使用 OpenCV.Python 和 Tesseract 执行 (1) 文本检测和 (2) 文本识别. 上篇文章,我向您展示了如何使用 OpenCV 的 EAST 深度学习模型执行 ...

  9. python opencv 文字识别_文本识别 使用 Tesseract 进行 OpenCV OCR 和 文本识别

    文本识别 用 Tesseract 进行 OpenCV OCR 和 文本识 在本教程中,您将学习如何应用OpenCV OCR(光学字符识别).我们将使用OpenCV,Python和Tesseract 执 ...

最新文章

  1. IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期
  2. 详解django三种文件下载方式
  3. 简述力法计算弹性固定无铰拱的原理_《隧道结构体系设计》PPT课件.ppt
  4. 解决jsp两种提交方式乱码 的方法
  5. Disqus API 用法 How to get your Disqus API keys
  6. [BZOJ3676][Apio2014]回文串
  7. 史上最全的php面试题-带有答案,史上最全的PHP面试题-带有答案
  8. MSCRM4.0删除Money类型属性可能引起的问题
  9. opera官方教程 预订一
  10. nginx中upstream的max_conns属性使用
  11. sigmoid画图_博弈画图软件(Window版和MAC版)
  12. mac 思科 链路聚合_思科链路聚合协议实验.docx
  13. 联想硬盘保护系统 计算机名 后缀,联想硬盘保护7.07.6安装及计算机名相同的解决方法...
  14. C语言扑克牌洗牌发牌代码
  15. fit into用法
  16. Jsonviewer2 for Notepad++ 64 bit
  17. linux 获取文件父目录权限,Linux 文件权限中,操作一个文件需要父目录的那些权限?...
  18. Swift游戏实战-跑酷熊猫 07 平台的移动
  19. 数据驱动的瑞幸咖啡未来会能赚!
  20. 数据库原理——关系模式的范式的简明判断

热门文章

  1. 君智咨询:从飞贷看传统企业如何转型移动互联网
  2. 大厂对话系统实践文章链接
  3. amd显卡linux命令,在deepin系统动态切换intel+amd笔记本显卡运行应用的方法
  4. ExtAspNet v3.1.4
  5. 【Android studio】将字体设为斜体/加粗
  6. 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 1
  7. AC-DC数字稳压电源设计与仿真+Multisim仿真
  8. 视频会议系统为政府需要
  9. 微信公众平台多客服系统怎么使用?
  10. 制作了一个 远程工作职位的 rss 聚合,有需要的订阅,有好的网站欢迎推荐