本文转自:http://www.cnblogs.com/yuanbao/archive/2007/09/25/905322.html
最近写了几个网站的验证码图片自动识别程序,尽管每个网站的验证码图片都不相同,识别的方法有所差别。但写得多了,也总结出不少相同之处。今天抽空封装出一个基础类来,发现可以很好地重复利用,编写不同的验证码识别程序,效率提高了不少。好东东不能独享,现放出来供大家共同研究,请网友们妥善用之。
封装后的类使用很简单,针对不同的验证码,相应继承修改某些方法,即可简单几句代码就可以实现图片识别了:
GrayByPixels(); //灰度处理
GetPicValidByValue(128, 4); //得到有效空间
Bitmap[] pics = GetSplitPics(4, 1); //分割
string code = GetSingleBmpCode(pics[i], 128); //得到代码串
具体使用,请参见我做的例子:
投票程序示例.exe投票程序源码
(例子说明:使用进程投票,可自动清除Alert弹出窗口,可自动换IP,ADSL用户自行修改Restart.bat中第三行内容)
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Collections;
using
System.Drawing;
using
System.Drawing.Imaging;
using
System.Runtime.InteropServices;

namespace
BallotAiying2

{
classUnCodebase


{
publicBitmapbmpobj;
publicUnCodebase(Bitmappic)


{
bmpobj=newBitmap(pic);//转换为Format32bppRgb
}


/**////<summary>
///根据RGB,计算灰度值
///</summary>
///<paramname="posClr">Color值</param>
///<returns>灰度值,整型</returns>
privateintGetGrayNumColor(System.Drawing.ColorposClr)


{
return(posClr.R*19595+posClr.G*38469+posClr.B*7472)>>16;
}


/**////<summary>
///灰度转换,逐点方式
///</summary>
publicvoidGrayByPixels()


{
for(inti=0;i<bmpobj.Height;i++)


{
for(intj=0;j<bmpobj.Width;j++)


{
inttmpValue=GetGrayNumColor(bmpobj.GetPixel(j,i));
bmpobj.SetPixel(j,i,Color.FromArgb(tmpValue,tmpValue,tmpValue));
}
}
}


/**////<summary>
///去图形边框
///</summary>
///<paramname="borderWidth"></param>
publicvoidClearPicBorder(intborderWidth)


{
for(inti=0;i<bmpobj.Height;i++)


{
for(intj=0;j<bmpobj.Width;j++)


{
if(i<borderWidth||j<borderWidth||j>bmpobj.Width-1-borderWidth||i>bmpobj.Height-1-borderWidth)
bmpobj.SetPixel(j,i,Color.FromArgb(255,255,255));
}
}
}


/**////<summary>
///灰度转换,逐行方式
///</summary>
publicvoidGrayByLine()


{
Rectanglerec=newRectangle(0,0,bmpobj.Width,bmpobj.Height);
BitmapDatabmpData=bmpobj.LockBits(rec,ImageLockMode.ReadWrite,bmpobj.PixelFormat);//PixelFormat.Format32bppPArgb);
//bmpData.PixelFormat=PixelFormat.Format24bppRgb;
IntPtrscan0=bmpData.Scan0;
intlen=bmpobj.Width*bmpobj.Height;
int[]pixels=newint[len];
Marshal.Copy(scan0,pixels,0,len);

//对图片进行处理
intGrayValue=0;
for(inti=0;i<len;i++)


{
GrayValue=GetGrayNumColor(Color.FromArgb(pixels[i]));
pixels[i]=(byte)(Color.FromArgb(GrayValue,GrayValue,GrayValue)).ToArgb();//Color转byte
}

bmpobj.UnlockBits(bmpData);
}


/**////<summary>
///得到有效图形并调整为可平均分割的大小
///</summary>
///<paramname="dgGrayValue">灰度背景分界值</param>
///<paramname="CharsCount">有效字符数</param>
///<returns></returns>
publicvoidGetPicValidByValue(intdgGrayValue,intCharsCount)


{
intposx1=bmpobj.Width;intposy1=bmpobj.Height;
intposx2=0;intposy2=0;
for(inti=0;i<bmpobj.Height;i++)//找有效区


{
for(intj=0;j<bmpobj.Width;j++)


{
intpixelValue=bmpobj.GetPixel(j,i).R;
if(pixelValue<dgGrayValue)//根据灰度值


{
if(posx1>j)posx1=j;
if(posy1>i)posy1=i;

if(posx2<j)posx2=j;
if(posy2<i)posy2=i;
};
};
};
//确保能整除
intSpan=CharsCount-(posx2-posx1+1)%CharsCount;//可整除的差额数
if(Span<CharsCount)


{
intleftSpan=Span/2;//分配到左边的空列,如span为单数,则右边比左边大1
if(posx1>leftSpan)
posx1=posx1-leftSpan;
if(posx2+Span-leftSpan<bmpobj.Width)
posx2=posx2+Span-leftSpan;
}
//复制新图
RectanglecloneRect=newRectangle(posx1,posy1,posx2-posx1+1,posy2-posy1+1);
bmpobj=bmpobj.Clone(cloneRect,bmpobj.PixelFormat);
}


/**////<summary>
///得到有效图形,图形为类变量
///</summary>
///<paramname="dgGrayValue">灰度背景分界值</param>
///<paramname="CharsCount">有效字符数</param>
///<returns></returns>
publicvoidGetPicValidByValue(intdgGrayValue)


{
intposx1=bmpobj.Width;intposy1=bmpobj.Height;
intposx2=0;intposy2=0;
for(inti=0;i<bmpobj.Height;i++)//找有效区


{
for(intj=0;j<bmpobj.Width;j++)


{
intpixelValue=bmpobj.GetPixel(j,i).R;
if(pixelValue<dgGrayValue)//根据灰度值


{
if(posx1>j)posx1=j;
if(posy1>i)posy1=i;

if(posx2<j)posx2=j;
if(posy2<i)posy2=i;
};
};
};
//复制新图
RectanglecloneRect=newRectangle(posx1,posy1,posx2-posx1+1,posy2-posy1+1);
bmpobj=bmpobj.Clone(cloneRect,bmpobj.PixelFormat);
}


/**////<summary>
///得到有效图形,图形由外面传入
///</summary>
///<paramname="dgGrayValue">灰度背景分界值</param>
///<paramname="CharsCount">有效字符数</param>
///<returns></returns>
publicBitmapGetPicValidByValue(Bitmapsinglepic,intdgGrayValue)


{
intposx1=singlepic.Width;intposy1=singlepic.Height;
intposx2=0;intposy2=0;
for(inti=0;i<singlepic.Height;i++)//找有效区

