文章地址:http://blog.csdn.net/u011535382/article/details/48210643
本文是成都地區CMCC-EDU登陸時候的驗證碼識別過程分析,完整的登陸過程分析在 這裏。
1.驗證碼識別難度分析
經過對比觀察發現,CMCC-EUD的驗證碼其實很二的,其中每個數字的出現位置是固定的,每個數字每次出現的形狀也是一樣的,只有少量的噪點可以通過分區和二值化處理來消除。
可以將圖片看成是44*20的一個矩陣,只要能夠把它每個數字標準的形式存儲下來,再將整個驗證碼分爲四個區域,逐一比較,找出差異度最小的就實現了。
2.標準數字矩陣的建立
由於每個數字可以看成是 13*9 的矩陣,需要將他們轉化爲二值並儲存在二維數組中作爲每次比較的標準。先通過ps將圖片裁剪成 13*9 分辨率的文件,再由軟件對比識別。
這是二值化前的效果:
其中彩色轉化爲灰度的計算方式爲 gray = R*0.11+G *0.59 + B*0.3;灰度轉二值的閥值取爲 128,這樣實際的的效果最好。再將識別出來的圖像矩陣存儲到文本文件 stand.txt 中方便以後編程的使用。
二值化後的效果:
4.驗證碼的識別思路
1、將待驗證的圖片分爲四個區域;
2、選擇一個區域數字識別;
3、將10個標準數字矩陣和待識別區做異或操作,統計差異最小的那個數就是識別出來的數num;
4、若四個區域都識別完,返回識別結果,若沒有,轉到步驟2。
5.具體實現代碼
/*
驗證碼識別函數
參數: 包含驗證碼圖片的 CImage 對象
返回值: 識別結果的 CString */
CString Distinguish(CImage &image)
{
CString strResult;
//每張驗證碼分爲四個區域
for(int temp= 0; temp<=3; temp++)
{
bool pixelArray[13][9] = {0};
int numL = 11*temp+2; //x像素座標的左邊起點
int numR = numL + 9; //x像素座標的右邊起點
int resultNum = 0;
//對一個圖像進行掃描二值化 存儲在 pixelArray
for (int y=2; y<15; y++)
{
for (int x=numL; x<numR; x++)
{
COLORREF colorRef = image.GetPixel(x,y);
//RGB同時擴大100倍 轉化爲灰度值
int gray = GetRValue(colorRef)*11+GetGValue(colorRef)*59+GetBValue(colorRef)*30;
if (gray>=12800)
{
pixelArray[y-2][x-numL] = true;
}
else
{
pixelArray[y-2][x-numL] = false;
}
}
}
//對一個區域的數字進行識別
//將10個標準數字與目標數字矩陣比較
int mincount = 117;
for (int num =0; num<10; num++)
{
int count = 0;
for (int y=0; y<13; y++)
{
for (int x=0; x<9 ;x++)
{
//統計差異的個數
if (standNum[num][y][x]&&pixelArray[y][x])
{
count++;
}
}
}
if (count<mincount)
{
mincount = count;
resultNum = num;
}
}
//將識別出來的數字轉化爲CString
CString strFormat;
strFormat.Format("%d", resultNum);
strResult += strFormat;
}
return strResult;
}
6.驗證碼識別效果
經過300多張圖片的測試,成功率爲 100% (主要是圖片太簡單)。