首頁 >後端開發 >PHP問題 >php如何實作驗證碼的識別

php如何實作驗證碼的識別

藏色散人
藏色散人原創
2020-09-01 09:14:163605瀏覽

php實現驗證碼辨識的方法:先將圖片二值化,並將值儲存到二維陣列裡;然後透過循環,求出每一個數字的位置;接著計算出數字在二維陣列裡的位置,並拼接數字;最後將字串與每一個字模的字串進行比較辨識即可。

php如何實作驗證碼的識別

推薦:《PHP影片教學

但是原文的介紹比較簡單,而且沒提到演算法的具體實作過程。詳細流程轉自:

http://www.poboke.com/study/php-verification-code-identification-primary.html

##所以本文以一個實際範例來示範php識別驗證碼的過程,並提交驗證碼到伺服器驗證。

第一部分:驗證碼的辨識


近期研究一些突破驗證碼的知識,記錄下來。一方面算是對這幾天學習知識的總結幫助自己理解;另一方面希望對研究這方面的技術同學有所幫助;另外也希望引起網站管理者的注意,在提供驗證碼時多些考慮進去。由於剛接觸這方面的知識,理解比較淺顯,有錯誤再所難免,歡迎拍磚。

驗證碼的作用:有效防止某個駭客對某一個特定註冊用戶用特定程式暴力破解方式進行不斷的登陸嘗試。其實現代的驗證碼一般是防止機器批量註冊的,防止機器批量發文回复。目前,不少網站為了防止用戶利用機器人自動註冊、登入、灌水,都採用了驗證碼技術。

所謂驗證碼,就是將一串隨機產生的數字或符號,產生一幅圖片,圖片裡加上一些幹擾像素(防止OCR),由用戶肉眼識別其中的驗證碼信息,輸入表單提交網站驗證,驗證成功後才能使用某項功能。 

我們最常見的驗證碼:

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

簡單起見,我們這次說明的主要物件是第1種類型的,我們先看幾個網路上比較常見的驗證碼圖片。

這四種樣式,基本上能代表2中所提到的驗證碼類型,初步看起來第一個圖片最容易破解,第二個次之,第三個更難,第四個最難。
真實情況呢?其實這三種圖片破解難度相同。

第一張圖片,最容易,圖片背景和數字都使用相同的顏色,字元規則,字元位置統一。本篇文章,就一這種類型驗證碼為例說明,其它的圖片,同學們自己搞。
第二張圖片,看似不容易,其實仔細研究會發現其規則,背景色和乾擾素無論怎麼變化,驗證字符字符規整,顏色相同,所以排除乾擾素非常容易,只要是非字符色素全部排除即可。
第三個圖片,看似更複雜,處理上面提到背景色和乾擾素一直變化外,驗證字符的顏色也在變化,並且各個字符的顏色也各不相同。
第四個圖片,除了第三個圖片上提到的特徵外,又在文字上加了兩條直線幹擾率,看似困難其實,很容易去掉。

以下以萬網的「通用網址查詢」來說明驗證碼的識別過程。
打開萬網:http://www.net.cn ,網站右邊側邊欄有一個「通用網址查詢」:

可以看出,這是第一種驗證碼,為了讓人眼能夠辨識出數字,所以驗證碼圖片的數字顏色和背景顏色的色差是比較大的,所以其RBG值也相差很大,可以透過判斷每個像素的RGB值來區分數字和背景。

驗證碼識別一般分為以下幾個步驟:

一、取出字模
識別驗證碼,畢竟不是專業的OCR識別,而且,由於各個網站的驗證碼各不相同,所以,最常見的方法就是就是建立這個驗證碼的特徵碼庫。去字模時,我們需要多下載幾張圖片,使這些圖片中,包括所有的字符,我們這裡的圖片裡只有數字,所以,只要收集到包括0-9的數字圖片即可。

1、多刷新幾次驗證碼,將驗證碼圖片儲存起來,要蒐集齊0-9的圖片。

2、用圖片處理軟體開啟圖片,我用的是Fireworks,按住ctrl 8可以將圖片的視圖放大8倍,這樣就能很清楚地觀察到圖片的每個像素。

可以發現,每個數字的寬是6px,高是10px,數字的間隔是4px,第一個數字左邊偏移了2px,頂部偏移了0px。這些數字後面都是要用的。

3、將每個數字截斷來儲存為圖片,大小為6*10。

二、圖片二值化
二值化就是把圖片上的驗證數字上每個像素用數字1表示,其它部分用0表示。把要辨識的圖片,進行二值化,將資料存到二維數組裡,得到圖片特徵數組。

1、首先要將數字和背景色和乾擾色區分開來,用螢幕取色器觀察顏色的規律。

可以得出結論:背景顏色的R、G、B值都是大於200的,而數字的顏色的R、G、B值的某一項有可能小於200,因此可以很容易區分。

