一、驗證碼識別的概念
機器識別圖片主要的三個步驟為消去背景、切割字元、識別字元。而現有的字元驗證碼也針對這三個方面來設計強壯的驗證碼。
以下簡圖協助大家理解驗證碼識別的流程:
二、處理流程
其中最為關鍵的就是好影像處理這一步了。影像處理功能模組包括映像的灰階化、二值化、離散雜訊點的去除、傾斜度校正、字元的切割、映像的歸一化等影像處理技術 。
1、 映像的灰階化
由於 256 色的位元影像的調色盤內容比較複雜,使得影像處理的許多演算法都沒有辦法展開,因此有必要對它進行灰階處理。所謂灰階映像就是映像的每一個像素的 R、G、B 分量的值是相等的。彩色映像的每個像素的 R、G、B 值是不相同的,所以顯示出紅綠藍等各種顏色。灰階映像沒有這些顏色差異,有的只是亮度上的不同。灰階值大的像素點比較亮(像素值最大為 255,為白色),反之比較暗(像素值最小為 0,為黑色)。映像灰階化有各種不同的演算法,比較直接的一種就是給像素的 RGB 值各自一個加權係數,然後求和;同時還要對調色盤表項進行相應的處理。
2、 映像的二值化
要注意的是,最後得到的結果一定要歸一到 0-255 之內。因為這是每個位元組表示
映像資料的極限。
3、 去噪
映像可能在產生、傳輸或者採集過程中夾帶了雜訊,去雜訊是影像處理中常用的手法。通常去雜訊用濾波的方法,比如中值濾波、均值濾波。但是那樣的演算法不適合用在處理字元這樣目標狹長的映像中,因為在濾波的過程中很有可能會去掉字元本身的像素。
一個採用的是去除雜點的方法來進行去雜訊處理的。具體演算法如下:掃描整個映像,當發現一個黑色點的時候,就考察和該黑色點間接或者直接相串連的黑色點的個數有多少,如果大於一定的值,那就說明該點不是離散點,否則就是離散點,把它去掉。在考察相連的黑色點的時候用的是遞迴的方法。此處,我簡單的用python實現了,大家可以參考以下。
#coding=utf-8"""creat time:2015.09.14"""import cv2import numpy as npfrom matplotlib import pyplot as pltfrom PIL import Image,ImageEnhance,ImageFilterimg_name = '2+.png'#去除幹擾線im = Image.open(img_name)#映像二值化enhancer = ImageEnhance.Contrast(im)im = enhancer.enhance(2)im = im.convert('1')data = im.getdata()w,h = im.size#im.show()black_point = 0for x in xrange(1,w-1): for y in xrange(1,h-1): mid_pixel = data[w*y+x] #中央像素點像素值 if mid_pixel == 0: #找出上下左右四個方向像素點像素值 top_pixel = data[w*(y-1)+x] left_pixel = data[w*y+(x-1)] down_pixel = data[w*(y+1)+x] right_pixel = data[w*y+(x+1)] #判斷上下左右的黑色像素點總個數 if top_pixel == 0: black_point += 1 if left_pixel == 0: black_point += 1 if down_pixel == 0: black_point += 1 if right_pixel == 0: black_point += 1 if black_point >= 3: im.putpixel((x,y),0) #print black_point black_point = 0im.show()
原驗證碼:
處理後:
4、分割
映像中一般會含有多個數字,識別的時候只能根據每個字元的特徵來進行判斷,所以還要進行字元切割的工作。這一步工作就是把映像中的字元獨立的切割出來。
具體的演算法如下:
第一步,先自下而上對映像進行漸進式掃描直至遇到第一個黑色的像素點。記錄下來。然後再自上而下對映像進行漸進式掃描直至找到第一個黑色像素,這樣就找到映像大致的高度範圍。
第二步,在這個高度範圍之內再自左向右逐列進行掃描,遇到第一個黑色像素時認為是字元切割的起始位置,然後繼續掃描,直至遇到有一列中沒有黑色像素,則認為這個字元切割結束,然後繼續掃描,按照上述的方法一直掃描直至映像的最右端。這樣就得到了每個字元的比較精確寬度範圍。
第三步,在已知的每個字元比較精確的寬度範圍內,按照第一步的方法,分別進行自上而下和自下而上的漸進式掃描來擷取每個字元精確的高度範圍。
5、 映像的歸一化
因為採集的映像中字元大小有可能存在較大的差異,或者是經過切割後的字元尺寸不統一,而相對來說,統一尺寸的字元識別的標準性更強,準確率自然也更高,歸一化映像就是要把原來各不相同的字元統一到同一尺寸,在系統實現中是統一到同一高度,然後根據高度來調整字元的寬度。具體演算法如下:先得到原來字元的高度,跟系統要求的高度做比較,得出要變換的係數,然後根據得到的係數求得變換後應有得寬度。在得到寬度和高度之後,把新映像裡面的點按照插值的方法映射到原映像中。
不少人認為把每個字元映像歸一化為 5×9 像素的二值映像是最理想的,因為映像的尺寸越小,識別速度就越高,網路訓練也越快。而實際上,相對於要識別的字元映像, 5×9 像素圖太小了。歸一化後,映像資訊丟失了很多,這時進行Image Recognition,準確率不高。實驗證明,將字元映像歸一化為 10×18 像素的二值映像是現實中是比較理想的,達到了識別速度快和識別準確率高的較好的平衡點。 三、識別
Image Recognition包括特徵提取、樣本訓練和識別三大塊內容。
驗證碼識別其中最為關鍵的就是去噪和分割,這對你的訓練和識別的精度都有著很大的影響。這裡只講了大致的流程,其中每個細節都有很多工作要做,這裡碼字也很難講清楚,大家可以以這個流程為主線,一步步的實現,最終也就能完成你的需求。