简单验证码的识别步骤有:黑白、锐化、切分、建模。
说说如何锐化,我从网上找到一个C#版本的:
//hsb: 0与1之间的值 public static Bitmap BitmapTo1Bpp(Bitmap img,Double hsb) { int w = img.Width; int h = img.Height; Bitmap bmp = new Bitmap(w, h, PixelFormat.Format1bppIndexed); BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed); for (int y = 0; y < h; y++) { byte[] scan = new byte[(w + 7) / 8]; for (int x = 0; x < w; x++) { Color c = img.GetPixel(x, y); //Console.WriteLine(c.GetBrightness().ToString()); if (c.GetBrightness() >= hsb ) scan[x / 8] |= (byte)(0x80 >> (x % 8)); } Marshal.Copy(scan, 0, (IntPtr)((int)data.Scan0 + data.Stride * y), scan.Length); } bmp.UnlockBits(data); return bmp; }
网上有不少图片处理类,所谓的“锐化”都起不到真正的效果。对于jpg等已经压缩过的图片,放大后,是可以看到空白区域有很多杂点的。用下面的函数,就可以轻松搞定:
function imagelightnessat($img, $x, $y) { if(!is_resource($img)) { trigger_error("imagelightnessat(): supplied argument is not a valid " . "Image resource", E_USER_WARNING); return 0.0; } $c = @imagecolorat($img, $x, $y); if($c === false) return false; if(imageistruecolor($img)) { $red = ($c >> 16) & 0xFF; $green = ($c >> 8) & 0xFF; $blue = $c & 0xFF; } else { $i = imagecolorsforindex($img, $c); $red = $i['red']; $green = $i['green']; $blue = $i['blue']; } $m = min($red, $green, $blue); $n = max($red, $green, $blue); /* Because RGB isn't normalized in GD, we divide by 510 here. * Lightness = (Max(RGB) + Min(RGB)) / 2 * But that's assuming red, green, and blue are 0 through 1 inclusive. * Red, green, and blue are actually 0-255 (255 + 255 = 510). */ $lightness = (double)(($m + $n) / 510.0); return($lightness); }
上面的函数来自于php.net线上手册注释。
有了清晰的、无干扰点的图片,剩下的事情,就很简单了。