1. 程式人生 > >python 基於機器學習—深度學習識別驗證碼

python 基於機器學習—深度學習識別驗證碼

一、前言

開發環境:Anaconda | python 3.5 —pycharm / jupyter notebook

專案的整個識別流程:

① 驗證碼清理並生成訓練集樣本 ② 驗證碼特徵提取 ③ 擬合識別模型 ④ 識別模型測試

關於資料集

二、驗證碼清理並生成訓練集樣本

2.1 獲取影象和標籤
"""
    :param input_path:                影象輸入目錄
    :return: image_array, image_label:獲取的影象,標籤
"""
def read_captcha(input_path):
    image_array = []
    image_label =
[] file_list = os.listdir(input_path) # 獲取captcha檔案 for file in file_list: image = Image.open(input_path+ '/' + file) # 開啟圖片 file_name = file.split(".")[0] # 獲取檔名,此為圖片標籤 image_array.append(image) image_label.append(file_name) return
image_array, image_label
2.2 初步去除驗證碼的噪點
def image_transfer(image_arry):
    """
    :param image_arry:   影象list,每個元素為一副影象
    :return: image_clean:清理過後的影象list
    """
    image_clean = []
    for i, image in enumerate(image_arry):
        image = image.convert('L')             # 轉換為灰度影象,即RGB通道從3變為1
im2 = Image.new("L", image.size, 255) for y in range(image.size[1]): # 遍歷所有畫素,將灰度超過閾值的畫素轉變為255(白) for x in range(image.size[0]): pix = image.getpixel((x, y)) if int(pix) > threshold_grey: # 灰度閾值 im2.putpixel((x, y), 255) else: im2.putpixel((x, y), pix) image_clean.append(im2) return image_clean ------------------------------------------------------------------ #或者 import cv2 def image_transfer(image_arry) img_gray = cv2.cvtColor(image_arry, cv2.COLOR_BGR2GRAY) # 設定閾值(閾值大小影響去噪效果) 二值化去除噪點 (_, thresh) = cv2.threshold(img_gray, 90, 255, cv2.THRESH_BINARY) return thresh
2.3 影象細清理

通過粗清理的辦法,無法完全去除所有噪聲點。此處引入了更細粒度的清理方法。 主要有3大步驟: step 1:找出影象中所有的孤立點; step 2:計算黑色點近鄰9宮格中黑色點個數,若小於等於2個,那麼認為該點為噪聲點; step 3:去除所有噪聲點。

2.4 字元切割

去除孤立點後,我們還是沒法一下子就識別出這四個字元,需要對經過處理後的圖片進行切分。 切割方式主要有一下步驟: step 1:找出圖片中所有分離影象的開始結束位置。遍歷width&height,當每出現一個黑色點,記為該字元開始位置;當新的一列出現全白色點,那麼記為結束位置。[(8, 9), (14, 22), (29, 38), (42, 50), (57, 66)] step 2:儘管經過清理後,還是可能存在噪聲點。在找到所有切割開始結束位置後,計算並選出(結束值-開始值)最大的切割位置。[(14, 22), (29, 38), (42, 50), (57, 66)]

def image_split(image):
    """
    :param image:單幅影象
    :return:     單幅影象被切割後的影象list
    """
    inletter = False    #找出每個字母開始位置
    foundletter = False #找出每個字母結束位置
    start = 0
    end = 0
    letters = []    #儲存座標
    for x in range(image.size[0]):
        for y in range(image.size[1]):
            pix = image.getpixel((x, y))
            if pix != True:
                inletter = True
        if foundletter == False and inletter == True:
            foundletter = True
            start = x
        if foundletter == True and inletter == False:
            foundletter = False
            end = x
            letters.append((start, end))
        inletter = False
 
    # 因為切割出來的影象有可能是噪聲點
    # 篩選可能切割出來的噪聲點,只保留開始結束位置差值最大的位置資訊
    subtract_array = []    # 儲存 結束-開始 值
    for each in letters:
        subtract_array.append(each[1]-each[0])
    reSet = sorted(subtract_array, key=lambda x:x, reverse=True)[0:image_character_num]
    letter_chioce = []    # 儲存 最終選擇的點座標
    for each in letters:
        if int(each[1] - each[0]) in reSet:
            letter_chioce.append(each)
 
    image_split_array = []    #儲存切割後的影象
    for letter in letter_chioce:
        im_split = image.crop((letter[0], 0, letter[1], image.size[1])) # (切割的起始橫座標,起始縱座標,切割的寬度,切割的高度)
        im_split = im_split.resize((image_width, image_height)) # 轉換格式
        image_split_array.append(im_split)
 
     return image_split_array[0:int(image_character_num)]

2.5 儲存到訓練集

將按上述方法切分後的單個數字、字母,儲存到新建的資料夾裡,專門用來作為模型的訓練集。

三、特徵提取

這裡我們先用HOG作為影象特徵,先提取字型的HOG特徵

list_hog_fd = [] 
for feature in image_split_array:
    fd = hog(feature.reshape((28, 28)),     # hog 特徵
             orientations=9, 
             pixels_per_cell=(14, 14), 
             cells_per_block=(1, 1), 
             visualise=False)
    list_hog_fd.append(fd)
hog_features = np.array(list_hog_fd, 'float64')

未完待續