栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python-openCV识别银行卡号,车牌同理,代码直接可用

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python-openCV识别银行卡号,车牌同理,代码直接可用

一、素材:

需要模板,输入模板必须带有所有的数字,且字体与识别的银行卡号一样

二、思路步骤:

首先把模板中的数字单个分离开,再提取银行卡上的ROI,再将两者的二值图像进行模板匹配,确定出每一个数字,即实现了银行卡号识别。

1、模板

(1)读取模板图像,将其转为灰度图,并且二值化。

(2)检测出模板图像中的数字轮廓;画出数字轮廓。

(3)将模板中的数字轮廓按照 x 方向的坐标大小进行排序,匹配对应的数字,并把轮廓定义为resize统一大小。

(4)将每个数字制成一个模板

2、银行卡

(1)读取银行卡图像,转为灰度图像;

(2)定义卷积核,通过顶帽操作——原图像与开操作之间的差值图像,突出明亮的区域;

(3)利用Sobel算子进行边缘检测

  (4)Sobel算子运算后的图像进行闭操作

(5)为提取出对应数字那几块区域,可以通过闭操作,连接数字,闭操作后的图像进行二值化(threshold);

(6)目标区域内部未填充完全,再通过闭操作连通区域;

(7)遍历轮廓,根据目标轮廓的特征,筛选出符合的轮廓;

(8)画出轮廓

(9)对轮廓进行筛选得出ROI(根据数字区域的W/H;以及图像大小范围)

(10)对ROI进行排序

(11)提取ROI中的每一位数字进行模板匹配,和模板中的数字进行模板匹配,选出最相近的数字图像;

3、上代码

import cv2
import  numpy as np
import imutils
from imutils import contours

filepath = 'D:\openCVImage\bankCard'

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

