基於python簡單圖像處理,識別驗證碼

基本識別原理概述:

1、每一幅圖像在構成上,都是由一個個像素組成的矩陣,每一個像素為單元格。

2、 彩色圖像的像素的由三原色(紅,綠,藍)構成元組,灰度圖像的像素是一個單值,每個像素的值範圍為(0,255)。

問題來源

某系統門戶登陸界面如下:

基於python簡單圖像處理,識別驗證碼

現在我們要實現自動的驗證碼識別。

圖像特徵

基於python簡單圖像處理,識別驗證碼

首先,我們仔細觀察下這個驗證碼圖像,可以發現一些固定特徵:

基於python簡單圖像處理,識別驗證碼

1、驗證碼中的字符數始終為6,並且是灰度圖像。

2、字符間的間隔看起來每次都一樣。

3、 每個字符都是完全定義的。

4、圖像有許多雜散的黑暗像素,以及穿過圖像的線條作為干擾因素。

圖像分析

所以我最終下載了一個這樣的圖像,並使用一個工具(binary-image)以二進制形式可視化圖像(0表示黑色,1表示白色像素)。

基於python簡單圖像處理,識別驗證碼

我的觀察沒錯,圖像尺寸為45x180,每個字符分配30個像素的空間來適配,從而使它們間隔比較均勻。

因此,取得了驗證碼識別路上的第一步,結果:

把圖像裁剪成6個不同的部分,每個部分的寬度為30像素。

python圖像裁剪

我們璇兒Python作為原型語言,因為它的庫最容易使用和部署。

經過簡單搜索,我找到了PIL庫。還用到了Image模塊,用來操作圖像進行字符裁剪並將圖像作為加載為數字矩陣。

字符部分裁剪

圖像裁剪的語法是:

from PIL import Image

image = Image.open("filename.png")

cropped_image = image.crop((left, upper, right, lower))

比如要裁剪第一個字符:

from PIL import Image

image = Image.open("captcha.png").convert("L")

cropped_image = image.crop((0, 0, 30, 45))

cropped_image.save("cropped_image.png")

得到的圖像為:

基於python簡單圖像處理,識別驗證碼

我將他打包到一個循環中,編寫了一個簡單的腳本,從該站點獲取500個驗證碼圖像,並將所有裁剪後的字符保存到一個文件夾中。回顧我們上一部分觀察到的特徵第三點,每個字符都有明確定義。

圖像去雜,清理干擾因子

為了"清理"圖像中的裁剪掉干擾因素(刪除不必要的線和點),我們使用一個很簡單的算法:

字符中的所有像素都是純黑色(0)。如果它不是完全黑色的,將它當成白色的。因此,對於值大於0的每個像素,將給其重新賦值為255。使用load()函數將圖像轉換為45x180數字矩陣,然後對其進行處理。

pixel_matrix = cropped_image.load()

for col in range(0, cropped_image.height):

for row in range(0, cropped_image.width):

if pixel_matrix[row, col] != 0:

pixel_matrix[row, col] = 255

image.save("thresholded_image.png")

基於python簡單圖像處理,識別驗證碼

為了清晰起見,我將代碼應用於原始圖像。

原版的:

基於python簡單圖像處理,識別驗證碼

做過算法矯正的圖

基於python簡單圖像處理,識別驗證碼

你可以看得到,並非完全黑暗的所有像素都被刪除了。比如通過圖像的線。上述方法在圖像處理中的專業術語叫做閾值處理,當然還有很多處理方法,閾值處理事最簡單實用的方法。

去除圖像中的黑點

回顧觀察到特徵的第四點,圖像中有許多散雜黑點像素的干擾因子。

循環遍歷圖像矩陣,並且如果相鄰像素是白色的,並且與相鄰像素相對的像素也是白色的,並且中心像素是黑色的,則設定中心像素為白色。

for column in range(1, image.height - 1):

for row in range(1, image.width - 1):

if pixel_matrix[row, column] == 0 and pixel_matrix[row, column - 1] == 255 and pixel_matrix[row, column + 1] == 255 :

pixel_matrix[row, column] = 255

if pixel_matrix[row, column] == 0 and pixel_matrix[row - 1, column] == 255 and pixel_matrix[row + 1, column] == 255:

pixel_matrix[row, column] = 255

基於python簡單圖像處理,識別驗證碼

結果為:

基於python簡單圖像處理,識別驗證碼

你可以看到,經過以上步驟的處理,圖像已經只剩下字符框架了。雖然有些字符已經丟失了一些基礎像素,但是每個字符的圖像骨架基本上都完備。當然這個是必須的,我們做這麼多處理的主要原因是為每個可能的字符都截取生成合適字符圖。

構建字符圖庫

我將上述算法裁剪得到的所有字符圖像都存儲於文件夾下。下一個任務是為屬於"A-Z0-9"的每個字符找到至少一個樣本圖像。這一步就像"訓練"步驟,我手動為每個字符選擇了一個字符圖像並對其更名。

完成這一步後,每個字符都有一幅骨架圖像!

基於python簡單圖像處理,識別驗證碼

選擇最優的字符圖

我還運行了其他幾個腳本,確保每一個字符的圖像中都有最佳的圖像,例如,如果有20個'A'的字符圖像,暗色(1)數量最少的圖像顯然是噪聲最少的圖像,因此最適合作為骨架圖像。選擇的原則:

一個按照字符排序的相似圖像(約束條件:黑像素數量大小,並且相似度> = 90~95%)。

一個從每個分組字符獲得最佳圖像。

因此,到目前為止,我們生成了一個像素圖像庫。我們將它們轉換為像素矩陣,並將"位圖,把字符圖轉為數字點陣SON文件

識別算法

最後,這就是獲取任何新的驗證碼圖像的算法:

使用相同的算法儘量減少新圖像中不必要的干擾因子

對於新驗證碼圖片中的每字符,強制通過生成的JSON文件舉證來匹配,基於相應的黑像素匹配來計算相似度。

如果一個像素是黑的並且在圖像中的位置恰好是破解驗證碼,並且像素在我們的字符庫中的骨架圖像/位圖中的相同位置處也是的,則計數會遞增1。

與骨架圖像中黑暗像素的數量做對比,計算匹配百分比,選擇具有最高匹配百分比的字符就是識別結果的字符。

基於python簡單圖像處理,識別驗證碼

結果演示

最終結果如下:

基於python簡單圖像處理,識別驗證碼

得到的字符為Z5M3MQ, 驗證碼被成功識別出來了。


分享到:


相關文章: