整體思路:利用輪廓檢測與模板匹配實作信用卡數字識別,
總體分為3步:
- 使用輪廓檢測實作數字1-9模板的存取,
- 檢測到信用卡的數字部磁區域并存盤,
- 將信用卡數字依次與模板進行匹配,尋找到最合適的數字
最終效果:

Step1:數字模板的獲取
原始圖片如下,需要通過輪廓檢測獲取每個單獨的數字模板,

思路:通過輪廓檢測獲得各個數字的外輪廓,然后通過做出各個外輪廓的外接矩形并根據外接矩形的左上角點x的排序結果,確定對應數字所在的位置,然后用digit字典存盤每一個數字的圖象,
#獲取模板,獲得模板字典
templateRGB=cv.imread('ocr_a_reference.png',cv.IMREAD_COLOR)
templateGray=cv.cvtColor(templateRGB, cv.COLOR_BGR2GRAY)
(ret,templateGrayInv)=cv.threshold(templateGray, 127, 255,
cv.THRESH_BINARY_INV)
contours,hierarchy=cv.findContours(templateGrayInv.copy(),
cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
boundingBoxes=[] #繪制外接矩形,按照x的大小排序,得到0-9的模板
for cnt in contours:
boundingBoxes.append(cv.boundingRect(cnt)) #(x,y,w,h)
boundingBoxes=sort(boundingBoxes)
digits = {} #此處可用字典也可用串列
for (i,c) in enumerate(boundingBoxes):
(x,y,w,h)=boundingBoxes[i]
roi=templateGrayInv[y:y+h,x:x+w]
roi=cv.resize(roi, (57,88))
digits[i]=roi
result: digit={0:image of number 0,1:image of number 1,...,9:image of number 9}
Step2:檢測到信用卡的數字部磁區域并存盤
難點在于如何檢測到數字所在的區域,此處采用形態學閉操作的方法,將數字膨脹成連接在一起的明亮區域(4個為1個區域),然后通過輪廓檢測做出外接矩形,根據限定矩形選擇條件,比如長寬之比、長寬范圍、矩形在影像中的整體位置等等選擇出合適的外接矩形,其框選的內部即為所要的區域,
下圖為閉操作之后的影像:

約束外接矩形條件后的結果:

#處理信用卡獲取信用卡數字所在位置
creditCardBGR=cv.imread('credit_card_01.png',cv.IMREAD_COLOR)
creditCardGray = cv.cvtColor(creditCardBGR, cv.COLOR_BGR2GRAY)
(ret,creditCardGrayThresh)=cv.threshold(creditCardGray, 127, 255,
cv.THRESH_BINARY)
kernel=np.ones((4,9)) #禮帽操作
tophat = cv.morphologyEx(creditCardGrayThresh, cv.MORPH_TOPHAT, kernel)
kernel=np.ones((3,25)) #閉操作
close=cv.morphologyEx(tophat, cv.MORPH_CLOSE, kernel)
close=cv.morphologyEx(close, cv.MORPH_CLOSE, kernel)
contours, hierarchy = cv.findContours(close.copy(), #依靠輪廓檢測找到四段數字的區域
cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
boundingBoxes=[]
for cnt in contours:
(x,y,w,h)=cv.boundingRect(cnt)
ratio=w/h
if ratio>3.3 and ratio<4.3: #可以再加入條件進行約束
boundingBoxes.append((x,y,w,h))
boundingBoxes=sort(boundingBoxes)
在獲取4段數字區域之后,與Step1的做法相同,在各自數字區域內進行輪廓檢測,并且根據外接矩形的x進行排序,獲得各自內部數字的影像資料,自此16個數字全部被從原始信用卡影像中提取出來,
#遍歷4段區域,找到16個數字的影像資訊并存盤
number=[]
for i in range(0,4):
(x,y,w,h)=boundingBoxes[i]
region=creditCardGrayThresh[y-3:y+h+3,x-3:x+w+3] #存盤當前段的影像內容
interNums=[]
contours, hierarchy = cv.findContours(region.copy(), #找到4個內部數字的區域
cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
for cnt in contours:
(x,y,w,h)=cv.boundingRect(cnt)
interNums.append((x,y,w,h))
interNums=sort(interNums)
for j in range(0,len(interNums)): #依次存盤到number串列中
(x,y,w,h)=interNums[j]
roi=region[y:y+h,x:x+w]
roi=cv.resize(roi, (57,88))
number.append(roi)
Step3:將信用卡數字依次與模板進行匹配,尋找到最合適的數字
將存盤信用卡數字的number串列中的數字依次與Step1中得到的模板進行匹配,以得分高的做為最終結果,
#使用模板匹配得到最終結果
OCR_Rseult=''
for i in range(0,len(number)):
scores=[]
for j in range(0,len(digits)):
result=cv.matchTemplate(number[i], digits[j], cv.TM_CCOEFF)
(_, score, _, _) = cv.minMaxLoc(result)
scores.append(score)
OCR_Rseult+=str(np.argmax(scores))
最后顯示效果:
print(OCR_Rseult) #列印數字
image=creditCardBGR.copy() #繪圖
for (i,(x,y,w,h)) in enumerate(boundingBoxes) :
cv.rectangle(image, (x- 5, y - 5),(x + w + 5, y + h + 5), (0, 0, 255), 1)
cv.putText(image,OCR_Rseult[4*i:4*i+4],(x,y-10), cv.FONT_HERSHEY_COMPLEX, 0.7, (0, 0, 255))
cv_show('img', image)


轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/289469.html
標籤:AI
