分享一個圖片驗證碼識別的乾貨

驗證碼的功能通常是防止使用程序惡意註冊、暴力破解或批量發帖而設置的。所謂驗證碼,就是將一串隨機產生的數字或符號,生成一幅圖片,圖片里加上一些干擾象素(防止OCR),由用戶肉眼識別其中的驗證碼信息,輸入表單提交網站驗證,驗證成功後才能使用某項功能。學習驗證碼的破解/識別技術,不只能夠知道驗證碼的原理,並且可讓你知道怎樣才能防止驗證碼被破解。程序員

最多見的驗證碼主要有如下幾種:學習

  1. 四位數字,隨機的一數字字符串,最原始的驗證碼,驗證做用幾乎爲零。 
  2. 隨機數字圖片驗證碼。圖片上的字符比較中規中矩,有的可能加入一些隨機干擾素,還有一些是隨機字符顏色,驗證做用比上一個好。沒有基本圖形圖像學知識的人,不可破!
  3. 各類圖片格式的隨機數字+隨機大寫英文字母+隨機干擾像素+隨機位置。 
  4. 漢字是註冊目前最新的驗證碼,隨機生成,打起來更難了,影響用戶體驗,因此,通常應用的比較少。 

爲簡單起見,破解說明主要針對是第2種類型的,先來看看網上常見的這種驗證碼的圖片:網站

  • 第一種,最容易,圖片背景和數字都使用相同的顏色,字符規整,字符位置統一。 
  • 第二種,看似不容易,其實仔細研究會發現其規則,背景色和干擾素不管怎麼變化,驗證字符字符規整,顏色相同,因此排除干擾素很是容易,只要是非字符色素所有排除便可。
  • 第三種,看似更復雜,處理上面提到背景色和干擾素一直變化外,驗證字符的顏色也在變化,而且各個字符的顏色也各不相同。 
  • 第四種,除了第三個圖片上提到的特徵外,又在文字上加了兩條直線干擾率,看似困難其實,很容易去掉。 

驗證碼識別通常分爲如下幾個步驟:圖片

  1. 取出字模 識別驗證碼,畢竟不是專業的OCR識別,而且,因爲各個網站的驗證碼各不相同,因此,最多見的方法就是就是創建這個驗證碼的特徵碼庫。去字模時,咱們須要多下載幾張圖片,使這些圖片中,包括全部的字符,咱們這裏的字母只有圖片,因此,只要收集到包括0-9的圖片便可。
  2. 二值化 二值化就是把圖片上的驗證數字上每一個象素用一種數字表示1,其餘部分用0表示。這樣就能夠計算出每一個數字字模,記錄下這些字模來,看成key便可。
  3. 計算特徵 把要識別的圖片,進行二值化,獲得圖片特徵。 
  4. 對照樣本 把步驟3種的圖片特徵碼和驗證碼的字模進行對比,獲得驗證圖片上的數字。 

使用目前這種方法,對驗證碼的識別基本上能夠作到100%。字符串

經過以上步驟,您可能說了,並無發現如何取出干擾素啊!其實取出干擾素的方法很簡單,干擾素的一個重要特徵是,不能影響驗證碼的顯示效果,因此製做干擾素時它的RGB可能低於或者高於某個特定值,好比我給的例子中的圖片,干擾素的RGB各項值是不會超過125的,因此,這樣咱們就很容易去掉干擾素了。驗證碼

簡單的驗證碼只有數字和字母組成,格式統一,每次出現位置固定。下面繼續深刻研究識別驗證碼,此次須要識別的目標是:驗證碼有字符和數字組成,驗證碼存在旋轉(可能左右都旋轉),位置不固定,存在字符與字符之間的粘連,且驗證碼有更強的干擾素。效率

咱們如下圖爲例進行講解。原理

第一步:二值化。把驗證碼的部分用 1 表示,背景部分用 0 表示出來,識別方法很簡單,咱們打印出驗證碼整張圖片的 RGB ,而後分析其規律便可,經過 RGB 碼,咱們很容易分辨出上面這張圖片的 R 值大於 120 , G 和 B 的值小於 80 ,因此依據這個規則咱們很容易把上面的圖片二值化。隨機數

再來看看上面的第三種驗證碼圖片用戶體驗

