python opencv 银行卡号识别

项目简介:

本次项目使用python中的opencv库对银行卡进行形态学操作和模板匹配,最终提取出银行卡号。

数据准备:

进行模板匹配所用数据

 进行训练所用的银行卡

 正文:

1.导入第三方库

import cv2 as cv
import numpy as np

2.自定义函数

def show_photo(photo,title='title',waitTime=0):
    # 展示图片
    cv.imshow(title,photo)
    cv.waitKey(waitTime)
    
def sort_inv(boxs):
    # 数组排序
    # 从小到大
    boxs_sort = []

    contour_index = list(map(lambda x:x[0],boxs))
    for i in np.argsort(contour_index):
        boxs_sort.append(boxs[i])
        
    return boxs_sort

函数说明:

show_photo()函数主要用于便捷展示图片,非必须。

sort_inyov()函数用于数组之间的排序。程序在寻找轮廓时,优先寻找右下角,而我们的思维惯性是以左上角优先,所以此处构造sort_inyov()函数,非必须。

3.制作特征模板

# 制作特征字典
photo = cv.imread('all_num.png')
photo_gray = cv.cvtColor(photo,cv.COLOR_BGR2GRAY)
_,photo_2 = cv.threshold(photo_gray,175,255,cv.THRESH_BINARY_INV)

contours,his = cv.findContours(photo_2,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_NONE)

boxs = []
for contour in contours:
    boxs.append(cv.boundingRect(contour))

boxs_sort = sort_inv(boxs)

# 得到的特征字典
dict_temp = dict(zip([i for i in range(10)],boxs_sort))

代码说明:

此处代码将特征转换为模板,dict_temp中储存的是all_num图片排序后的特征。

key为特征代表的数字,value为特征在原始图像中的x,y,w,h。

4.寻找到银行卡号所在区域

# 读图,并固定照片尺寸
photo_card = cv.resize(cv.imread('card_1.png'),(580,360))

# 转灰度
photo_card_gray = cv.cvtColor(photo_card,cv.COLOR_BGR2GRAY)

# 二值化| 自适应阈值
_,binary = cv.threshold(photo_card_gray,0,255,cv.THRESH_BINARY+ cv. THRESH_OTSU)

# 边缘提取
img_canny = cv.Canny(binary,100,200)


# 凸显数字区域
kernel = cv.getStructuringElement(cv.MORPH_RECT,(9,5)) 

dilation = cv.dilate(img_canny,kernel,iterations=3)    
erosion = cv.erode(dilation,kernel,iterations=3)

show_photo(erosion)

 代码说明

通过形态学操作,凸显出银行卡中的各个区域

运行效果:

根据寻找到的轮廓排除面积不匹配的区域,将剩下的轮廓进行排序

# 寻找轮廓
contours,his = cv.findContours(erosion,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_NONE)


count_infos = []
for contour in contours:
    # 获取轮廓面积
    area = cv.contourArea(contour)
    
    # 面积 小|大 的都筛选掉
    if (area < 500) | (area > 2500):
        continue   

    x,y,w,h = cv.boundingRect(contour)
    count_infos.append((x,y,w,h))
    # cv.rectangle(photo_card,(x,y),(x+w,y+h),(0,0,255),2)

count_sort = sort_inv(count_infos)

5.模板匹配

for (x,y,w,h) in count_sort:
    infos = []
    photo_count = binary[y:y+h,x:x+w]
    contours,_ = cv.findContours(photo_count,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_NONE)
    
    boxs2 = []
    for contour in contours:
        # 待匹配图
        boxs2.append(cv.boundingRect(contour))
    
    qwe = sort_inv(boxs2)
    for (x2,y2,w2,h2) in qwe:
        img_photo1 = photo_count[y2:y2+h2,x2:x2+w2]
        
        max_val = 0
        max_temp = 0
        for i in range(len(dict_temp)):
            x3,y3,w3,h3 = dict_temp[i]
            temp = photo_2[y3:y3+h3,x3:x3+w3]
            img_temp_resize = cv.resize(temp,(w2,h2))  

            # 此处,img_temp_resize 是模板
            # img_photo1是单个切割后的待预测图片
            
            result = cv.matchTemplate(img_photo1, img_temp_resize, cv.TM_CCOEFF_NORMED)
            (_, maxVal, _, _) = cv.minMaxLoc(result)
            
            if maxVal>max_val:
                max_val = maxVal
                max_temp = i
        infos.append(str(max_temp))
    
    cv.rectangle(photo_card,(x,y-h-2),(x+w,y-2),(0,0,255),1)
    # 绘制矩形框
    cv.putText(photo_card,''.join(infos),(x,y-3),cv.FONT_HERSHEY_SIMPLEX,1,(0,0,0))
    # 绘制检测出的值
show_photo(photo_card)  
# 展示绘制后的图片  
cv.destroyAllWindows()
# 关闭所有窗口

6.运行结果

 ps

本篇文章仅实现完整项目jiangj,后续可能会出单独的知识点讲解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值