模板:
银行卡:
主要思路:用遮盖法 将无关紧要的上面和下面部分截掉,保留银行卡号差不多的位置,然后用opencv做图像处理,得到四个
连着数字的小框框,然后再在四个小框框里面提取出每一个单个的数字和模板里面的数字进行对比
难点是:如何使用opencv进行图像处理,最后只提取出银行卡卡号部分的图像 ;
如何保证从左到右输出的阅读顺序
import cv2
import numpy as np
roi2=[]
labels=[]
points=[]img=cv2.imread('ocr_a_reference.png')
img_gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_bit=cv2.threshold(img_gray,10,255,cv2.THRESH_BINARY_INV)[1]
cnts=cv2.findContours(img_bit,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0]def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()for i,cnt in enumerate(cnts):x,y,w,h = cv2.boundingRect(cnt)labels.append([x,y,w,h])labels.sort(key=lambda x : x[0])for i ,label in enumerate(labels) : x,y,w,h = label #cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0),2)original=img_bit[y:y+h,x:x+w]#original = cv2.threshold(original, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]resize=cv2.resize(original, (57, 88))roi2.append(resize)#cv_show('roi',roi2[i])kernel=np.ones((3,3))
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 3)) #非常灵活 非常有用card1 = cv2.imread('./images/credit_card_05.png')
card=card1.copy()
card [0:card.shape[0]//2] = 0
card [2*card.shape[0]//3:] =0
cv_show('img',card)
card_gray = cv2.cvtColor(card,cv2.COLOR_BGR2GRAY)
#tophat = cv2.morphologyEx(card_gray, cv2.MORPH_TOPHAT, rectKernel) #加了之后效果反而变差了
#cv_show('tophat',tophat)
gradX = cv2.Sobel(card_gray, ddepth=cv2.CV_64F, dx=1, dy=0, #ksize=-1相当于用3*3的ksize=-1)
cv_show('gradX',gradX)
gradX=np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
sobelx=np.uint8(gradX)close=cv2.morphologyEx(sobelx,cv2.MORPH_CLOSE,rectKernel)
thresh = cv2.threshold(close, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] close=cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,rectKernel)
cv_show('close',close)
cnts=cv2.findContours(close.copy(),cv2.RETR_EXTERNAL,\cv2.CHAIN_APPROX_SIMPLE)[0]cv2.drawContours(card, cnts, -1, (0,0,255),3)
#cv_show('cnts',card)if len(cnts)>0:for cnt in cnts:if cv2.contourArea(cnt) >1000:L=cv2.arcLength(cnt,True ) approx=cv2.approxPolyDP(cnt,0.02*L, True)x,y,w,h=cv2.boundingRect(approx)points.append([x,y,w,h])#print(x)#cv2.rectangle(card1,(x,y),(x+w,y+h),(0,0,255),1)points.sort(key=lambda x: x[0])
print(points)
pic=card1.copy()
groupOutput = []
for point in points :numbox=[]getnumber=[]x,y,w,h = point cv2.rectangle(card1,(x-10,y-5),(x+w+3,y+h+2),(0,0,255),1)box=card_gray[y-5:y+h+5,x-5:x+w+5]#cv_show('1', box)box_thresh=cv2.threshold(box, 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]for i,cnt in enumerate(cnts):x1,y1,w1,h1=cv2.boundingRect(cnt)#cv2.rectangle(box,(x1,y1),(x1+w1,y1+h1),(0,0,255),2)numbox.append([x1,y1,w1,h1])#cv_show('get', box) numbox.sort(key=lambda x:x[0])#print('cnt',x1,y1,w1,h1)for num in numbox:x2,y2,w2,h2=numroi1=box_thresh[y2-1:y2+h2+1,x2-1:x2+w2+1]roi1=cv2.resize(roi1,(57,88))#cv_show('roi1',roi1)scores=[]for r in roi2 :#cv_show('r',r)result = cv2.matchTemplate(roi1,r,cv2.TM_CCOEFF)#print('r',result)#print(np.argmax(result))(_, score, _, _) = cv2.minMaxLoc(result)scores.append(score)groupOutput.append(str(np.argmax(scores)))getnumber.append(str(np.argmax(scores)))cv2.putText(card1, "".join(getnumber), (x-10,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8 , (0, 0, 255), 2) \print('groupOutput',groupOutput) cv2.imshow('out',card1)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果如下: