OpenCV_信用卡识别代码_唐宇迪实战项目
PyCharm環境配置
? ? ? ? 添加將所需的兩個圖片的路徑
PyCharm中添加OpenCV庫
正式代碼:
1.導入工具包
from imutils import contours import numpy as np import argparse import cv2 import myutils2.設置圖片的路徑
# 設置參數 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", default='./images/credit_card_01.png', help="path to input image") ap.add_argument("-t", "--template", default='./ocr_a_reference.png', help="path to template OCR image") args = vars(ap.parse_args()) # 指定信用卡類型 FIRST_NUMBER = {"3": "American Express", "4": "Visa", "5": "MasterCard", "6": "Discover Card"}argparse.ArgumentParser()函數:?argparse模塊可以讓人輕松編寫用戶友好的命令行接口
????????argparse.ArgumentParser()用法解析_quantLearner的博客-CSDN博客_argparse.argumentparser
3.設置一個顯示函數,方便以后的調用
def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(500)cv2.destroyAllWindows()4.將圖像讀進來,然后進行灰度處理和二值化處理
# 讀取一個模板圖像 img = cv2.imread(args["template"]) cv_show('template', img) template = cv2.imread(args["image"]) cv_show('image', template) # 灰度圖 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.cvtColor()函數
cv2.cvtColor(p1,p2) 是顏色空間轉換函數,p1是需要轉換的圖片,p2是轉換成何種格式。
cv2.imread()和cv2.cvtColor() 的使用_靜茹秋葉的博客-CSDN博客_cv2.color_bgr2gray
cv2.threshold()簡單閥值函數
CV2簡單閾值函數:cv2.threshold()_風華明遠的博客-CSDN博客_cv2 threshold
5.計算輪廓,然后遍歷每一個輪廓,外接矩形,扣出模板,列出每一個數字對應的模板
# 計算輪廓 # cv2.findContours()函數接受的參數為二值圖,即黑白的(不是灰度圖),cv2.RETR_EXTERNAL只檢測外輪廓,cv2.CHAIN_APPROX_SIMPLE只保留終點坐標 # 返回的list中每個元素都是圖像中的一個輪廓 refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # cv版本大于3.8的,只有兩個返回值cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3) # 輪廓在二值圖上得到, 畫要畫在原圖上 cv_show('template_Contours', img) print(np.array(refCnts).shape) refCnts = myutils.sort_contours(refCnts, method="left-to-right")[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] = roicv2.findContours()函數
cv2.drawContours()函數
opencv:圖像輪廓檢測 cv2.findContours() 與 cv2.drawContours()_寧靜致遠*的博客-CSDN博客_cv2.findcontours
cv2.boundingRect()函數:矩形邊框
該段代碼中還涉及一個排序函數(myutils),該函數創建在另一個PythonFile中
myutilsFile函數
# myutils.py import cv2def 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 = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一個最小的矩形,把找到的形狀包起來x,y,h,w(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxes 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 resized6.輸入圖像的處理
# 輸入圖像處理 # 1.初始化卷積核,根據實際任務指定大小,不一定非要3*3 rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3)) sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 2.讀取輸入圖像,預處理 image = cv2.imread(args["image"]) cv_show("Input image", image) image = myutils.resize(image, width=300) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv_show("Input_gray", gray) # 3.禮帽:原始輸入-開運算結果(只剩毛刺) tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) cv_show("Input tophat", tophat) # 4.x方向上面的Sobel算子,實驗表明只加x效果更好一些 gradx = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1) gradx = np.absolute(gradx) (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)# 5.通過閉操作將數字連在一起,將本是4個數字的4個框膨脹成1個框,就腐蝕不掉了 gradx = cv2.morphologyEx(gradx, cv2.MORPH_CLOSE, rectKernel) cv_show("Input_close_gradx", gradx)# 6.THRESH_OTSU會自動尋找合適的閾值,適合雙峰,需把閾值參數設置為0 thresh = cv2.threshold(gradx, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] cv_show('Input_thresh', thresh)# 7.再來一個閉操作 thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) cv_show('Input_thresh_CLOSE', thresh)# 8.計算輪廓 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, (200, 150, 190), 3) cv_show('Input_Contours', cur_img)cv2.morphologyEx()函數
opencv-python 之 cv2.morphologyEx()_一芷泡泡的博客-CSDN博客_morphologyex python
cv2.Sobel()函數
利用cv2.Sobel()計算圖像梯度(即邊緣檢測)的細節講解_悟影生的博客-CSDN博客
7.遍歷輪廓
# 遍歷輪廓 # 1.遍歷輪廓 locs = [] # 存符合條件的輪廓 for i, c in enumerate(threshCnts):# 計算矩形x, y, w, h = cv2.boundingRect(c)ar = w / float(h)# 選擇合適的區域,根據實際任務來,這里的基本都是四個數字一組if 2.5 < ar < 4.0:if (40 < w < 55) and (10 < h < 20):# 符合的留下來locs.append((x, y, w, h)) # append函數,給列表里面添加元素 # 將符合的輪廓從左到右排序 locs = sorted(locs, key=lambda x: x[0])# 2.遍歷每一個輪廓中的數字 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_' + str(i), group)# 2.1 預處理group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 二值化的group# cv_show('group_'+str(i),group)# 計算每一組的輪廓 這樣就分成4個小輪廓了digitCnts = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]# 排序digitCnts = myutils.sort_contours(digitCnts, method="left-to-right")[0]# 2.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))# cv_show("roi_"+str(z),roi)# 計算匹配得分: 0得分多少,1得分多少...scores = [] # 單次循環中,scores存的是一個數值 匹配 10個模板數值的最大得分# 在模板中計算每一個得分# digits的digit正好是數值0,1,...,9;digitROI是每個數值的特征表示for (digit, digitROI) in digits.items():# 進行模板匹配, res是結果矩陣res = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF) # 此時roi是X digitROI是0 依次是1,2.. 匹配10次,看模板最高得分多少Max_score = cv2.minMaxLoc(res)[1] # 返回4個,取第二個最大值Maxscorescores.append(Max_score) # 10個最大值print("scores:", scores)# 得到最合適的數字groupOutput.append(str(np.argmax(scores))) # 返回的是輸入列表中最大值的位置z = z + 1# 2.3 畫出來cv2.rectangle(image, (gx - 5, gy - 5), (gx + gw + 5, gy + gh + 5), (0, 0, 255), 1) # 左上角,右下角# 2.4 putText參數:圖片,添加的文字,左上角坐標,字體,字體大小,顏色,字體粗細cv2.putText(image, "".join(groupOutput), (gx, gy - 15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)# 2.5 得到結果output.extend(groupOutput)print("groupOutput:", groupOutput)cv2.matchTemplate()模板匹配函數
cv2.minMaxLoc():函數功能:假設有一個矩陣a,現在需要求這個矩陣的最小值,最大值,并得到最大值,最小值的索引。咋一看感覺很復雜,但使用這個cv2.minMaxLoc()函數就可全部解決。函數返回的四個值就是上述所要得到的。
cv2.matchTemplate模板匹配和cv2.minMaxLoc()函數_zhaojiafu666的博客-CSDN博客_cv2.matchtemplate函數8.打印結果
# 打印結果 print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]])) print("Credit Card #: {}".format("".join(output))) cv2.imshow("Output_image", image) cv2.waitKey(0)總結
以上是生活随笔為你收集整理的OpenCV_信用卡识别代码_唐宇迪实战项目的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序上传的视频显示封面 我是阿里云
- 下一篇: 26.中继器数据的添加与删除