淘宝验证码破解之轮廓线
现在的验证码已经不是什么花哨的复杂背景了,而趋于背景单一,但字体扭曲,粘连,加上和字体同样颜色的干扰线,所以这个发展趋势就像武功练到一定境界时反而招式简单,却威力巨大。有句话叫做什么来着--返璞归真。
看看淘宝的验证码:让人纠结吧。
下面开始我们的破解之旅:淘宝验证码破解之轮廓线。
先从指定连接获取验证码图片:
//获取验证码
private Bitmap GetCode(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
System.IO.Stream responseStream = ((HttpWebResponse)request.GetResponse()).GetResponseStream();
Image original = Image.FromStream(responseStream);
Bitmap bitMap = new Bitmap(original);
responseStream.Close();
return bitMap;
}
//图片拷贝
由于我们建立的对象是引用类型。所以得用拷贝函数。
private Bitmap CopyImg(Bitmap img)
{
int W = img.Width;
int H = img.Height;
Bitmap NewImg = new Bitmap(W, H);
for (int y = 0; y < H; y++)
{
for (int x = 0; x < W; x++)
{
Color C = img.GetPixel(x, y);
NewImg.SetPixel(x, y, C);
}
}
return NewImg;
}
//图象二值化
public Bitmap BitmapToHead(Bitmap Timg)
{
Bitmap img = CopyImg(Timg);
int W = img.Width;
int H = img.Height;
for (int y = 0; y < H;y++ )
{
for(int x=0;x<W;x++)
{
Color c = img.GetPixel(x, y);
int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);//转换灰度的算法
img.SetPixel(x, y, Color.FromArgb(luma, luma, luma));
}
}
for(int y = 0; y < H;y++){
for (int x = 0; x < W; x++)
{
Color c = img.GetPixel(x, y);
if (c.R >= 120) //设置一个合适的临界值 大于等于临界值设为白色,小于临界值为黑色
img.SetPixel(x, y, Color.FromArgb(255, 255, 255));
else img.SetPixel(x, y, Color.FromArgb(0, 0, 0));
}
}
return img;
}
下面就是关键算法了。跟踪轮廓线:
//轮廓线算法
private Bitmap ContourFollowing(Bitmap Timg)
{
Bitmap img = CopyImg(Timg);
int W = img.Width-1;
int H = img.Height-1;
for (int y = 0; y <=H; y++)
{
for (int x = 0; x <=W; x++)
{
if (y == 0 && x == 0)
{
//break;
}
else if (y == 0 && x > 0 && x < W)
{
// break;
}
else if (y == 0 && x == W)
{
//break;
}
else if (y > 0 && y < H && x == 0)
{
// break;
}
else if (x == 0 && y == H)
{
//break;
}
else if (x > 0 && x < W && y == H)
{
//break;
}
else if (x == W && y == H)
{
//break;
}
else if (x == W&& y > 0 && y < H)
{
//break;
}
else
{
Color Cm = img.GetPixel(x, y);
Color[] Ccenter = new Color[] { img.GetPixel(x - 1, y), img.GetPixel(x, y - 1), img.GetPixel(x, y + 1), img.GetPixel(x + 1, y) };
int flag = 0;
if (Cm.R == 0)
{
for (int i = 0; i < 4; i++)
{
if (Ccenter[i].R==0||Ccenter[i].R==100)
{
flag++;
}
}
}
if (flag == 4)
{
img.SetPixel(x, y, Color.FromArgb(100, 100, 100));
}
}
}
}
for (int y = 0; y < H; y++)
{
for (int x = 0; x < W; x++)
{
Color c = img.GetPixel(x, y);
if (c.R == 100)
img.SetPixel(x, y, Color.FromArgb(255, 255, 255));
}
}
return img;
}
下面函数调用,画出轮廓线。
private void button1_Click(object sender, EventArgs e)
{
string url = textBox4.Text;
//Bitmap Map =GetCode(url);
Bitmap Mapp = CopyImg(GetCode1(url));
Bitmap Map1 = BitmapToHead(Mapp);
Bitmap Fuck = CopyImg(Map1);
Bitmap Map2 = ContourFollowing(Fuck);
pictureBox3.Image = Map1;
pictureBox4.Image = Map2;
}