用模板匹配進行的銀行卡數字識別


實現功能:在銀行卡上識別出卡號數字部分,並在其上方寫下數字,如下圖所示。

模板圖片如下圖,

原始銀行卡圖片,

完整代碼如下,在Pycharm中編寫。

imutils庫需要提前下載,在cmd中用命令 pip install imutils 下載。
 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 import imutils
 5 from imutils import contours
 6 
 7 # 處理模板圖片
 8 img = cv2.imread("C:\\Users\\lenovo\\Pictures\\moban.jpg")
 9 #cv2.imshow("img_moban",img)
10 img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
11 #cv2.imshow("img_moban_gray ",img_gray)
12 ret,ref = cv2.threshold(img_gray,20,255,cv2.THRESH_BINARY_INV)
13 #cv2.imshow("binary", ref)
14 image,refCnts, hierarchy = cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
15 contour = cv2.drawContours(img,refCnts,-1,(0,0,255),3)
16 cv2.namedWindow("img_moban_contours",cv2.WINDOW_NORMAL)
17 #cv2.imshow("img_moban_contours",contour)
18 
19 #refCnts = refCnts[0] if imutils.is_cv2() else refCnts[1]
20 refCnts = contours.sort_contours(refCnts,method = "left-to-right")[0] #from imutils import contours
21 digits = {}
22 for (i,c) in enumerate(refCnts):     # enumerate(refCnts)下標從0開始,返回值是0,第一個輪廓。1,第二個輪廓
23     (x,y,w,h) = cv2.boundingRect(c)  # x,y是矩陣左上點的坐標,w,h是矩陣的寬和高
24     roi = ref[y:y+h,x:x+w]
25     roi = cv2.resize(roi,(57,88))
26     digits[i] = roi
27 
28 
29 # 處理待檢測圖片
30 recKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,3))
31 sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(2,2))
32 
33 image = cv2.imread("C:\\Users\\lenovo\\Pictures\\yinhangka.png")
34 image = cv2.resize(image,(250,200))
35 
36 gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
37 cv2.imshow("imagesize",gray)
38 tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,recKernel) # 頂帽操作:突出明亮區域
39 cv2.imshow("imagetophat",tophat)
40 gradx = cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=3)
41 gradx= np.absolute(gradx)
42 (minVal,maxVal) = (np.min(gradx),np.max(gradx))
43 gradx = (255*((gradx-minVal)/(maxVal-minVal)))
44 gradx = gradx.astype("uint8")
45 
46 gradx = cv2.morphologyEx(gradx,cv2.MORPH_CLOSE,recKernel)
47 cv2.imshow("imagegradx",gradx)
48 ret,thresh = cv2.threshold(gradx,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)
49 thresh = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel)
50 imageprint,Cnts,hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
51 cnts = Cnts # cnts是所有輪廓
52 curImage = image.copy()
53 contours = cv2.drawContours(curImage,cnts,-1,(0,0,255),3)
54 cv2.imshow("contours",contours)
55 locs = []    # 儲存符合條件的數字模塊
56 locsnum = []
57 for (i,c) in enumerate(cnts):
58     (x,y,w,h) = cv2.boundingRect(c)
59     ar = w/float(h)
60     if (ar>2.5) and (ar<4):
61         if h>10:   # 這里的條件要多試幾次
62             locs.append((x,y,w,h))
63 locs = sorted(locs,key=lambda x:x[0]) #排序方式按照中括號[]里面的維度進行排序,[0]按照第一維排序,[2]按照第三維排序
64 print(len(locs))
65 output=[]
66 for (i,(gx,gy,gw,gh)) in enumerate(locs):
67     groupOutput = []
68     group = gray[gy-5:gy+gh+5,gx-5:gx+gw+5] # 在灰度圖中選取roi
69     group = cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
70    # cv2.imshow("group", group)
71     imageing,digitCnts,hierarchy = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
72     # digitCnts = contours.sort_contours(digitCnts,method = "left-to-right")[0]
73     for c in digitCnts:
74         (x,y,w,h) = cv2.boundingRect(c)
75         roi = group[y:y+h,x:x+w]
76         roi = cv2.resize(roi,(57,88))
77         scores=[]
78         for (digit, digitROI) in digits.items():  # 在模板預處理中建立了數值的字典類型,一個為索引、一個為值
79             result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)  # 匹配,返回與之匹配度最高的數值
80             (min_val, score, min_index, max_index) = cv2.minMaxLoc(result)  # 做10次匹配,取最大值(注意:取最大值還是最小值跟選取的模板匹配方法有關)
81             scores.append(score)
82         groupOutput.append(str(np.argmax(scores))) #argmax返回的是最大數的索引
83     cv2.rectangle(image, (gx - 5, gy - 5), (gx + gw + 5, gy + gh + 5), (0, 0, 255), 1) # 第一組的矩形框
84     groupOutput.reverse()
85     image = cv2.putText(image, str("".join(groupOutput)), (gx, gy - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
86     output.extend(groupOutput)
87 # print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
88 print("Credit Card #: {}".format("".join(output))) # 將output中的字符用雙引號中間的符號連接起來
89 cv2.imshow("Image", image)
90 cv2.waitKey(0)
91 cv2.destroyAllWindows()
92 # . join():    連接字符串數組。將字符串、元組、列表中的元素以指定的字符(分隔符)連接生成一個新的字符串
完整代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM