程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> QQ驗證碼識別源代碼(C#/NET1.1)

QQ驗證碼識別源代碼(C#/NET1.1)

編輯:關於C語言
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;
}
}
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved