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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV-信用卡数字识别-03

發布時間:2024/9/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV-信用卡数字识别-03 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

模板圖

銀行卡圖

# 導入工具包 from imutils import contours import numpy as np import argparse import cv2 # 指定信用卡類型 FIRST_NUMBER = {"3": "American Express","4": "Visa","5": "MasterCard","6": "Discover Card" } # 繪圖展示函數 def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0) # cv2.destroyAllWindows() # 讀取一個模板圖像 img = cv2.imread("ocr_a_reference.png") cv_show('template',img) # 灰度圖 ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv_show('template_gray',ref) # 二值圖像 ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1] cv_show('template_bi',ref)


# 計算輪廓 # cv2.findContours()函數接受的參數為二值圖,即黑白的(不是灰度圖),cv2.RETR_EXTERNAL只檢測外輪廓,cv2.CHAIN_APPROX_SIMPLE只保留終點坐標 # 返回的list中每個元素都是圖像中的一個輪廓ref_,refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cv2.drawContours(img,refCnts,-1,(0,0,255),3) # 輪廓在二值圖上得到, 畫要畫在原圖上 cv_show('template_Contours',img) print (np.array(refCnts).shape)

# 對輪廓進行排序函數 def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1# 計算外接矩形 boundingBoxes是一個元組boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一個最小的矩形,把找到的形狀包起來x,y,h,w# sorted排序(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxes # 輪廓和boundingBoxess # 圖像處理函數 def resize(image, width=None, height=None, inter=cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return imageif width is None:r = height / float(h)dim = (int(w * r), height)else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation=inter)return resized refCnts = sort_contours(refCnts, method="template_Contours")[0] #排序,從左到右,從上到下 digits = {} # 遍歷每一個輪廓 for (i, c) in enumerate(refCnts): # c是每個輪廓的終點坐標 # 計算外接矩形并且resize成合適大小(x, y, w, h) = cv2.boundingRect(c)roi = ref[y:y + h, x:x + w] # 每個roi對應一個數字 roi = cv2.resize(roi, (57, 88)) # 太小,調大點digits[i] = roi # 每一個數字對應每一個模板# 【模板處理流程: 輪廓檢測,外接矩形,摳出模板,讓模板對應每個數值】# 【輸入圖像處理】 # 形態學操作,禮帽+閉操作可以突出明亮區域,但并不是非得禮帽+閉操作 # 初始化卷積核,根據實際任務指定大小,不一定非要3x3 rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3)) sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) #讀取輸入圖像,預處理 image = cv2.imread("credit_card_01.png") cv_show('Input_img',image) image = resize(image, width=300) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv_show('Input_gray',gray)


#禮帽操作,突出更明亮的區域 tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) cv_show('Input_tophat',tophat) # x方向的Sobel算子,實驗表明,加y的效果的并不好 gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相當于用3*3的ksize=-1)gradX = np.absolute(gradX) # absolute: 計算絕對值 (minVal, maxVal) = (np.min(gradX), np.max(gradX)) gradX = (255 * ((gradX - minVal) / (maxVal - minVal))) gradX = gradX.astype("uint8")print (np.array(gradX).shape) cv_show('Input_Sobel_gradX',gradX)


# 通過閉操作(先膨脹,再腐蝕)將數字連在一起. 將本是4個數字的4個框膨脹成1個框,就腐蝕不掉了 gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) cv_show('Input_CLOSE_gradX',gradX)# THRESH_OTSU會自動尋找合適的閾值,適合雙峰,需把閾值參數設置為0 thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] cv_show('Input_thresh',thresh)# 再來一個閉操作 thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) # 填補空洞 cv_show('Input_thresh_CLOSE',thresh)# 計算輪廓 thre_,threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = threshCnts cur_img = image.copy() cv2.drawContours(cur_img,cnts,-1,(0,0,255),3) cv_show('Input_Contours',cur_img) locs = []




# 遍歷輪廓 for (i, c) in enumerate(cnts): # 計算矩形(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h) # 選擇合適的區域,根據實際任務來,這里的基本都是四個數字一組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]) output = [] # 遍歷每一個輪廓中的數字 for (i, (gX, gY, gW, gH)) in enumerate(locs): # 遍歷每一組大輪廓(包含4個數字) # initialize the list of group digitsgroupOutput = [] # 根據坐標提取每一個組(4個值)group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5] # 往外擴一點 # cv_show('group',group) # 1.預處理 # 二值化的groupgroup = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]group_name = 'Input_group_' + str(i)cv_show(group_name,group)cv2.imwrite('./credit_card_01/' + group_name + '.jpg',group) # 計算每一組的輪廓 這樣就分成4個小輪廓了dig_,digitCnts,hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # 排序digitCnts = contours.sort_contours(digitCnts,method="left-to-right")[0]# 2.計算并匹配每一組中的每一個數值for c in digitCnts: # c表示每個小輪廓的終點坐標z=0 # 找到當前數值的輪廓,resize成合適的的大小(x, y, w, h) = cv2.boundingRect(c) # 外接矩形roi = group[y:y + h, x:x + w] # 在原圖中取出小輪廓覆蓋區域,即數字roi = cv2.resize(roi, (57, 88))roi_name = 'roi_'+str(z)# cv_show(roi_name,roi)# 計算匹配得分: 0得分多少,1得分多少...scores = [] # 單次循環中,scores存的是一個數值 匹配 10個模板數值的最大得分 # 在模板中計算每一個得分#digits的digit正好是數值0,1,...,9;digitROI是每個數值的特征表示for (digit, digitROI) in digits.items():# 進行模板匹配, res是結果矩陣result = cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF) # 此時roi是5 digitROI是0 依次是1,2.. 匹配10次,看模板最高得分多少(_, score, _, _) = cv2.minMaxLoc(result) # score是最大值scores.append(score) # 10個最大值# 得到最合適的數字groupOutput.append(str(np.argmax(scores))) # 取最大值z = z+1# 畫出來cv2.rectangle(image, (gX - 5, gY - 5),(gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# putText參數:圖片,添加的文字,左上角坐標,字體,字體大小,顏色,字體粗細cv2.putText(image, " ".join(groupOutput), (gX, gY - 15),cv2.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))) cv2.imshow("Output_image", image) cv2.waitKey(0)


總結

以上是生活随笔為你收集整理的OpenCV-信用卡数字识别-03的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。