openCV银行卡数字匹配(重点归纳)

(1)引入模块

import cv2

import numpy as np

import myutils

(2)图像的基本操作

1.图像读取

img=cv2.imread(“路径”)

2.图像显示

cv2.imshow(“窗口名”,图像变量(img))

(3)图像的轮廓检测

1.图像的灰度化

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

或直接img=cv2,imread(“路径”,0)

2.图像的二值化(黑白图像)

ref=cv2.threshold(gray,10,255,cv2.THRESH_BINARY_INV)[1]

10,255:表示阈值(超过10取255,小于取0)

cv2.THRESH_BINARY_INV表示取法相反

3.寻找轮廓

refCnt,hierarchy=cv2.findContours(ref,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

ref表示在轮廓检测中要用二值图像

cv2.RETR_EXTERNAL只寻外轮廓

draw_refCnt=cv2.drawContours(img.copy(),refCnt,-1,(0,0,255),3)

img.copy()为在画轮廓时不印象原图

reCnts表示轮廓

-1表示所有的轮廓

3表示通道3

结果:

4.模块轮廓划分和排序

1.refCnts = myutils.sort_contours(refCnts, method=“left-to-right”)[0]

将数字模板每个数字的轮廓计算出来,并且排序,reCnts可以看做轮廓合集

2.遍历每个轮廓,得到模块

for (i,c) in enumerate (reCnts)😕/遍历每个轮廓

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

(x,y,w,h)=cv2.boundingrect©//获得轮廓的外接矩形,返回元组矩形左上坐标和矩阵长宽

roi=ref[x:x+w, y:y+h]//获得roi感兴趣部分

roi=cv2.resize(58,88)//转化大小适用于模板匹配

4.定义卷积核

rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))

sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

5.读入银行卡图像,预处理(使其可以更准确)

1.img2=cv2.imread(“绝对路径”)

img2=myutils.resize(img2,width=300)//把宽变为300,其高转变为对应的长度

gray=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)//灰度化

tophat=cv2.morphologyEx(gray,MORPH_TOPHAT,rectKernel)//礼帽处理,使图像变得更加明亮

6.sobel算子

gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)# ksize=-1相当于用3*3的

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)

sobel算子作用:Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

7.进行闭运算【先腐后膨】(对输入图像没有规定(灰度图和二值图像))

gradx=cv2.morphologyEX(gradX,0,255,cv2.MORPH_CLOSE,rectKernel)

作用:使图像中的孔隙填充(先对图像膨胀后腐蚀 作用:用来填充物体内的小空洞,连接邻近的物体,连接断开的轮廓线,平滑其边界的同时不改变面积)

8.二值化cv2.threshold

THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0

thresh = cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

9.在进行一个闭运算

thresh=cv2.morphologyEX(thresh,0,255,cv2.MORPH_CLOSE,rectKernel)

10.寻找轮廓

threshcnts,hierarchy=cv2.foundContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

cnts=theshcnts

11.遍历轮廓数字组

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 = []

12.遍历数字轮廓(每个数字组中数字)

for(i,(gx,gy,gw,gh)) in enumberate(locs):

groudOutput=[]//定义一个list

# 根据坐标提取每一个组

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)

# 计算每一组的轮廓

digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,

 cv2.CHAIN_APPROX_SIMPLE)//轮廓检测

digitCnts = myutils.sort_contours(digitCnts,method="left-to-right")[0]    //为数字组中每个数字轮廓排序

for (c) in (digitCnts):

    (x,y,w,h)=cv2.boundingRect(c)

    roi=(y:y+h,x:x+w)

    roi=cv2.resize(roi,(58,88))

    # 计算匹配得分

    scores = []

    # 在模板中计算每一个得分

    for (digit, digitROI)in digits.items()://item()方法把字典中每对key和value组成一个元组,并把这些元组放在列表中返回。digit为key,digitROI为value

     # 模板匹配

        result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF_NORMED))#TM_CCOEFF_NORMED,1表示完美的匹配;-1表示最差的匹配。即表示越大越好

        (_, score, _, _) = cv2.minMaxLoc(result)    

        scores.append(score)//#result参数表示匹配结果图像,必须是单通道32位浮点,scorce参数表示返回的最大值//score可以大致认为匹配度,匹配度越大,越准确

        # 得到最合适的数字

        groupOutput.append(str(np.argmax(scores)))//#numpy.argmax(array, axis) 用于返回一个numpy数组中最大值(最大可能性)的索引值(下标)

        # 画出来

        cv2.rectangle(img2, (gX -5, gY -5),(gX + gW +5, gY + gH +5), (0, 0, 255), 1)

        cv2.putText(img2, "".join(groupOutput), (gX, gY -15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)

cv2.putText(img, str(i), (123,456)), font, 2, (0,255,0), 3)

各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细

Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串

print(“Credit Card #: {}”.format("".join(output)))//数字识别结果

cv2.imshow(“Image”, img2)

cv2.waitKey(0)

附言:这个小项目网上已经有许多源代码(本文只是代码简单说明),本博客只是自己对这个项目的理解,希望对读者有点帮助

银行卡图片:在这里插入图片描述

模板图片:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值