此文已由做者楊傑受權網易雲社區發佈。html
歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。算法
全自動區分計算機和人類的圖靈測試(Completely Automated Public Turing test to tell Computers and Humans Apart,簡稱CAPTCHA),俗稱驗證碼,是一種區分用戶是計算機和人的公共全自動程序。驗證碼的主要目的是強制人機交互來抵禦機器自動化攻擊,爲了確保服務器系統的穩定和用戶信息的安全,愈來愈多的網站採用了驗證碼技術。圖片驗證碼是目前最經常使用的一種,本文也主要討論這種驗證碼的識別。
最近在一個爬蟲項目中遇到了驗證碼,須要機器自動識別繞過。這些驗證碼大都分辨率都較低,自己信息量不大。一般被加入一種或多種干擾因素:各類背景干擾,噪聲點像素,字體形變和累疊,字符位置隨機及個數不定,反色等狀況。在網上調研了資料和文獻後,分別採用OCR識別和模板庫匹配方法對不一樣類型驗證碼進行了識別。主要過程能夠分解爲三個步驟:1.圖片清理,2.字符切分,3.字符識別。如下結合工做經驗和調研內容講解一些經常使用的驗證碼識別方法和過程。
1.圖片清理
圖片清理是爲接下來的機器學習或模板匹配階段作準備的,指經過灰度化、二值化、干擾點清理等過程,獲得比較乾淨的圖片數據,具體樣例見下表。
docker
1.1 彩色去噪
在計算機中使用最多的 RGB色彩空間,分別對應紅、綠、藍三種顏色,經過調配三個份量的比例來組成各類顏色。以最多見的32位顏色爲例,一個份量是用8位來表示,最大值是255,灰度圖是指組成顏色的三個份量相等。原始彩色圖片包含的信息量是最大的,若是驗證碼圖片中有一些利用顏色反差加的干擾點或者線條,最好能在該階段作初步清理。比較簡單的一種處理方法是採用3*3矩陣對圖像進行平滑處理,即對每一個像素取他所在3*3矩陣全部點的RGB均值,分別做爲新的RGB值。稍微作點優化,取3*3矩陣中RGB三維歐式距離最接近均值的點做爲新值。
1.2 灰度化
在彩色電視機系統中,一般使用一種叫 YUV 的色彩空間,其中Y表示亮度信號,對於人眼來講,亮度信號(Y)是最敏感的,若是將彩色圖像轉換爲灰度圖像,僅僅須要轉換並保存亮度信號就能夠。從RGB到YUV空間的Y轉換有一個很著名的心理學公式:Y = 0.299R + 0.587G + 0.114B。
而實際應用時,將係數縮放1000倍來實現整數運算:Gray = (R*299 + G*587 + B*114 + 500) / 1000 。注意後面那個除法是整數除法,因此須要加上500來實現四捨五入。該公式的另外一個簡化變種也很流行:Gray = (R*30 + G*59 + B*11 + 50) / 100。更快的算法是採用移位代替除法,因此能夠將係數縮放成 2的整數冪,再作右移操做。該整數取7從精度和速度上最合適:Gray = (R*0.299*2^7 + G*0.587*2^7 + B*0.114*2^7)>>7 = (R*38 + G*75 + B*15)>>7
1.3 二值化
爲了簡化接下來的計算,須要把灰度圖片轉化成黑白二值圖。默認狀況下值大於127的像素點被設置爲白色,其他像素點設置爲黑色。固然,這個閾值也須要根據圖片的實際狀況計算調整。通常採用直方圖統計肯定動態閾值的方法比較靠譜,白底黑字的取直方圖靠左邊的波谷位置做爲閾值,黑底白字則取直方圖右邊的波谷位置做爲閾值,將背景和字符做很好的區分。
api
以(圖A),和(圖B)爲例,對應直方圖分別爲直方圖A和直方圖B,圖A對應的動態閾值取127,而圖B的動態閾值則取241比較合適。數組
1.4 底色統一
若是是黑底白字的圖片,須要轉換成白底黑字,如以上圖B。
安全
1.5 干擾點清理
在黑白二值圖片去噪階段,經常使用的去噪方法爲聯通性去噪,一般採用8向聯通來計算連通點個數,若某個點的連通點數目小於預設的閥值,則認爲這些點都是噪聲點。這一簡單粗暴的清理方法,一般狀況下是很是有效的。
2 字符切分
該階段對前期預處理後的圖片進行切割處理,定位和分離出整幅圖片中的每一個孤立的字符主體部分。主要採用X軸和Y軸投影的方法,即統計對應座標上黑色像素點的個數。對於圖片獲得的X軸和Y軸投影分別以下。利用X軸投影能夠切割出單獨的字符,再分別利用Y軸投影,裁剪掉頂部和底部的空白部分。 bash
3. OCR軟件識別
咱們使用的是開源的OCR識別引擎Tesseract,初期由HP實驗室研發,後來貢獻給了開源軟件業,後經由Google進行優化並從新發布。調用代碼以及識別效果以下:
服務器
api = tesseract.TessBaseAPI()
api.Init(".","eng",tesseract.OEM_TESSERACT_ONLY) #初始化api.SetPageSegMode(tesseract.PSM_SINGLE_LINE) #設置爲單行字符串模式api.SetVariable("tessedit_char_whitelist", whitelist) #設置白名單stringOCR = tesseract.ProcessPagesBuffer(mBuffer, len(mBuffer), api)複製代碼
該方法的優勢是:開發量少;比較通用,適合於各類變形較少的驗證碼;對於扭曲不嚴重的字母和數字識別率高。缺點也很明顯:對於扭曲的字母和數字識別率大大下降;對於字符間有粘連的驗證碼幾乎難以正確識別;很難針對特定網站的驗證碼作定製開發。
網絡
4.模板庫匹配
4.1 創建字符模板庫
首先須要針對目標網站收集大量的驗證碼;而後根據上一章節的方法,進行圖片清理;最後按照固定的長寬值切分出字符模板圖,保存文件名帶上對應字符的標記。
app
4.2 字符匹配
首先,把目標驗證碼圖片按字符個數切分,這裏的圖片切分方法必須與模板製做時的切分方法一致,獲得與模板圖一樣大小的字符圖。接下來一般的作法是使用漢明距離或編輯距離定義類似度,並用KNN方法獲得K個最類似的字符,最後從K個字符中選取出現次數最多的那個做爲匹配結果。參考了文獻[1]中K取值和字符識別率的變化關係(以下圖)。
而後,咱們把K取值爲5。而且把類似度從新定義爲:matchScore = dotMatch^2 / (dotCaptcha * dotTemplate),其中dotMatch爲驗證碼字符圖與模板圖對應位置都是黑色點的個數,dotCaptcha爲驗證碼字符圖中黑色點個數,而dotTemplate爲模板圖中黑色點個數。取這個分母是爲了防止某些黑色點較多的模板圖在匹配度計算中始終獲得較大值。識別效果以下表:
該方法的優勢是:原理簡單直觀;能夠針對不一樣網站定製優化;對於扭曲的字母和數字識別率較高。缺點是:開發量大,須要定製開發;須要收集大量的字符圖片庫;字符變化不少的狀況,匹配次數增長速度降低;對於字符有粘連的圖片識別率低;
5. 支持向量機
支持向量機通俗來說是一種二類分類模型,其基本模型定義爲特徵空間上的間隔最大的線性分類器,其學習策略即是間隔最大化,最終可轉化爲一個凸二次規劃問題的求解。實際應用上,每每遇到的是非線性可分得狀況,所以經過核函數把低維向量映射到更高維空間,使得樣本知足線性可分。
驗證碼識別問題其實是其中單個字符識別問題,而在字符可窮舉的狀況下,好比只有英文字符和數字,單個字符識別問題實際上是一個分類問題。一個英文字母或數字表示一類,而驗證碼中切分後獲得的單個字符須要被機器自動分到某一類。通常狀況下,把單個字符的灰度圖片轉成整形數組,數組的每個元素表示圖片的一個像素,即一個特徵維度。咱們切分獲得的圖片大小爲10x16=160像素,即有160個特徵,當特徵數量多且特徵之間關係不明確時,採用支持向量機分類比較合適。
LIBSVM 是臺灣大學林智仁(Lin Chih-Jen)副教授等開發設計的一個簡單、易於使用和快速有效的SVM模式識別與迴歸的軟件包,他不但提供了編譯好的可在Windows系統的執行文件,還提供了源代碼,方便改進、修改以及在其它操做系統上應用。該軟件還有一個特色,就是對SVM所涉及的參數調節相對比較少,提供了不少的默認參數,利用這些默認參數就能夠解決不少問題;而且提供了交互檢驗(Cross Validation)的功能。主要參數使用:多類別(C-SVC=0),radial basis function(kernel_type=2),訓練和預測代碼以下。對於 這樣輕微變形的驗證碼,有字母和數字共36個類別,收集訓練樣本共778個字符圖的狀況下,單字符預測準確率接近100%:
labels = []
samples = []for ch in captchaTemplate.keys(): for table in captchaTemplate[ch]:
labels.append(ord(ch))
samples.append(map(lambda e:e/255., table))
problem = svm_problem(labels, samples)
model = svm_train(problem, '-t 2 -c 500')print len(samples)
data = map(lambda e:e/255., list(Image.open(TESTFILE).getdata(TESTFILE)))
y = ord('z')
prediction = svm_predict([y,], [data,], model)print prediction複製代碼
該方法的優勢是:無需設計快速的圖像匹配算法;只要圖片切分方法合適,對於扭曲傾斜的字母和數字識別率也較高;而且能夠針對不一樣類型的驗證碼作定製優化。缺點是:支持向量機原理比較複雜,沒法直觀解釋,須要瞭解支持向量機等機器學習方法。
6. 神經網絡
以上驗證碼識別都依賴於字符切分,切分的好壞幾乎直接決定識別的準確程度。而對於有字符粘連的圖片,每每識別率就會低不少。目前驗證碼識別最早進的是谷歌在識別「街景」圖像中門牌號碼中使用的一套的算法。該算法將定位、分割和識別等幾個步驟統一塊兒來,採用一種「深度卷積神經網絡」(deep convolutional neural network)方法進行識別,準確率能夠達到99%以上。谷歌拿自有的reCAPTCHA驗證碼作了測試,結果發現,對於難度最大的reCAPTCHA驗證碼,新算法的準確率都達到 99.8%,這可能也好於大多數人爲驗證。
驗證碼做爲一種輔助安全手段在Web安全中有着特殊的地位,瞭解驗證碼識別的方法和原理,不只有利於繞過驗證碼抓取網站內容,並且有利於設計更安全合理的驗證碼。
網易雲安全(易盾)行爲式驗證碼超10億次完美驗證,堅固守衛網站安全第一道防線。網易雲易盾提供新一代網站驗證碼,包括智能驗證碼、滑動驗證碼等形式,驗證碼接口穩定性 99.9%,感知威脅可智能切換驗證難度,告別繁瑣驗證,保護業務安全,點擊可免費試用。
參考資料:
[1] 《高效的驗證碼識別技術與驗證碼分類思想》
[2] 《驗證碼的識別與改進》
[3] Tesseract項目:code.google.com/p/tesseract…
[4] 常見驗證碼的弱點與驗證碼識別:drops.wooyun.org/tips/141
[5] blog.csdn.net/v_july_v/ar…
[6] www.codeproject.com/Articles/10…
[7] www.csie.ntu.edu.tw/~cjlin/libs…
相關文章:
【推薦】 測試環境docker化(一)—基於ndp部署模式的docker基礎鏡像製做