剛看上去,感受很複雜。驗證碼的圖片每次背景色都不相同,且不是單色,各個驗證碼數字的顏色每次也各不相同。貌似很難二值化,其實咱們打印出其 RGB 值很容易就發現。不管驗證數字顏色如何變化,該數字的 RGB 值總有一個值小於 125 ,因此經過以下判斷 $rgbarray['red'] < 125 || $rgbarray['green']<125|| $rgbarray['blue'] < 125 咱們就很容易分辨出哪裏是數字,哪裏是背景。

咱們可以找到這些規律的緣由是,在製做驗證碼的干擾素時,爲了使干擾素不影響數字的顯示效果,必須使用干擾素的 RGB 和數字 RGB 相互獨立,互不干擾。只要懂得這個規律,咱們就很容易實現二值化。

咱們找到的 120 , 80 , 125 等閾值,可能和實際的 RGB 有出入,因此,有時二值化後,會有部分地方出現 1 ,對於驗證碼上固定位置顯示數字,這種干擾沒有太大意義。可是對於驗證碼位置不肯定的圖片來講,在咱們切割字符時,極可能形成干擾。因此,在二值化後要進行去噪處理。

第二部:去噪處理。去噪的原理很簡單,就是把孤立的有效的值去掉,若是噪點比較高,要求的效率也比較高的話,這裏面也有不少工做要作。幸虧這裏咱們不要求這麼高深,咱們使用最簡單的方法就能夠,若是一個點爲 1 則判斷這個點的上下左右上左上右下左下右 8 個方位上數字是否爲 1 ,若是不爲 1 ,就認爲是一個燥點,直接設置爲 1 便可。

如上圖所示,咱們使用此方法很容易發現紅色方框部分的 1 爲燥點,直接設置爲 1 便可。在判斷時咱們使用了一個技巧,有時候的噪點多是兩個連續的 1 ,因此咱們計算這個點的 8 個方向上的值之和,最後咱們判斷他們的和是否小於特定的閾值。

第三部:切割字符。切割字符的方法有不少種,這裏採用最簡單的一種,先垂直方向切割成爲字符,而後在水平方向去掉多於的 0000 ,以下圖

第一步切割紅線部分,第二步切割藍線部分,這樣就能夠獲得獨立的字符了。可是像下面這種狀況

按上面的方法會把 dw 字符切割成一個字符,這是錯誤的切割,因此這裏咱們涉及到粘連字符的切割。

第四步:粘連字符切割。製做驗證碼時,規則字符的粘連很容易分割開,若是字符自己有縮放,變形就很難處理,通過分析,咱們能夠發現,上面的字符粘連屬於很簡單的方式,只是規則字符的粘連,因此處理這種狀況,咱們也使用很簡單的處理方式。當完成分割操做後,咱們不能立刻肯定分割的部分就爲一個字符,要進行驗證,驗證的關鍵因素就是,切割下來的字符的寬是否大於閾值,這個閾值的取捨標準是,一個字符不管怎麼旋轉變形都不會大於這個閾值,因此,若是咱們切割的塊大於這個閾值,就能夠認爲這是一個粘連字符;若是大於兩個閾值之和,就認爲是三個字符粘連,以此類推。知道這個規則後,切割粘連字符也就很簡單了。若是咱們發現是粘連字符塊,直接平分這個塊爲兩個或者多個新的塊就能夠。固然爲了更好的還原字符,我通常都採用平分 +1 , -1 對字符塊的部分進行適當的補充。

第五步:匹配字符。對於旋轉字符的特徵碼創建,有不少種方法,這裏就不作深刻研究了。我這裏使用的最簡單的方式,爲全部字符的全部狀況創建匹配庫,因此在我提供的代碼種增長了 study 操做,其目的就是,先有人手工識別圖片的驗證碼,而後經過 study 方法,寫入特徵碼庫。這樣寫入的圖片數據越多,驗證識別的準確行也就越高。

通過以上步驟,咱們基本上能夠識別如今互聯網上大部分的驗證碼,這裏咱們都是使用的最簡單的方法,沒有使用任何 OCR 知識。

另外製做驗證碼的一些建議:

對於識別驗證碼的程序來講,最可貴部分是驗證字符的切割和特徵碼的創建,而國內不少程序員只作驗證碼時,老是喜歡在驗證碼加不少干擾素,干擾線,影響效果不說,還達不到很好的效果;因此,要想使本身驗證碼難於本識別,只作下面兩點就夠了

  1. 字符粘連,最好全部的字符都有粘連的部分; 
  2. 不要使用規格字符,驗證碼的各個部分使用不一樣比例的縮放或者旋轉。 

只要作到這兩點,或者這兩點的變形,識別程序就很難識別。

相關文章
相關標籤/搜索