日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

opencv进阶篇---银行卡数字识别

發(fā)布時(shí)間:2024/3/24 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv进阶篇---银行卡数字识别 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

執(zhí)行結(jié)果:

主要思想:對(duì)模板圖像以及待檢測(cè)圖像進(jìn)行外輪廓檢測(cè),并得到各自外接矩形,將模板圖像的外接矩形做resize()操作,使其外接矩形的大小與待檢測(cè)圖像外接矩形的大小相一致,然后與待檢測(cè)圖形做模板匹配
準(zhǔn)備工作:
1、轉(zhuǎn)為為灰度圖像
2、轉(zhuǎn)化為二值圖像,才能做輪廓檢測(cè)
3、根據(jù)輪廓的長(zhǎng)寬比例的不同,過(guò)濾掉一些銀行卡上無(wú)用的干擾信息
4、上面的步驟僅能得到一些大致的輪廓,還需做一些形態(tài)學(xué)操作,然后對(duì)數(shù)字進(jìn)行拆分,得到更為精確的數(shù)字信息
注意:在找模板時(shí),應(yīng)該找字體十分接近的字體作為模板

(1)模板預(yù)處理過(guò)程:將模板中的每一個(gè)數(shù)字分別進(jìn)行灰度轉(zhuǎn)換、二值化、輪廓查找、輪廓繪制、resize()輪廓的大小并且將每個(gè)數(shù)字的輪廓值(排好序的)存入字典類(lèi)型的變量中
模板圖:

預(yù)處理之后的模板圖:

代碼片段:

img=cv.imread("E:\OpenCVTests\Samples\sample/nine/template-matching-ocr\images\ocr_a_reference.png") gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,ref=cv.threshold(gray,10,255,cv.THRESH_BINARY_INV)#此步驟,應(yīng)該加前面的ret,否則會(huì)報(bào)錯(cuò) refCnts,hierarchy=cv.findContours(ref.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) #后面還要繼續(xù)使用ref,因此需使用ref.copy(),否則會(huì)對(duì)原圖做出改變;第二個(gè)參數(shù)為指定檢測(cè)外輪廓;第三個(gè)參數(shù)為輪廓逼近的一種方法 cv.drawContours(img,refCnts,-1,(0,0,255),3)#-1表示繪制所有輪廓,當(dāng)指定為其他值時(shí),只在圖像中選擇一個(gè)繪制單個(gè)輪廓 refCnts=contours.sort_contours(refCnts,method="left-to-right")[0]#返回排序完的輪廓 digits={}#建立一個(gè)字典類(lèi)型,i是輪廓索引,c是輪廓----字典類(lèi)型:每個(gè)索引號(hào)對(duì)應(yīng)一個(gè)索引值 for(i,c)in enumerate(refCnts):#i是輪廓索引,c是對(duì)應(yīng)輪廓,則完成了對(duì)檢測(cè)出來(lái)的輪廓進(jìn)行了排序(x,y,w,h)=cv.boundingRect(c)#得到?jīng)]一個(gè)外接矩形的左上坐標(biāo)點(diǎn)以及長(zhǎng)度、寬度roi=ref[y:y+h,x:x+w]#每個(gè)數(shù)字的外接矩形的尺寸roi=cv.resize(roi,(57,88))#重置外接矩形的尺寸至合適大小digits[i]=roi#每個(gè)數(shù)字對(duì)應(yīng)一個(gè)模板

(2)待檢測(cè)圖像預(yù)處理過(guò)程:主要包括形態(tài)學(xué)操作去噪點(diǎn)、灰度轉(zhuǎn)換、二值化、Sobel()函數(shù)求梯度、輪廓相關(guān)操作(輪廓的查找、輪廓的繪制、外接輪廓、根據(jù)輪廓的長(zhǎng)寬比來(lái)對(duì)輪廓就行篩選、排序)再到遍歷每一塊中的每一個(gè)數(shù)字
待檢測(cè)圖像原圖:

