QQ验证码识别源代码(C#/NET1.1)
using System;
namespace QQ { /// <summary> /// yzm 的摘要说明。 /// </summary> public class yzm { public yzm(public System.Drawing.Bitmap pic) { this.bp = pic; } /// <summary> /// 将一个int值存入到4个字节的字节数组(从高地址开始转换,最高地址的值以无符号整型参与"与运算") /// </summary> /// <param name="thevalue">要处理的int值</param> /// <param name="thebuff">存放信息的字符数组</param> public static void getbytesfromint(int thevalue, byte[] thebuff) { long v1=0; long v2=0; long v3=0; long v4=0; uint b1=(uint)4278190080; uint b2=(uint)16711680; uint b3=(uint)65280; uint b4=(uint)255; v1=thevalue & b1; v2=thevalue & b2; v3=thevalue & b3; v4=thevalue & b4; thebuff[0]=(byte)(v1>>24); thebuff[1]=(byte)(v2>>16); thebuff[2]=(byte)(v3>>8); thebuff[3]=(byte)v4; } /// <summary> /// 将一个ushort值存入到2个字节的字节数组(从高地址开始转换,最高地址的值以无符号整型参与"与运算") /// </summary> /// <param name="thevalue">要处理的ushort值</param> /// <param name="thebuff">存放信息的字符数组</param> public static void getbytesfromushort(ushort thevalue, byte[] thebuff) { ushort v1=0; ushort v2=0; ushort b1=(ushort)65280; ushort b2=(ushort)255; v1=(ushort)(thevalue & b1); v2=(ushort)(thevalue & b2); thebuff[0]=(byte)(v1>>8); thebuff[1]=(byte)(v2); } /// <summary> /// 将4个字节的字节数组转换成一个int值 /// </summary> /// <param name="thebuff">字符数组</param> /// <returns></returns> public static int getintfrombyte(byte[] thebuff) { int jieguo=0; long mid=0; long m1=0; long m2=0; long m3=0; long m4=0; m1=(thebuff[0]<<24); m2=(thebuff[1]<<16); m3=(thebuff[2]<<8); m4=thebuff[3]; mid=m1+m2+m3+m4; jieguo=(int)mid; return jieguo; } /// <summary> /// 将2个字节的字节数组转换成一个ushort值 /// </summary> /// <param name="thebuff">字符数组</param> /// <returns></returns> public static ushort getushortfrombyte(byte[] thebuff) { int jieguo1=0; jieguo1=(thebuff[0]<<8)+thebuff[1]; ushort jieguo=(ushort)jieguo1; return jieguo; } /// <summary> /// 将内存中的数据写入硬盘(保存特征库) /// </summary> /// <param name="thefile">保存的位置</param> public static void writetofile(string thefile) { System.IO.FileStream fs = new System.IO.FileStream(thefile,System.IO.FileMode.OpenOrCreate,System.IO.FileAccess.ReadWrite); byte[] buff0=new byte[4]; getbytesfromint(datanum,buff0); fs.Write(buff0,0,4); for(int ii=0;ii<datanum;ii++) { for(int jj=0;jj<20;jj++) { byte[] buff=new byte[2]; getbytesfromushort(datap[ii,jj],buff); fs.Write(buff,0,2); } fs.WriteByte(dataxy[ii,0]); fs.WriteByte(dataxy[ii,1]); fs.WriteByte(datachar[ii]); } fs.Close(); } /// <summary> /// 从文件中读取信息,并保存在内存中相应的位置 /// </summary> /// <param name="thefile">特征库文件</param> public static void readfromfile(string thefile) { int allnum=0; byte[] buff=new byte[4]; System.IO.FileStream fs = new System.IO.FileStream(thefile,System.IO.FileMode.Open,System.IO.FileAccess.Read); fs.Read(buff,0,4); allnum=getintfrombyte(buff); byte[] buff0=new byte[2]; for(int ii=0;ii<allnum;ii++) { for(int jj=0;jj<20;jj++) { fs.Read(buff0,0,2); datap[ii,jj]=getushortfrombyte(buff0); } fs.Read(buff0,0,1); dataxy[ii,0]=buff0[0]; fs.Read(buff0,0,1); dataxy[ii,1]=buff0[0]; fs.Read(buff0,0,1); datachar[ii]=buff0[0]; } datanum=allnum; fs.Close(); } /// <summary> /// 验证码图片 /// </summary> public System.Drawing.Bitmap bp =new System.Drawing.Bitmap(49,20); /// <summary> /// 特征库的长度 /// </summary> public static int datanum=0; /// <summary> /// 特征库数据 /// </summary> public static ushort[,] datap=new ushort[100000,20]; /// <summary> /// 长度与高度 /// </summary> public static byte[,] dataxy=new byte[100000,2]; /// <summary> /// 对应的字符 /// </summary> public static byte[] datachar=new byte[100000]; /// <summary> /// 等待处理的数据 /// </summary> public ushort[] datapic=new ushort[20]; /// <summary> /// 有效长度 /// </summary> public byte xlpic=0; /// <summary> /// 有效宽度 /// </summary> public byte ylpic=0; /// <summary> /// 检索特征库中存在的记录 /// </summary> public string getchar() { //如果查找不到,就返回空串 string jieguo=""; for(int ii=0;ii<datanum;ii++) { //统计一共有多少行的像素有差异,如果在4行以内就认为是存在该记录 //这种方法比较原始,但比较适合多线程时的运行,因为程序只进行简单的逻辑比较 //如果能够收集更多的特征库,识别率可以达到80%以上 //(此时可能需要将特征库的容量提高到15W个或以上) //当然也可以改进品配算法(如使用关键点品配),以用较少的特征库达到较高的识别率,但 //那样有比较大的机会造成识别错误并且多线程时占用较多CPU时间。 int notsamenum=0; if(dataxy[ii,0]!=xlpic || dataxy[ii,1]!=ylpic) { continue; } for(int jj=0;jj<20;jj++) { if(datap[ii,jj]!=datapic[jj]) { notsamenum++; } } if(notsamenum<4) { char cj=(char)datachar[ii]; return cj.ToString(); } } return jieguo; } /// <summary> /// 检查特征库中是否已经存在相关记录 /// </summary> bool ischardatain() { bool jieguo=false; for(int ii=0;ii<datanum;ii++) { //统计一共有多少行的像素有差异,如果在4行以内就认为是存在该记录 //这种方法比较原始,但比较适合多线程时的运行,因为程序只进行简单的逻辑比较 //如果能够收集更多的特征库,识别率可以达到80%以上 //(此时可能需要将特征库的容量提高到15W个或以上) //当然也可以改进品配算法(如使用关键点品配),以用较少的特征库达到较高的识别率,但 //那样有比较大的机会造成识别错误并且多线程时占用较多CPU时间。 int notsamenum=0; if(System.Math.Abs(dataxy[ii,0]-xlpic)>1 || System.Math.Abs(dataxy[ii,1]-ylpic)>1) { continue; } for(int jj=0;jj<20;jj++) { if(datap[ii,jj]!=datapic[jj]) { notsamenum++; } } if(notsamenum<4) { string asdasd=((char)datachar[ii]).ToString(); return true; } } return jieguo; } /// <summary> /// 添加到特征库中,并暂时将对应的字符置为空格以待人工识别 /// </summary> void adddatawithnullchar() { if(this.ischardatain()) { return; } for(int ii=0;ii<20;ii++) { datap[datanum,ii]=this.datapic[ii]; } |
|
![]() |
![]() |