2、下面的php程式碼只是為了示範二維數組,為了直接觀看數字,所以把1和0改為了0和-:



##1

2

3######4#####

5

6

7

8

#9

10

##11

12

13

14

15

16

17

18

19

#20

21


echo '<br><img src="v1.jpg"><br><br>';

 

getHec("v1.jpg");

 

函數 getHec($imagePath) {

#

    $res#= imagecreatefromjpeg#($imagePath)#;

    $大小#= getimagesize($imagePath);

    

#################################################################

    for #($i# #= 0; $i ##&lt; $[1]; ##$i# ) {

        ##($##j #= 0; $j &lt; $[0]; $j) {

            $rgb #($res,$j , $i);#

            $rgbararray= ##($res,#$rgb );

            ### '紅色'] &#lt; 200 || $rgbararray['綠色']&lt#;200 || $rgbararray['藍色'] &lt;#200##){#

                echo ##"0"## ## }

else

{                echo

" -“;#

            }

        }

        echo "<br>";

    }

}

結果如下圖所示:

如果圖片的背景顏色比較複雜,處理方法也是一樣的,總是能找到臨界值來區分,具體要靠自己觀察了。

三、數字字模二值化
計算出每個數字字模的二值化的數據,記錄下這些數據,當作key即可。

1、0-9的數字字模圖片進行二值化,逐一取出圖片的像像素的顏色,然後取得每個像素的R、G、B值,再進行判斷,程式碼如下:



1

2

3

4

5

6

##10

11

12

13

14

15

16

17

18

19

#20

21


for($#i##= ##0;$#i& lt;10#;##$# ##我###### ##){

    echo"'$i'=>'";

    echogetHec("$i.jpg")."',<br>";

}

 

函數getHec($imagePath){

    $res= imagecreatefromjpeg(#$##imagePath);

    $尺寸#=##getimagesize($imagePath);

    

###########################################################################################

    for#($i# #=############0######;#############$#####i######## #########lt######;#############$######尺寸#####[### # ##1######]###;$i){

        for#($##j # #=0;#$j &lt;#$##[ 0###];$j) ##{

            $rgb#imagecolorat($res,#$j, $i)

#;######

            $rgbararray=imagecolorsforindex=##imagecolorsforindex ##($res,$

###rgb###### )######;#######

            if($ '紅色']&#lt;200||$###rgbararray#####[###### '綠色的'######]##&lt;#200|| #$rgbararray['藍色']& lt;#200#)##{

                echo##"1";

#}else##{{

                因echo

#################C###############################################C####################C###############CCC ## #" 0"######;############            #######}######

        }

#    }

##

輸出結果:



1

2

3

4

#5######6# ##

7

8

9

10


' 0'=&gt;'011110100001100001100001100001100001100110010101001 ,

#

'1'=&gt;' 0010001110000010000010000010000010000100000 #;

'011110100001100001000001000010000100001000010000110011111111'

,,

'3'=&gt;' 011110100001100001000010001100000010000001100001100001011110',

'4'##'4'# #;'0001000001000011000101001001001001001111110001000011000011111',

'5'=&gt;' 111111100000100000101110110001000001000001100001100001011110',

'6'=&gt;'0011100100011000001000001011101100011000011000011000010111110',

'7'=&gt;' 111111100010100010000100000100001000001000001000001000001000',

’ #;'0111101000011000011000010111100100101000011000011000010111110',

'9'=&gt;' 011100100010100001100001100011011101000001000001100010011100',

四、對照樣本
把步驟二中的圖片特徵碼和步驟三的驗證碼的字模進行對比,得到驗證圖片上的數字。

演算法過程(程式碼請見附件):
1、將圖片二值化後的值儲存到二維陣列裡。
2、經過循環,求出每一個數字的位置,要用到前面得到的數字的寬、高、間隔、左邊偏移、頂部偏移。
例如:第i個數字左邊偏移 =(數字寬 間隔)* i 左邊偏移。 (w h x y)
3、知道了數字的偏移位置,就可以計算出數字在二維數組裡的位置,透過循環將數字的6*10=60個資料取出來拼接在一起,就形成了與數字字模類似的字串。
4、將字串與每一個字模的字串比較,求其相似度,取最高的相似度對應的數字,或相似度達到95%以上就可以斷定是某個數字。
5、辨識結果如下:

使用目前這種方法,對驗證碼的辨識基本上可以做到100%。
透過以上步驟,您可能說了,並沒有發現如何取出乾擾素啊!其實取出乾擾素的方法很簡單,幹擾素的一個重要特徵是,不能影響驗證碼的顯示效果,所以製作幹擾素時它的RGB可能低於或高於某個特定值,例如我給的例子中的圖片,幹擾素的RGB各項值是不會小於200的,所以,這樣我們就很容易去掉幹擾素了。

源下載:http://yunpan.cn/cmJCkEnyGij3t  存取密碼 d2ba

#

以上是php如何實作驗證碼的識別的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn