使用OpenCV+Keras輕鬆破解驗證碼

選自Mediumnode

做者:Adam Geitgey編程

機器之心編譯後端

參與:李澤南、蔣思源安全


登陸網站時必須輸入的圖片驗證碼能夠用來識別訪問者究竟是人仍是機器——這同時也是某種程度上的「圖靈測試」,人工智能研究者們尋求破解的方向,讓計算機學會破解驗證碼,咱們就距離通用智能更近了一步( 前不久 Vicarious 發表在 Science 上的論文就介紹了一種用於破解圖片驗證碼的機器學習新模型)。今天,破解全世界最爲流行的圖片驗證碼須要多久?本文做者 Adam Geitgey 告訴你:僅需 15 分鐘。


每一個人都討厭 CAPTCHA——這些惱人的圖片中包含你必須輸入的文字,正確地填寫它你才能訪問網站。CAPTCHA 全稱「全自動區分計算機和人類的公開圖靈測試(Completely Automated Public Turing test to tell Computers and Humans Apart)」,旨在確認訪問者是真正的人類,防止惡意程序的入侵。然而,隨着深度學習和計算機視覺技術的發展,如今這些認證方法能夠被咱們輕鬆破解了。bash

最近,我正在讀 Adrian RoseBrock 撰寫的《Deep Learning for Computer Vision with Python》。在這本書中,Adrian 利用機器學習破解了 E-ZPass New York 網站上的 CAPTCHA 驗證碼:網絡

在這裏,Adrian 沒有接入生成 CAPTCHA 圖片應用源代碼的權限。爲了破解這樣的系統,咱們必須找到數百張示例圖片,而後訓練機器學習模型來破解它。架構

可是若是咱們想要破解開源的 CAPTCHA 系統——在這裏咱們擁有全部源代碼的訪問權,事情又會如何呢?框架

我訪問了 http://WordPress.org (http://wordpress.org/) 插件登記網站,在其中搜索「CAPTCHA」。結果中顯示的第一個內容是「Really Simple CAPTCHA」,已經擁有超過 100 萬次活躍安裝了:https://wordpress.org/plugins/really-simple-captcha/dom

重點在於,這裏有它的源代碼!有了生成 CAPTCHA 圖片的源代碼,咱們就能夠輕鬆破解驗證碼了。在這裏,爲了讓任務更具挑戰性,咱們先給本身添加一點限制:咱們能不能在 15 分鐘內破解它?Let's try it!機器學習

Note:這並不意味着咱們在批評「Really Simple CAPTCHA」插件及其做者。目前,插件的做者已表示該款驗證碼已經再也不安全,並推薦用戶尋找其餘更加具備安全性的認證方式。但若是你真的是這 100 萬用戶中的一員,或許你應該有所防備了:)


挑戰

首先,咱們須要作好計劃,讓咱們看看 Really Simple CAPTCHA 生成的圖片是什麼樣子。在 Demo 站中,咱們看到了這樣的情景:

一個 CAPTCHA 圖片範例


看起來它會生成由四個字符組成的圖片。讓咱們在這個插件的 PHP 源代碼裏面確認一下:

public function __construct() {
        /* Characters available in images */
        $this->chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
        /* Length of a word in an image */
        $this->char_length = 4;
        /* Array of fonts. Randomly picked up per character */
        $this->fonts = array(
            dirname( __FILE__ ) . '/gentium/GenBkBasR.ttf',
            dirname( __FILE__ ) . '/gentium/GenBkBasI.ttf',
            dirname( __FILE__ ) . '/gentium/GenBkBasBI.ttf'
        );
複製代碼

沒錯,它會生成四個字母/數字組成的 CAPTCHA 驗證碼,每一個字符的字體各不相同,在代碼中咱們也能夠看出驗證碼中不會包含「O」或者「I」,由於這兩個字母極可能會讓人與數字產生混淆。因此,咱們共有 32 個數字或字母須要識別。沒問題!

至此用時:2 分鐘


咱們須要的工具

在開始破解以前,咱們先要介紹一下行動所需的工具:


Python 3

Python 是目前人工智能領域中最爲流行的編程語言,包含多種機器學習和計算機視覺庫。


OpenCV

OpenCV 是計算機視覺和圖像處理任務上的流行框架。在這裏,咱們須要使用 OpenCV 來處理 CAPTCHA 生成的圖像,OpenCV 擁有 Python API,因此咱們能夠直接使用 Python 調用它。


Keras

Keras 是一個使用 Python 編寫的深度學習框架。他可讓咱們更加輕鬆地定義、訓練和使用深度神經網絡——僅需編寫不多的代碼。


TensorFlow

TensorFlow 是谷歌推出與維護的機器學習庫,也是目前人工智能領域裏最爲流行的框架。咱們會在 Keras 之上寫代碼,但 Keras 實際上並無實現神經網絡運算的方法——它須要使用 TensorFlow 做爲後端來完成具體的工做。


好了,讓咱們回到挑戰之中。


創立數據集

想要訓練任何機器學習系統,咱們都須要相應的數據集。爲了破解 CAPTCHA 驗證碼系統,咱們須要這樣的訓練數據:

看起來少不了大量的標註工做。不過在這裏咱們有了 WordPress 插件的源代碼,咱們能夠稍稍修改插件,讓它自動輸出 10,000 個 CAPTCHA 圖片,以及相應的正確答案。

在對源代碼的幾分鐘破解以後(只要簡單地加個『for』循環),咱們就擁有了一個內含 10,000 張 PNG 圖片的訓練集,而圖片的正確答案就是每張圖片的文件名:

Note:在這部分我不會給你示例代碼。由於本文面向教學,但願各位不會真的去破解各家 WordPress 網站。不過這裏我會給你 10,000 張生成的圖片讓你們用於復現。

至此用時:5 分鐘


簡化問題

如今咱們已經有了訓練數據,咱們能夠直接用它來訓練一個簡單的神經網絡:

由於有了足夠的數據,這種方法將能很好地工做,但咱們可使問題變得更簡單。由於問題越簡單、訓練數據越少,咱們解決問題所須要的計算力就越少,畢竟咱們總共只有 15 分鐘的時間。

幸運的是,一個 CAPTCHA 圖像由四個符合組成,所以咱們能夠以某種方式將圖像分割開以令每張圖像只有一個符號。這樣的話咱們只需訓練神經網絡識別單個字符就好了。

咱們並不能手動地用 Photoshop 等圖像軟件將它們分割開,由於訓練圖像總共有 1 萬張。此外,咱們也不能將圖像切分爲四個等大小的圖像塊,由於 CAPTCHA 會隨機地將這些不一樣的字符放置在不一樣的水平線上,以下所示:


幸運的是,咱們能使用已有的方法自動完成這一部分。在圖像處理中,咱們常常須要檢測有相同色彩的像素塊,這些連續像素塊的邊界能夠稱之爲輪廓。而 OpenCV 有一個內置的 findContours() 函數能夠檢測這些輪廓的區域。

因此咱們原始的 CAPTCHA 圖像爲以下所示:



而後咱們將該圖像轉換爲純淨的黑白像素點(即採用色彩閾值的方法),所以咱們將很容易尋找到連續的輪廓邊界:

下面咱們使用 OpenCV 的 findContours() 函數以檢測包含連續相同像素塊的分離部分:

隨後將每一個區域保存爲一個單獨的圖像文件就很是簡單了,並且咱們也知道每張圖像從左到右有四個字符,所以咱們能夠在保存的時候使用這種知識標註各個字符。咱們只須要按順序保存它們,並將每一張圖像保存爲對應的字符名。

可是還有一個問題,有些 CAPTCHA 圖像包含重疊的字符:

這就意味着咱們極可能會將兩個字符抽取爲一個分割區域:

若是咱們不解決這個問題,那麼咱們最後就會建立一個很是糟糕的訓練集。咱們須要解決這個問題,以避免模型會將兩個重疊的字符識別爲一個。

這裏有一個簡單的解決方案,若是字符輪廓的寬要比高長一些,那麼頗有可能這一個切份內就包含了兩個字符。所以咱們能夠將這種連體的字符拆分爲兩半,並將它們視爲單獨的字符。

咱們將寬度大於高度必定數值的圖像拆分爲兩個數值,雖然這種方法很是簡單,但在 CAPTCHA 上卻十分有效。

如今咱們有方法抽取獨立的字符,所以咱們須要將全部的 CAPTCHA 圖像都執行這種處理。咱們的目標是收集每一個字符的不一樣變體,並將單個字符的全部變體保留在一個文件夾中。

上圖展現了字符「W」的抽取狀況,咱們最後從 1 萬張 CAPTCHA 圖像中獲取了 1147 張不一樣的「W」。處理完這些圖像後,咱們總共大約花了 10 分鐘。


構建並訓練神經網絡

由於咱們一次只須要識別單個字符,因此並不須要一個複雜的神經網絡架構,且識別這種字母與數字的任務要比其它識別複雜圖像的任務簡單地多。所以咱們使用了一個簡單的卷積神經網絡,它一共包含兩個卷積層與兩個全鏈接層。

若是咱們使用的是 Keras,那麼只須要幾行代碼就能構建一個神經網絡架構:

# Build the neural network!
model = Sequential()
# First convolutional layer with max pooling
model.add(Conv2D(20, (5, 5), padding="same", input_shape=(20, 20, 1), activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# Second convolutional layer with max pooling
model.add(Conv2D(50, (5, 5), padding="same", activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# Hidden layer with 500 nodes
model.add(Flatten())
model.add(Dense(500, activation="relu"))
# Output layer with 32 nodes (one for each possible letter/number we predict)
model.add(Dense(32, activation="softmax"))
# Ask Keras to build the TensorFlow model behind the scenes
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
複製代碼

如今開始訓練

# Train the neural network
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), batch_size=32, epochs=10, verbose=1)
複製代碼

在通過 10 個 Epoch 的訓練後,咱們的訓練準確度能夠到達 100%,所以咱們就能終止程序以完成整個模型的訓練。因此最後咱們一共花了 15 分鐘。


使用訓練後的模型解決 CAPTCHA 識別問題

如今咱們利用已訓練的神經網絡能夠輕鬆識別 CAPTCHA 驗證碼:

  1. 在網站上使用 WordPress 插件獲取真正的 CAPTCHA 驗證碼;
  2. 將 CAPTCHA 圖像分割爲四個獨立的字符塊,這裏使用的方法和建立訓練集的方法同樣;
  3. 調用神經網絡對這四個獨立的字符塊進行預測;
  4. 將四個預測結果排列以做爲該 CAPTCHA 驗證碼的返回結果。

或者咱們能夠直接使用命令行運行:

試試看!

若是你想本身試驗一下,這裏有代碼:https://s3-us-west-2.amazonaws.com/mlif-example-code/solving_captchas_code_examples.zip

這個壓縮文件包中包含 10,000 張實例圖片以及本文中涉及的每一步的代碼。其中還有 README 文件告訴你如何運行它。

若是你想要深刻了解代碼背後的知識,那麼最好讀一讀那本《Deep Learning for Computer Vision with Python》。它涵蓋了不少細節,並介紹了大量示例,若是你對解決現實生活中困難問題的示例感興趣,那麼它或許很適合你。



原文連接:medium.com/@ageitgey/h…

相關文章
相關標籤/搜索