关于思路:
识别流程:
1.银行卡需要提取出卡号数字
2.需要与模板字体进行匹配
关于模板:
转换成灰度图——二值转换——轮廓检测——外接矩形——将每一个数字进行切割——切割完后
与0-9数字进行匹配
图中用到的模板图片和银行卡图片皆可在网上找到。
所用的示例银行卡:
所用模板图片:
import numpy as np
import cv2
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.imread('2020.png')
ref=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ref=cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
# cv_show('ref',ref)
countour=cv2.findContours(ref,cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[0]
n=len(countour)
Rectbox=np.ones((n,4),dtype=int)
# print(Rectbox)
for i in range(n):
Rectbox[i]=cv2.boundingRect(countour[i])
# print(rect)
imgBox=sorted(Rectbox,key=lambda x:x[0])
# print(imgBox)
roi2=[]
for i in range(n):
x,y,w,h=imgBox[i]
ROI=ref[y:y+h,x:x+w]
# print(ROI)
ROI=cv2.resize(ROI,(53,83))
roi2.append(ROI)
thresh_val,ROI=cv2.threshold(ROI,200,255,cv2.THRESH_BINARY)
imgBox[i]=ROI
# cv_show('ROI',ROI)
#至此实现数字与模板字体一一对应,后续可进行银行卡字体与模板字体的比较
# 关于模板数字识别完成
rectkernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(20,3))
sqkernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
card=cv2.imread('08.png')
ROI=cv2.resize(card,(500,300))
gray_card=cv2.cvtColor(ROI,cv2.COLOR_BGR2GRAY)
tophat=cv2.morphologyEx(gray_card,cv2.MORPH_TOPHAT,rectkernel)
# cv_show('tophat',tophat)
#
gradx=cv2.Sobel(tophat,ddepth=cv2.CV_64F,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')
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]
# cv_show('thresh',thresh)
counters=cv2.findContours(thresh,cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[0]
cur_img=card.copy()
cv2.drawContours(ROI,counters,-1,(0,0,255),3)
# cv_show('ROI',ROI)
locs=[]
for (i,c) in enumerate(counters):
(x,y,w,h)=cv2.boundingRect(c)
ar=w/float(h)
if ar>2.5 and ar<5:
if h>20 and h<30:
locs.append((x,y,w,h))
# print(locs)
cnm=cv2.findContours(gray_card,cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[0]
locs.sort(key=lambda x:x[0])
Rectbox1=[]
ri=[]
numbox0=[]
for (i,(gx,gy,gw,gh)) in enumerate(locs):
groudOutput=[]
group=gray_card[gy-5:gy+gh+5,gx-10:gx+gw]
# cv_show('group',group)
# 目前实现数字提取,剩下与模板数字分割原理相同
box_thresh=cv2.threshold(group,0,255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# cv_show('box_thresh',box_thresh)
cnts=cv2.findContours(box_thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0]
groupOutput = []
for c in cnts:
getnumber = []
(x, y, w, h) = cv2.boundingRect(c)
# points.append([x, y, w, h])
roi = box_thresh[y:y + h, x:x + w]
roi = cv2.resize(roi, (53, 83))
thresh_val, roi = cv2.threshold(roi, 200, 255, cv2.THRESH_BINARY)
# cv_show('roi', roi)
scores = []
for r in roi2:
# cv_show('r',r)
result = cv2.matchTemplate(roi, r, cv2.TM_CCOEFF)
# print('r',result)
# print(np.argmax(result))
(_, score, _, _) = cv2.minMaxLoc(result)
scores.append(score)
# scores.reverse()
groupOutput.insert(0,str(np.argmax(scores)))
print('输出', groupOutput)