OpenCV图像处理-银行卡识别

本文介绍了使用OpenCV进行银行卡识别的过程,包括模板图像的处理(读取、灰度转换、二值化、轮廓提取),以及测试图像的处理(灰度处理、顶帽操作、边缘检测、闭运算和轮廓匹配),最终实现卡片号码的识别。
摘要由CSDN通过智能技术生成

1.整体代码

"""
=============================================
    Time     :
    Auther   :
    File     :
    Function : 银行卡识别
=============================================
"""
import cv2
import numpy as np

def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def sort(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]  # 用一个最小的矩形,把找到的形状包起来,然后对最小坐标进行排序
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
                                        key=lambda b:b[1][i], reverse=reverse))
    return cnts, boundingBoxes

# 1.读取模板
img = cv2.imread(r'F:\30_UndergraduateThesis\04_LearningOpencv\02BasicKnowledge\Card_template.png')
cv_show('number', img)
# 2.模板转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('gray', gray)
# 3.换为二值图像
ref, thre = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY_INV)
cv_show('ref', thre)
# 4.计算轮廓
refCnts, hierarchy = cv2.findContours(thre.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)  # 画轮廓,此处只画外轮廓,一共10个轮廓0~9
cv_show('imgLK', img)
refCnts = sort(refCnts, "left-to-right")[0]
digits = {}  # 用来存放模板数字对应的数字

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

    # 每个数字都有一个模板
    digits[i] = roi  # 0~9的数字模板对应

# 初始化卷积核,做形态学处理,核的大小可以自己定义,根据实际情况进行定义
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 读取原始图像,预处理
image = cv2.imread(r'F:\30_UndergraduateThesis\04_LearningOpencv\02BasicKnowledge\Card.png')
cv_show('card', image)
image = cv2.resize(image, (300, 200))
# 灰度处理
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show('gray', image_gray)
# 顶帽操作,突出明亮区域
tophat = cv2.morphologyEx(image_gray, cv2.MORPH_TOPHAT,rectKernel)
cv_show('tophat', tophat)
# 计算边界的梯度
gradX = cv2.Sobel(tophat, ddepth=-1, dx=1, dy=0, ksize=-1)

gradX = np.absolute(gradX)  # 取绝对值
(minVal, maxVal)=(np.min(gradX),np.max(gradX))
gradX = (255*((gradX-minVal)/(maxVal-minVal)))  # 归一化
gradX = gradX.astype("uint8")
cv_show('gradX', gradX)

# 执行闭操作,让图像信息成块出现
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show('gradX', gradX)

thresh = cv2.threshold(gradX,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]  # 阈值设为0是因为函数中设置了自动判断阈值,一般适用于双峰情况
cv_show('gradX_t',thresh)

# 再进行一次闭操作,让图像信息成团出现,补齐空白部分
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
conts, hiera = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cont = conts
curImag = image.copy()
tmp = cv2.drawContours(curImag, cont, -1, (0, 0, 255), 3)  # 在经过一系列处理后的图像中画出轮廓
locs = []

for(i, c) in enumerate(cont):
    (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))
locs = sorted(locs, key=lambda x:x[0])  # 将筛选之后的轮廓数据进行排序
output = []
for(i, (gx, gy, gw, gh)) in enumerate(locs):
    groupOuput=[]
    group = image_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]  # 再次对每个大框里面的数据进行二值化、测边界
    digitsCont, hieraD = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 再进行轮廓检测
    digitsCont = sort(digitsCont, method="left-to-right")[0]
    for c in digitsCont:  # 计算每个小框的值
        (x, y, w, h)=cv2.boundingRect(c)  # 做同样操作,画外接矩形然后模式匹配
        roi = group[y:y+h, x:x+w]
        roi = cv2.resize(roi, (57, 88))
        scores = []
        for (digit, digitROI) in digits.items():
            result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)  # 进行匹配,返回的最高值
            (_, score, _, _) = cv2.minMaxLoc(result)  # 做10次匹配,取最大值
            scores.append(score)
        groupOuput.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(groupOuput), (gx,gy-15),
                cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
    output.extend(groupOuput)
print("The Card's number is :{}", format("".join(output)))
cv_show('image_result', image)

2.整体思路

模板处理流程:

读取 -> 转换为灰度图 -> 转换为二值图像 -> 计算轮廓 -> 遍历每个轮廓,计算外接矩形 -> 存放

测试图像处理流程:

读取 -> 灰度处理 -> 顶帽操作,突出明亮区域 -> 梯度运算 -> 闭运算、二值化、闭运算 -> 轮廓检测 -> 遍历所有轮廓,得到想要的四组数字 -> 遍历四组数据,得出结果

3.效果展示

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值