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
import  cv2
import numpy as np
import myutils
from imutils import contours
def cv_show(str,thing):
cv2.imshow(str, thing)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 指定信用卡类型
FIRST_NUMBER = {
"": "American Express",
"": "Visa",
"": "MasterCard",
"": "Discover Card"
}
img=cv2.imread("D:\images\ocr_a_reference.png")
# 灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#二值化
ref=cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
cv_show("img_ref",ref)
# 计算轮廓
#cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓
ref_,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)
print (np.array(refCnts).shape)
refCnts = myutils.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
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) #读取输入图像,预处理
image = cv2.imread("D:\images\credit_card_01.png")
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)
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) # 计算轮廓 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)
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])
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 Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)

下面样图适用

基于opencv -python--银行卡识别的更多相关文章

  1. 基于 OpenCV 的人脸识别

    基于 OpenCV 的人脸识别 一点背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenC ...

  2. 【计算机视觉】基于OpenCV的人脸识别

    一点背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从 ...

  3. java基于OpenCV的人脸识别

    基于Java简单的人脸和人眼识别程序 使用这个程序之前必须先安装配置OpenCV详细教程见:https://www.cnblogs.com/prodigal-son/p/12768948.html 注 ...

  4. 基于opencv+python的二维码识别

    花了2天时间终于把二维码识别做出来了,不过效果一般,后面会应用在ROS辅助定位上,废话少说先上图: 具体过程参考了这位大神的博客:http://blog.csdn.net/qq_25491201/ar ...

  5. python基于OpenCV的人脸识别系统

    想获得所有的代码,请下载(来自我的CSDN): https://download.csdn.net/download/qq_40875849/11292912 主函数: from recognitio ...

  6. 使用Python基于OpenCV的验证码识别

    Blog:https://blog.csdn.net/qq_40962368/article/details/89312429(Verification_Code_Identification) 步骤 ...

  7. 基于opencv的车牌识别系统

    前言 学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程. 概述     OpenCV的全称是:Open Source Computer Vision ...

  8. OpenCV+python 人脸识别

    首先给大家推荐一本书:机器学习算法原理与编程实践 本文内容全部转载于书中,相当于一个读书笔记了吧 绪论 1992年麻省理工学院通过实验对比了基于结构特征的方法与基于模版匹配的方法,发现模版匹配的方法要 ...

  9. 基于OpenCV的人脸识别[iOS开发笔记(2)]

    开始了OpenCV的试水工作了... 1.Get ready 在OpenCV中我们会使用函数cv::CascadeClassifier 来进行人脸检测.但是在使用本函数之前我们需要添加一个XML文件对 ...

  10. 基于opencv的人脸识别程序

    1. 解析opencv自带人脸识别源码(……/opencv-3.1.0/samples/cpp/facedetect.cpp) @ 操作系统:Ubuntu 15.04 OpenCV版本:3.1.0 # ...

随机推荐

  1. 《漫画ERP》经典文章摘抄

    1.对企业来说,应用ERP的价值就在于通过系统的计划和控制功能,结合企业的流程优化,有效的配置各项资源,以加快对市场的响应,降低成本,提高效率和效益,从而提升企业的竞争力:

  2. 1w+的心路历程

    鬼知道我是如何坚持下来的,如果非要找个理由,那或许是所谓的热爱. 公众号转眼间写了三年.写的内容围绕着安卓技术,源码剖析,生活感悟,职场人生. 很庆幸的是,得到大家的支持,每一条留言都会是一次交流,看 ...

  3. Linux下快速手动产生core文件

    原文链接:https://blog.csdn.net/jctian000/article/details/79695006 当我们配置好自动生成core文件的环境后,若不想写导致崩溃的程序验证,那要怎 ...

  4. APP 安全测试点概述

    一.安装包测试 1.1 关于反编译   目的是为了保护公司的知识产权和安全方面的考虑等,一些程序开发人员会在源码中硬编码一些敏感信息,如密码.而且若程序内部一些设计欠佳的逻辑,也可能隐含漏洞,一旦源码 ...

  5. HttpRunner学习1--Windows&Linux安装httprunner

    最近在学习HttpRunner,这是一款开源的接口测试框架,可用于HTTP(S)协议的接口测试.通过该框架,我们只需维护一份 YAML/JSON 脚本,即可轻松的进行接口自动化. 更多的介绍,大家可以 ...

  6. MongoDB(四):数据类型、插入文档、查询文档

    1. 数据类型 MongoDB支持许多数据类型. 字符串 - 这是用于存储数据的最常用的数据类型.MongoDB中的字符串必须为UTF-8. 整型 - 此类型用于存储数值. 整数可以是32位或64位, ...

  7. jQuery随笔记录

            DOM遍历 parent()方法返回所选元素的直接父元素.(parent() 只能遍历单个级别的 DOM树) parents()方法获取所选元素的所有祖先 children()所选元素 ...

  8. node error SOCKET error:10106

    上周我的node.js command prompt出错了,什么也干不了 SOCKET error:10106 纠结两天,终于搞定了,其实比较简单,就是不会弄起来好麻烦 参考: 作者:忆常  url: ...

  9. CentOS7 如何升级Git

    CentOS7自带的git版本1.8.3.1,这个版本有点低了.于是决定折腾升级,我首先想到的是用update更新: yum update git 结果,事与原违,还是1.8.3.1.在网上提供的升级 ...

  10. JavaScript-----12.对象

    1. 对象 万物皆对象,但是对象必须是一个具体的事物.例如:"明星"不是对象,"周星驰"是对象:"苹果"不是对象"这个苹果&quo ...