執(zhí)行一次頂帽操作:

執(zhí)行一次Sobel()求X方向上的梯度操作:求圖中較為明亮的區(qū)域

執(zhí)行一次閉操作:使圖像上的內(nèi)容成塊出現(xiàn)

執(zhí)行一次二值化操作:過(guò)濾掉雜亂信息

再執(zhí)行一次閉操作:填補(bǔ)白色塊中的小黑塊

執(zhí)行輪廓檢測(cè)、輪廓繪制:

后續(xù)再根據(jù)輪廓的長(zhǎng)寬比對(duì)輪廓進(jìn)行篩選,篩選出需要的輪廓信息,工寄檢測(cè)出4組有用的輪廓信息,并循環(huán)遍歷這四組輪廓中的每一個(gè)數(shù)字,方法與上面同。

完整代碼:

import cv2 as cv from imutils import contours import matplotlib as plt import numpy as np FIRST_NUMBER = {"3": "American Express","4": "Visa","5": "MasterCard","6": "Discover Card" } #對(duì)模板圖像做預(yù)處理img=cv.imread("E:\OpenCVTests\Samples\sample/nine/template-matching-ocr\images\ocr_a_reference.png") gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,ref=cv.threshold(gray,10,255,cv.THRESH_BINARY_INV)#此步驟,應(yīng)該加前面的ret,否則會(huì)報(bào)錯(cuò) refCnts,hierarchy=cv.findContours(ref.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) #后面還要繼續(xù)使用ref,因此需使用ref.copy(),否則會(huì)對(duì)原圖做出改變;第二個(gè)參數(shù)為指定檢測(cè)外輪廓;第三個(gè)參數(shù)為輪廓逼近的一種方法 cv.drawContours(img,refCnts,-1,(0,0,255),3)#-1表示繪制所有輪廓,當(dāng)指定為其他值時(shí),只在圖像中選擇一個(gè)繪制單個(gè)輪廓 refCnts=contours.sort_contours(refCnts,method="left-to-right")[0]#返回排序完的輪廓 digits={}#建立一個(gè)字典類(lèi)型,i是輪廓索引,c是輪廓----字典類(lèi)型:每個(gè)索引號(hào)對(duì)應(yīng)一個(gè)索引值 for(i,c)in enumerate(refCnts):#i是輪廓索引,c是對(duì)應(yīng)輪廓,則完成了對(duì)檢測(cè)出來(lái)的輪廓進(jìn)行了排序(x,y,w,h)=cv.boundingRect(c)#得到?jīng)]一個(gè)外接矩形的左上坐標(biāo)點(diǎn)以及長(zhǎng)度、寬度roi=ref[y:y+h,x:x+w]#每個(gè)數(shù)字的外接矩形的尺寸roi=cv.resize(roi,(57,88))#重置外接矩形的尺寸至合適大小digits[i]=roi#每個(gè)數(shù)字對(duì)應(yīng)一個(gè)模板#對(duì)待檢測(cè)圖像做預(yù)處理 recKernel=cv.getStructuringElement(cv.MORPH_RECT,(10,3))#為保證檢測(cè)信息準(zhǔn)確,需去除銀行卡頁(yè)面雜亂信 sqKernel=cv.getStructuringElement(cv.MORPH_RECT,(2,2))#因此需要對(duì)圖像做形態(tài)學(xué)操作,故在此設(shè)立卷積核image=cv.imread("E:\OpenCVTests\Samples\sample/nine/template-matching-ocr\images\credit_card_01.png") image=cv.resize(image,(250,200)) gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY) tophat=cv.morphologyEx(gray,cv.MORPH_TOPHAT,recKernel)#根據(jù)字體的大小來(lái)選定合適的核;頂帽操作來(lái)突出明亮的區(qū)域gradx=cv.Sobel(tophat,ddepth=cv.CV_32F,dx=1,dy=0,ksize=3)#對(duì)X還是對(duì)Y需要或者同時(shí)需要根據(jù)實(shí)際需要來(lái)設(shè)定,圖像梯度 gradx=np.absolute(gradx)#取絕對(duì)值 (minVal,maxVal)=(np.min(gradx),np.max(gradx))#歸一化 gradx=(255*((gradx-minVal)/(maxVal-minVal))) gradx=gradx.astype("uint8")gradx=cv.morphologyEx(gradx,cv.MORPH_CLOSE,recKernel)#執(zhí)行閉操作,使圖像上的內(nèi)容成塊出現(xiàn) ret,thresh=cv.threshold(gradx,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)#低閾值之所以設(shè)為0,是因?yàn)楹竺娴姆椒ㄟx用了OTSU自動(dòng)設(shè)定閾值,適合雙峰的圖像操作 thresh=cv.morphologyEx(thresh,cv.MORPH_CLOSE,sqKernel)#本次閉操作是為了填補(bǔ)二值化圖像中塊中的不完整小塊 Cnts,hierarchy=cv.findContours(thresh.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) cnts=Cnts curImage=image.copy() cv.drawContours(curImage,cnts,-1,(0,0,255),3)#此處輪廓不是原圖像的輪廓,而是經(jīng)歷了一些列運(yùn)算之后的圖像的輪廓 locs=[] for (i,c)in enumerate(cnts):(x,y,w,h)=cv.boundingRect(c)#做出每個(gè)輪廓的外接矩形ar=w/float(h)#根據(jù)外接矩形的長(zhǎng)寬比來(lái)篩選有用的矩形,并將其添加到元組中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])#經(jīng)篩選之后的輪廓 output=[] for (i,(gx,gy,gw,gh))in enumerate(locs):#遍歷每一塊中的每一個(gè)數(shù)字groupOutput=[]group=gray[gy-5:gy+gh+5,gx-5:gx+gw+5]#取輪廓及其周?chē)膮^(qū)域cv.imshow("group",group)group=cv.threshold(group,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)[1]#后面的[]要加,否則會(huì)報(bào)錯(cuò)元組類(lèi)型不能copy,下面再對(duì)每個(gè)塊進(jìn)行輪廓檢測(cè)、繪制digitCnts,hierarchy=cv.findContours(group.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)#每一個(gè)group再進(jìn)行輪廓檢測(cè)、繪制digitCnts=contours.sort_contours(digitCnts,method="left-to-right")[0]for c in digitCnts:#計(jì)算每一組數(shù)中的每一個(gè)數(shù)值(x,y,w,h)=cv.boundingRect(c)roi=group[y:y+h,x:x+w]roi=cv.resize(roi,(57,88))#尺寸需與模板的尺寸對(duì)應(yīng),得到每一個(gè)數(shù)字所在的區(qū)域scores=[]#新建一個(gè)空列表,用來(lái)存儲(chǔ)檢測(cè)到的數(shù)字for (digit,digitROI)in digits.items():#在模板預(yù)處理中建立了數(shù)值的字典類(lèi)型,一個(gè)為索引、一個(gè)為值result=cv.matchTemplate(roi,digitROI,cv.TM_CCOEFF)#匹配,返回與之匹配度最高的數(shù)值(_,score,_,_)=cv.minMaxLoc(result)#做10次匹配,取最大值(注意:取最大值還是最小值跟選取的模板匹配方法有關(guān))scores.append(score)groupOutput.append(str(np.argmax(scores)))cv.rectangle(image,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)#第一組的矩形框cv.putText(image,"".join(groupOutput),(gx,gy-15),cv.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)output.extend(groupOutput) print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]])) print("Credit Card #: {}".format("".join(output))) cv.imshow("Image",image)cv.waitKey(0) cv.destroyAllWindows()

總結(jié)

以上是生活随笔為你收集整理的opencv进阶篇---银行卡数字识别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。