c# 驗證碼的識別主要分為預處理、分割、識別三個步驟
首先我從網站上下載驗證碼
處理結果如下:

1.圖片預處理,即二值化圖片
*就是將圖像上的像素點的灰度值設置為0或255。
原理如下:

代碼如下:
#region 二值化圖片
/// <summary>
/// 二值化圖片
/// 就是將圖像上的像素點的灰度值設置為0或255
/// </summary>
/// <returns>處理后的驗證碼</returns>
public Bitmap BinaryZaTion()
{
for (int x = 0; x < img.Width; x++)
{
for (int y = 0; y < img.Height; y++)
{
__c = img.GetPixel(x, y);
//灰度值
int __tc = (__c.R + __c.G + __c.B) / 3;
//大於闕值 黑色
if (__tc > t)
{
img.SetPixel(x, y, Color.FromArgb(__c.A, b, b, b));
//黑色點個數自加
__blackNum++;
}
//大於闕值 白色
else
{
img.SetPixel(x, y, Color.FromArgb(__c.A, w, w, w));
}
}
}
return img;
}
#endregion
二值化過后需要判斷圖片的黑白比列,若果黑色比白色多,需要對圖片反色處理。
代碼如下:
#region 是否需要反色
/// <summary>
/// 是否需要反色
/// </summary>
/// <returns>是否需要反色</returns>
public bool IsNeedInverseColor()
{
if ((__blackNum * 1.0 / (img.Width * img.Height)) > 0.5)
{
return true;
}
else
{
return false;
}
}
#endregion
#region 反色
/// <summary>
/// 反色
/// </summary>
/// <returns>處理后的驗證碼</returns>
public Bitmap InverseColor()
{
for (int x = 0; x < img.Width; x++)
{
for (int y = 0; y < img.Height; y++)
{
__c = img.GetPixel(x, y);
img.SetPixel(x, y, Color.FromArgb(__c.A, w - __c.R, w - __c.G, w - __c.B));
}
}
return img;
}
#endregion
處理結果如下:

2.圖片分割
我的做法是先每一豎行判斷是否是純白色行,不是的話記錄當前x坐標,然后沒以橫行判斷是否純白色行,這樣就能的到每一個數字的區域,然后將區域畫出來。
代碼如下:
#region 分割圖片
/// <summary>
/// 分割圖片
/// </summary>
/// <returns>處理后的驗證碼</returns>
public Bitmap CutImg()
{
//Y軸分割
CutY();
//區域個數
__count = 0;
if (XList.Count > 1)
{
//x起始值
int __start = XList[0];
//x結束值
int __end = XList[XList.Count - 1];
//x索引
int __idx = 0;
while (__start != __end)
{
//區域寬度
int __w = __start;
//區域個數自加
__count++;
while (XList.Contains(__w) && __idx < XList.Count)
{
//區域寬度自加
__w++;
//x索引自加
__idx++;
}
//區域X軸坐標
int x = __start;
//區域Y軸坐標
int y = 0;
//區域寬度
int width = __w - __start;
//區域高度
int height = img.Height;
/*
* X軸分割當前區域
*/
CutX(img.Clone(new Rectangle(x, y, width, height), img.PixelFormat));
if (YList.Count > 1 && YList.Count != img.Height)
{
int y1 = YList[0];
int y2 = YList[YList.Count - 1];
if (y1 != 1)
{
y = y1 - 1;
}
height = y2 - y1 + 1;
}
//GDI+繪圖對象
Graphics g = Graphics.FromImage(img);
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingMode = CompositingMode.SourceOver;
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
//畫出驗證碼區域
g.DrawRectangle(new Pen(Brushes.Green), new Rectangle(x, y, width, height));
g.Dispose();
//起始值指向下一組
if (__idx < XList.Count)
{
__start = XList[__idx];
}
else
{
__start = __end;
}
}
}
return img;
}
#endregion
#region Y軸字符分割圖片
/// <summary>
/// 得到Y軸分割點
/// 判斷每一豎行是否有黑色
/// 有則添加
/// </summary>
/// <param name="img">要驗證的圖片</param>
private void CutY()
{
XList.Clear();
for (int x = 0; x < img.Width; x++)
{
isWhilteLine = false;
for (int y = 0; y < img.Height; y++)
{
__c = img.GetPixel(x, y);
if (__c.R == w)
{
isWhilteLine = true;
}
else
{
isWhilteLine = false;
break;
}
}
if (!isWhilteLine)
{
XList.Add(x);
}
}
}
#endregion
#region X軸字符分割圖片
/// <summary>
/// 得到X軸分割點
/// 判斷每一橫行是否有黑色
/// 有則添加
/// </summary>
/// <param name="tempImg">臨時區域</param>
private void CutX(Bitmap tempImg)
{
YList.Clear();
for (int x = 0; x < tempImg.Height; x++)
{
isWhilteLine = false;
for (int y = 0; y < tempImg.Width; y++)
{
__c = tempImg.GetPixel(y, x);
if (__c.R == w)
{
isWhilteLine = true;
}
else
{
isWhilteLine = false;
break;
}
}
if (!isWhilteLine)
{
YList.Add(x);
}
}
tempImg.Dispose();
}
#endregion
效果如下:

3.識別
識別呢就是提取出圖片的特征
我的做法是將圖片數字區域逐一分成4*4的區域,計算出各個區域的黑色點所占的百分比,然后將計算出來的結果和以前計算的特征進行比較,求出歐氏距離 d = sqrt( (x1-x2)^2+(y1-y2)^2 )最小的一個作為結果。
部分代碼如下:
#region 黑色像素比列
/// <summary>
/// 計算黑色像素比列
/// </summary>
/// <param name="tempimg"></param>
/// <returns></returns>
private double PixlPercent(Bitmap tempimg)
{
int temp = 0;
int w_h = tempimg.Width * tempimg.Height;
for (int x = 0; x < tempimg.Width; x++)
{
for (int y = 0; y < tempimg.Height; y++)
{
__c = tempimg.GetPixel(x, y);
if (__c.R == b)
{
temp++;
}
}
}
tempimg.Dispose();
double result = temp * 1.0 / w_h;
result = result.ToString().Length > 3 ? Convert.ToDouble(result.ToString().Substring(0, 3)) : result;
return result;
}
#endregion
效果如下:

本代碼只做研究學習之用。
新手上路,有任何建議、意見聯系 pigkeli@qq.com 。
