7. cv2.putText(img, text, loc, text_font, font_scale, color, linestick)
# 參數說明:img表示輸入圖片,text表示需要填寫的文本str格式,loc表示文本在圖中的位置,font_size可以使用cv2.FONT_HERSHEY_SIMPLEX,
font_scale表示文本的規格,color表示文本顏色,linestick表示線條大小
信用卡數字識別:
信用卡
數字模板
涉及到的內容:主要是采用模板匹配的思想
思路:
第一部分:數字模板提取數字
第一步:讀入圖片
第二步:進行灰度化和二值化處理,這里的二值化使用的cv2.THRESH_BINARY_INV, 將黑色的數字轉換為白色
第三步:使用cv2.findContours獲得輪廓信息
第四步:對contours根據外接矩陣的x的位置,從左到右進行排序
第五步:遍歷contours,使用cv2.boudingRect外接矩形獲得輪廓的位置信息,提取數字輪廓的圖片,與索引組成輪廓信息的字典
import cv2 import numpy as np import my_utis def cv_show(img, name): cv2.imshow(name, img) cv2.waitKey(0) cv2.destroyAllWindows() # 第一部分:數字模板准備 # 第一步:讀入圖片 template = cv2.imread('images/ocr_a_reference.png') # 第二步:進行灰度值和二值化轉換 gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) cv_show(gray, 'gray') # 將黑色轉換為白色,將白色轉換為黑色 thresh = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY_INV)[1] cv_show(thresh, 'thresh') # 第三步:找出輪廓值使用cv2.findContours找出輪廓值,cv2.RETR_EXTERNAL表示圖像的外輪廓 binary, contours, h = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 第四步:對輪廓值進行排序, 因為contours輪廓不是按循序排列的,因此根據contours所在的位置從左到右進行排序 contours = my_utis.contours_sort(contours) # 第五步: 遍歷模板,使用cv2.boudingRect獲得輪廓的位置,提取位置對應的圖片,與數字結合構造成模板字典 dict_template = {} for i, contour in enumerate(contours): # 畫出其外接矩陣,獲得其位置信息 x, y, w, h = cv2.boundingRect(contour) template_img = binary[y:y+h, x:x+w] # 使用cv2.resize變化模板的大小 template_img = cv2.resize(template_img, (55, 88)) # cv_show(template_img, 'template_img') dict_template[i] = template_img
第二部分:對圖片進行預處理,提取包含數字信息的4個輪廓的位置信息
第一步:讀入圖片
第二步:調用函數,擴大圖片的面積,並進行灰度化
第三步:使用禮帽tophat 原始圖片 - 先腐蝕后膨脹的圖片,為了去除背景,使得線條更加的突出
第四步:使用sobel算子cv2.Sobel 找出圖片中的邊緣信息,即進行圖像的梯度運算
第五步:使用閉運算 先膨脹再腐蝕, 將圖片上的一些相近的數字進行相連,使得其連成一塊
第六步:使用cv2.threshold 將圖片進行二值化操作
第七步:再次使用閉運算對圖片中的內部缺失的位置再次進行填充,使用不同的卷積核
第八步:重新計算輪廓值,遍歷輪廓,根據長寬比和長寬的數值,篩選出符合條件的輪廓的locs,並對locs根據x的大小進行排序
# 第二部分:對圖片進行預處理,提取包含數字信息的輪廓塊 rectKernel = np.ones([3, 9]) # 構造的卷積核,用於進行閉運算,和禮帽運算 sqKernel = np.ones([6, 6]) # 構造的卷積核,用於進行閉運算 # 第一步: 讀入圖片 img = cv2.imread('images/cr' 'edit_card_01.png') # 第二步:擴大圖片的維度,進行灰度化轉換 img = my_utis.resize(img, width=300) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) print(gray.shape) #第三步:使用禮帽操作,使得亮度更加的明顯 tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) cv_show(tophat, 'tophat') # 第四步:使用sobel算子獲得邊緣信息,ksize=-1表示sobel算子的維度為(3, 3) sobel = cv2.Sobel(tophat, cv2.CV_64F, 1, 0, ksize=-1) # 取絕對值操作 sobel = np.absolute(sobel) sobel_img = 255 * (sobel - sobel.min()) / (sobel.max() - sobel.min()) sobel_img = np.uint8(sobel_img) cv_show(sobel_img, 'sobel_img') # 第五步:使用閉操作, 先腐蝕,再膨脹將字母進行合並 close = cv2.morphologyEx(sobel_img, cv2.MORPH_CLOSE, rectKernel) cv_show(close, 'close') # 第六步:進行二值化操作 binary = cv2.threshold(close, 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] cv_show(binary, 'binary') # 第七步:再使用閉操作,對內部空白區域進行填充 close2 = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, sqKernel) cv_show(close2, 'close2') # 第八步:使用cv2.findContours進行輪廓的識別 binary, contours, h = cv2.findContours(close2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) locs = [] # 循環輪廓,將符合條件的contours加入 for i, contour in enumerate(contours): x, y, w, h = cv2.boundingRect(contour) acr = int(w/h) if acr > 2.5 and acr < 4.0: if (w > 40 and w<55) and (h > 10 and h < 20): locs.append((x, y, w, h)) # 對locs根據x從左到右進行排序 locs = sorted(locs, key=lambda x: x[0])
第三部分:遍歷每個locs,提取其中的數字,與模板數字做匹配,判斷數字屬於模板中的哪個數字
第一步:遍歷locs,使用loc中的x,y, w, h 獲得信用卡中的對應圖片
第二步:對圖片進行二值化操作
第三步:使用cv2.findContours,找出其中的輪廓,對輪廓進行排序
第四步:循環輪廓,使用外接矩形的位置信息, x1, y1, w1, h1, 獲得當前輪廓對應的數字,此時已經獲得了需要預測數字的單個圖片
第五步:循環數字模板,使用cv2.matchTemplate進行模板匹配,使用cv2.minMaxLoc獲得最大的得分值,使用np.argmax輸出可能性最大的數字
print(np.shape(locs)) # 第三部分:遍歷每個locs,對其中的數字進行匹配, 判斷數字屬於模板中的哪個數字 predict_number = [] predict_loc = [] for i, loc in enumerate(locs): # 第一步:獲得輪廓對應的數字塊的圖片 x, y, w, h = loc loc_img = gray[y-5 : y+h+5, x-5: x+w+5] # 第二步:對數字塊的圖片進行二值化操作 thresh = cv2.threshold(loc_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 第三步:進行輪廓檢測, 並對輪廓進行排序操作 binary, contours, h = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 對輪廓檢測的結果按照從左到右的順序進行排序 contours = my_utis.contours_sort(contours) # 第四步:遍歷輪廓, 使用輪廓的外接矩陣獲得數字圖片,並使用cv2.resize改變圖片的大小 for i, contour in enumerate(contours): scores = [] x1, y1, w1, h1 = cv2.boundingRect(contour) predict_loc.append((x1-6+x, y1-6+y, w1+2, h1+2)) contour_img = thresh[y1:y1+h1, x1:x1+w1] contour_img = cv2.resize(contour_img, (55, 88)) # cv_show(contour_img, 'contour') # 進行模板匹配 # 第五步:遍歷數字模板,使用matchTemplate找出與圖片匹配度最高的數字 for templates in dict_template.values(): ret = cv2.matchTemplate(contour_img, templates, cv2.TM_CCOEFF_NORMED) _, score, _, _ = cv2.minMaxLoc(ret) scores.append(score) predict_number.append(str((np.argmax(scores))))
第四部分:在原始的圖片進行作圖操作
第一步:使用cv2.rectangle畫出矩陣
第二步:使用cv2.putText加上文字信息
for i in range(len(predict_number)): x, y, w, h = predict_loc[i] # 第一步:畫出矩形框 cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 1) print(predict_number[i]) # 第二步:在圖片上加上文本 cv2.putText(img, predict_number[i], (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2) cv_show(img, 'img')
最終的效果圖
import cv2 import numpy as np def contours_sort(contours, method=0): if method == 0: contours = sorted(contours, key=lambda x:cv2.boundingRect(x)[0]) else: contours = sorted(contours, key=lambda x:cv2.boundingRect(x)[0], reverse=True) return contours def resize(image, width=None, height=None, inter=cv2.INTER_AREA): h, w = image.shape[:2] if width is None and height is None: return image if width is None: r = height / float(h) dim = (int(w * r), height) else: r = width / w dim = (width, int(r * h)) resized = cv2.resize(image, dim, interpolation=inter) return resized
調用的函數my_utis.py