Python OpenCV 365 天學習計劃,與橡皮擦一起進入影像領域吧,本篇博客是這個系列的第 53 篇,
該系列文章導航參考:https://blog.csdn.net/hihell/category_10688961.html
Python OpenCV
- 學在前面
- 提取卡片相關數字
- 橡皮擦的小節
學在前面
從本篇博客起,我們將實際完成幾個小案例,第一個就是銀行卡號識別,預計本案例將寫 5 篇左右的博客才可以完成,一起加油吧,
本文的目標是最侄訓取一套招商銀行卡,0~9 數字的圖,對于下圖的數字,我們需要提取出來,便于后續模板匹配使用,不過下圖中找到的數字不完整,需要找到盡量多的卡片,然后補齊這些數字,

提取卡片相關數字
先對上文中卡片中的數字進行相關提取操作,加載圖片的灰度圖,獲取目標區域,在畫板中模擬一下坐標區域,為了便于進行后續的操作,

具體代碼如下:
import cv2 as cv
import numpy as np
# 讀取灰度圖
src = cv.imread("./ka1.jpg", 0)
# 尋找卡號目標區域
roi = src[142:168, 42:360]
# cv.imshow("roi",roi)
獲取到的圖片如下,發現右側邊緣缺少一部分內容,對目標區域坐標進行微調,

修改之后的代碼如下,你如果使用的圖片與橡皮擦不一致,注意進行修改,
# 尋找卡號目標區域
roi = src[142:168, 46:364]
cv.imshow("roi",roi)

消除噪音,可以增加模糊卷積操作,分別測驗均值模糊,中值模糊,高斯模糊效果,
# 模糊卷積操作
blur_roi = cv.blur(roi,(5,5))
cv.imshow("blur_roi",blur_roi)
med_roi = cv.medianBlur(roi,5)
cv.imshow("med_roi",med_roi)
gau_roi = cv.GaussianBlur(roi,(7,7),0)
cv.imshow("gau_roi",gau_roi)
測驗不同的卷積核效果,選擇一個合適的即可,我這里發現卷積核為 (7,7) 的時候,高斯模糊效果不錯,可以去噪,

接下來進行二值化操作,
# 對目標區域進行二值化操作
ret, thresh = cv.threshold(
gau_roi, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("thresh", thresh)

二值化處理完畢之后,發現還存在一些白色區域的點,需要去除掉,這里使用了形態學里面的腐蝕操作,
# 腐蝕
kernel = np.ones((3, 4), np.uint8)
dst = cv.erode(thresh, kernel=kernel)

腐蝕之后在進行膨脹,讓原有的數字區域變的明顯,最后的圖片是進行之后的效果,關于卷積核你可以自行調整,
# 腐蝕
kernel = np.ones((3, 4), np.uint8)
erode_dst = cv.erode(thresh, kernel=kernel)
cv.imshow("erode_dst", erode_dst)
# 膨脹
kernel = np.ones((4, 4), np.uint8)
dilate_dst = cv.dilate(erode_dst, kernel=kernel)

下面進行外輪廓檢測,檢測之后發現恰好有 16 個輪廓,也就對應了 16 個數字區域,
# 檢測外輪廓
# 只檢測外輪廓
contours, hierarchy = cv.findContours(dilate_dst, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
print(len(contours))

對輪廓面積進行一下輸出,為了防止出現非目標區域,可以進行一下基本的判斷,當羅闊面積大于 80 的時候才進行展示,
target_list = []
# 輪廓判斷
for cnt in contours:
# 輪廓面積
area = cv.contourArea(cnt)
print(area)
if area > 79:
target_list.append(cnt)
print(len(target_list))

有這些引數之后,就可以對灰度圖進行裁切了,基于外接矩形獲取目標區域,我直接做了回圈展示,
for index, cnt in enumerate(target_list):
# 外接矩形
x, y, w, h = cv.boundingRect(cnt)
# 在二值化的影像上進行目標區域獲取
c_roi = roi[y:y+h, x:x+w]
# 調整影像大小
# big_roi = cv.resize(c_roi, dsize=(0, 0), fx=2, fy=2)
# big_roi = cv.resize(c_roi, dsize=(0, 0))
cv.imshow("big_roi"+str(index), c_roi)
# cv.imwrite(f"./numbers/ka_{index}.png", big_roi)

接下來放大圖片對其進行保存即可,得到如下圖片串列,至此,已經獲取到 1、4、6、8 幾個數字,下面在切換到另一張卡片,去獲取其他數字即可,注意圖片大小保持一致,
big_roi = cv.resize(c_roi, dsize=(42, 66))
# cv.imshow("c_roi"+str(index), c_roi)
cv.imwrite(f"./numbers/ka1_{index}.png", big_roi)

新的影像注意調整目標區域,獲取素材,已經獲取到 1、2、4、5、6、7、8 幾個數字

反復迭代這個辦法,知道 0~9 個數字獲取完整,找到所有數字之后,對該檔案夾中的所有檔案進行二值化操作,
import cv2 as cv
import os
def walk_file(file):
for root, dirs, files in os.walk(file):
for f in files:
file = os.path.join(root, f)
# 讀取灰度圖
basename = os.path.basename(file)
filename = basename.split(".")[0]
src = cv.imread(file, 0)
ret, thresh = cv.threshold(src, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# cv.imshow("thresh", thresh)
cv.imwrite(f"./numbers/001_{filename}_bit.png", thresh)
cv.waitKey()
cv.destroyAllWindows()
if __name__ == "__main__":
walk_file("./numbers")
二值化之后,挑選出比較清晰的數字即可,如果發現存在不清楚的,可以在尋找資源進行提取,銀行里面 8 真的是太多了,

橡皮擦最后調整之后,得到的結果如下所示,信用卡卡號識別的第一步算是準備好了,

橡皮擦的小節
今天也碰到了一些問題,最難的問題,就是顏色相近,提取不出來前面的數字,
希望今天的 1 個小時(貌似不太夠)你有所識訓,我們下篇博客見~
相關閱讀
技術專欄
- Python 爬蟲 100 例教程,超棒的爬蟲教程,立即訂閱吧
- Python 爬蟲小課,精彩 9 講
今天是持續寫作的第 99 / 100 天,
如果你想跟博主建立親密關系,可以關注同名公眾號 夢想橡皮擦,近距離接觸一個逗趣的互聯網高級網蟲,
博主 ID:夢想橡皮擦,希望大家點贊、評論、收藏,
CSDN認證博客專家
高級產品經理
互聯網從業者
業余編程愛好者
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266674.html
標籤:python
