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];
}
//暂时将对应的字符置为空格以待人工识别
datachar[datanum]=32;
dataxy[datanum,0]=this.xlpic;
dataxy[datanum,1]=this.ylpic;
datanum++;
}
/// <summary>
/// 检查验证码图片是否能分成4个部分,如果可以就检查4个字符在特征库中是否已经存在,如果不存在,
/// 就添加到特征库中,并暂时将对应的字符置为空格以待人工识别
/// </summary>
public void writetodata()
{
bool[,] picpixel=new bool[49,20];
for(int ii=0;ii<49;ii++)
{
for(int jj=0;jj<20;jj++)
{
if(bp.getpixel(ii,jj).getbrightness()<0.999)
{
picpixel[ii,jj]=true;
}
}
}
int[] index=new int[8];
int indexnum=0;
bool black=false;
for(int ii=0;ii<49;ii++)
{
bool haveblack=false;
for(int jj=0;jj<20;jj++)
{
if(picpixel[ii,jj])
{
haveblack=true;
break;
}
}
if(haveblack && black==false)
{
index[indexnum]=ii;
indexnum++;
black=true;
}
if(!haveblack && black)
{
index[indexnum]=ii;
indexnum++;
black=false;
}
}
if(indexnum<7)
{
return;
}
if(indexnum==7)
{
index[7]=49;
}
//****
for(int ii=0;ii<4;ii++)
{
int x1=index[ii*2];
int x2=index[ii*2+1];
int y1=0,y2=19;
bool mb=false;
for(int jj=0;jj<20;jj++)
{
for(int kk=x1;kk<x2;kk++)
{
if(picpixel[kk,jj])
{
mb=true;
break;
}
}
if(mb)
{
y1=jj;
break;
}
}
mb=false;
for(int jj=19;jj>=0;jj--)
{
for(int kk=x1;kk<x2;kk++)
{
if(picpixel[kk,jj])
{
mb=true;
break;
}
}
if(mb)
{
y2=jj;
break;
}
}
//**以上是获取有效区域的范围
for(int jj=0;jj<20;jj++)
{
this.datapic[jj]=0;
this.datapic[jj]=0;
}
this.xlpic=(byte)(x2-x1);
//如果字符宽度超过16个像素就不予处理
if(xlpic>16)
{
continue;
}
this.ylpic=(byte)(y2-y1+1);
int ys=-1;
ushort[] addin=new ushort[]{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
for(int jj=y1;jj<=y2;jj++)
{
ys++;
int xs=-1;
for(int kk=x1;kk<x2;kk++)
{
xs++;
if(picpixel[kk,jj])
{
this.datapic[ys]=(ushort)(this.datapic[ys]+addin[xs]);
}
}
}
this.adddatawithnullchar();
}
//****
}
/// <summary>
/// 识别图片
/// </summary>
/// <returns>返回识别结果(如果返回的字符串长度小于4就说明识别失败)</returns>
public string ocrpic()
{
string jieguo="";
bool[,] picpixel=new bool[49,20];
for(int ii=0;ii<49;ii++)
{
for(int jj=0;jj<20;jj++)
{
if(bp.getpixel(ii,jj).getbrightness()<0.999)
{
picpixel[ii,jj]=true;
}
}
}
int[] index=new int[8];
int indexnum=0;
bool black=false;
for(int ii=0;ii<49;ii++)
{
bool haveblack=false;
for(int jj=0;jj<20;jj++)
{
if(picpixel[ii,jj])
{
haveblack=true;
break;
}
}
if(haveblack && black==false)
{
index[indexnum]=ii;
indexnum++;
black=true;
}
if(!haveblack && black)
{
index[indexnum]=ii;
indexnum++;
black=false;
}
}
if(indexnum<7)
{
return jieguo;
}
if(indexnum==7)
{
index[7]=49;
}
//****
for(int ii=0;ii<4;ii++)
{
int x1=index[ii*2];
int x2=index[ii*2+1];
int y1=0,y2=19;
bool mb=false;
for(int jj=0;jj<20;jj++)
{
for(int kk=x1;kk<x2;kk++)
{
if(picpixel[kk,jj])
{
mb=true;
break;
}
}
if(mb)
{
y1=jj;
break;
}
}
mb=false;
for(int jj=19;jj>=0;jj--)
{
for(int kk=x1;kk<x2;kk++)
{
if(picpixel[kk,jj])
{
mb=true;
break;
}
}
if(mb)
{
y2=jj;
break;
}
}
//**以上是获取有效区域的范围
for(int jj=0;jj<20;jj++)
{
this.datapic[jj]=0;
this.datapic[jj]=0;
}
this.xlpic=(byte)(x2-x1);
//如果字符宽度超过16个像素就不予处理
if(xlpic>16)
{
continue;
}
this.ylpic=(byte)(y2-y1+1);
int ys=-1;
ushort[] addin=new ushort[]{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
for(int jj=y1;jj<=y2;jj++)
{
ys++;
int xs=-1;
for(int kk=x1;kk<x2;kk++)
{
xs++;
if(picpixel[kk,jj])
{
this.datapic[ys]=(ushort)(this.datapic[ys]+addin[xs]);
}
}
}
jieguo=jieguo+this.getchar();
}
return jieguo;
}
}
}
分享到:
相关推荐
QQ验证码识别源代码(C#/NET1.1)
QQ验证码识别C#
C#编写的QQ+源代码C#编写的QQ+源代码C#编写的QQ+源代码C#编写的QQ+源代码
界面很酷的C#仿QQ聊天软件源代码C# 界面很酷的C#仿QQ聊天软件源代码C#
QQ源代码 C# LanMsgC#1.0.1.1
机票查询源代码C#/.net机票查询源代码C#/.net机票查询源代码C#/.net机票查询源代码C#/.net机票查询源代码C#/.net机票查询源代码C#/.net
C#模仿QQ靠边停靠效果源代码,修改了原本网上看到的最小化之后不能恢复到之前位置的bug,完美的实现了C#的靠边停靠的效果!
c/s架构的。只是一个草稿,可以互相通讯。一个朋友写的。我转给大家学习
验证码处理 源代码 博客地址:https://blog.csdn.net/qq_26696715/article/details/115263274 视频地址:https://live.csdn.net/v/157825
java 模仿QQ图片验证码-源代码
这是一个很好用的用c#做的QQ程序 希望对大家有帮助
QQ验证码识别
C#仿QQ聊天软件源代码 C#仿QQ聊天软件源代码
C#QQ宠物源代码主要是采用窗体透明非,常有意思大家有空的可以看看,对于初学者很有用的。
亦思专业验证码识别系统,拥有国内领先的验证码识别技术,给您带来全新的验证码识别体验,3大分割方式,3大识别模式,将近20种处理滤镜, 拥有识别库体积小(10个验证地址小于5K),识别速度快(1毫秒以下),做到...
超真仿QQ的源代码之c#语言 仅供学习参考使用
基于.net的C#qq源代码,下载后点个赞哦
早期的QQ验证码识别,可用于简单验证码识别,仅供参考
配合手写汉字识别系统使用 原数据集下载: http://www.nlpr.ia.ac.cn/databases/download/feature_data/HWDB1.1trn_gnt.zip http://www.nlpr.ia.ac.cn/databases/download/feature_data/HWDB1.1tst_gnt.zip 解压后是...
Windows Phone 7 QQ词典V1.1 共享源代码 c#源代码