#处理模板
def temp_deal():
    # 读取模板图像
    tempImage=cv2.imread(filepath+'\temp.png')
    cv_show("temp",tempImage)
    # 转换灰度图,颜色改变函数
    tempGray = cv2.cvtColor(tempImage,cv2.COLOR_BGR2GRAY)
    # 二值化处理,图像阈值函数,像素值超过127变成0,否则变成255  反二值化,高亮突出数字
    ret,tempBinary=cv2.threshold(tempGray,127,255,cv2.THRESH_BINARY_INV)
    #image_Binary = cv2.threshold(image_Gray, 177, 255, cv2.THRESH_BINARY_INV)[1]   # 转换为二值化图像,[1]表示返回二值化图像,[0]表示返回阈值177
    cv_show("tempBinary",tempBinary)


    # 返回轮廓信息和轮廓层数
    contours,hierarchy = cv2.findContours(tempBinary.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 轮廓检测。第1个参数是二值图。第2个参数检测最外层轮廓,第3个参数保留轮廓终点坐标
    # 绘制轮廓
    drawTemp=tempImage.copy()# 复制一份原图像作为画板,不能在原图上画,不然原图会改变
    res=cv2.drawContours(drawTemp,contours,-1,(0,0,255),2)#"-1"是指在画板上画出所有轮廓信息,红色,线宽为2
    cv_show("drawTempImage",res)

    #模板轮廓排序
    #详细解释参考:使用Python和OpenCV对轮廓进行排序(从左到右,自上而下) 
    # 原理求每一个轮廓的外接矩形也就是轮廓拟合,根据返回的左上坐标点,就能判断出轮廓的位置,再排序
    # boxing中存放每次计算轮廓外接矩形得到的x、y、w、h,它的shape为(10,4)。cnt存放每一个轮廓
    #轮廓排序核心思想为先求出每个轮廓的外接矩形框,然后通过对外接框按照x或y坐标排序进⽽来实现对轮廓的排序.
    refCnts = imutils.contours.sort_contours(contours, method="left-to-right")[0]    # 排序,从左到右,从上到下
    digits = {}
    #遍历每一个轮廓
    for(i,c) in enumerate(refCnts): #返回轮廓下标和对应的轮廓值
        # 计算外接矩形并且resize成合适大小
        (x,y,w,h) = cv2.boundingRect(c)# 轮廓拟合,中存放的是每个轮廓1 2 3 。。。。的最小矩形信息
        roi = tempBinary[y:y+h,x:x+w]# tempBinary中依次保存的是高和宽,即(y,x)
        # 将每个区域对应一个数字
        roi = cv2.resize(roi,(55,85))# roi区域统一大小,根据自己需求来定
        digits[i] = roi
    return digits

 

#处理待识别银行卡图片
def bankCard_deal(digits):
    # 初始化卷积核
    rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,3))
    myKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

    img = cv2.imread(filepath+"\card2.png")
    cv_show("img", img)
    img = imutils.resize(img, width=300)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 礼帽操作,突出更明亮的区域
    tophat=cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
    cv_show("tophat",tophat)

    #利用Sobel算子进行边缘检测
    gradX=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)
    gradY = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)
    gradX=np.absolute(gradX)
    minVal = np.min(gradX)
    maxVal = 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("gradXclose",gradX)


    thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    cv_show('threshImg', thresh)
    # 再来一个闭操作
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, myKernel)
    cv_show('gradXclose2', thresh)

    # 计算轮廓
    threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = threshCnts
    cur_img = img.copy()
    cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 2)
    cv_show('imgCopy', cur_img)

    locs = []

    # 遍历轮廓,提取轮廓,需要尝试
    for (i, c) in enumerate(cnts):
        # 计算矩形
        (x, y, w, h) = cv2.boundingRect(c)
        ar = w / float(h)
        # 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
        # [(454, 213, 110, 29), (308, 211, 109, 31), (171, 211, 98, 31), (18, 211, 107, 31)]
        if 2.5 < ar < 5.0:
            if (40 < w < 85) and (10 < h < 20):
                # 符合的留下来
                locs.append((x, y, w, h))
                #res = cv2.rectangle(img.copy(), (x, y), (x + w, y + h), (0, 0, 255), 2)  # "-1"是指在画板上画出所有轮廓信息,红色,线宽为2
                #cv_show("imgRect", res)

    # 将符合的轮廓从左到右排序
    locs = sorted(locs, key=lambda o: o[0])
    output = []

    #四组轮廓
    for(i,(gx,gy,gw,gh)) in enumerate(locs ):
        groupOutput=[]
        group=gray[gy-5:gy+gh+5,gx-5:gx+gw+5]
        group=cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
        cv_show("groupThreshold",group)#1234;5678;
        digitCnts,his=cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#提取轮廓内数字1,2,3,4
        digitCnts = imutils.contours.sort_contours(digitCnts, method="left-to-right")[0] # 对找到的轮廓进行排序  按照X轴坐标
        # 计算每一组中的每一个数值
        for c in  digitCnts:#每组数字1,2,3,4
            # 找到当前数值的轮廓,resize成合适的大小
            (x,y,w,h)=cv2.boundingRect(c)#具体数字
            roi = group[y:y + h, x:x + w]  # 数字在每组group中的坐标
            # 将每个区域对应一个数字
            roi = cv2.resize(roi, (22, 44))  # roi区域统一大小,根据自己需求来定
            print("roi",roi)
            scores = []
            for (digitKey,digitROIValue) in digits.items():#识别图的roi数字与模板里每个数字matchTemplate
                result=cv2.matchTemplate(roi,digitROIValue,cv2.TM_CCOEFF_NORMED)
                # 返回最值及最值位置,在这里我们需要的是最小值的得分,不同的匹配度计算方法的选择不同
                min_val, max_val, min_loc, max_loc = cv2.minMaxLoc (result)
                scores.append(max_val)#最大值
            score = np.abs(scores)  # 有负数出现,统一成正数,相关系数都变成正数
            flag=False
            for val in score:
                if val>0.9:
                    flag=True
                    break
            if !flag:
                best_index = np.argmax(score)  # score最大值的下标,匹配度最高
                best_value = str(best_index)  # 下标就是对应的数字,在字典中,key是0对应的是值为0的图片
                groupOutput.append(best_value)
        cv2.rectangle(img,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)
        # 在矩形框上绘图
        cv2.putText(img, ''.join(groupOutput), (gx, gy - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
        output.append(groupOutput)
    cv_show('img',img)
    print('数字为:',output)

 

 

 

 

如有疑问,欢迎进群学习交流 856044792

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/858778.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号