字体固定,位置固定,干扰点和字体颜色深度没有交叉,比如下面的样例,是我前几天帮朋友写投票机刷票时碰到的一个具体案例。
基本就三步,确定特征码-分割图片-逐个匹配,代码很简单,不超过100行
using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace BmpNumber { class Number { //数字特征库 static int[,] _num0 = new int[7, 10] { { 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, { 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, { 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 }, { 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 } }; static int[,] _num1 = new int[7, 10] { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; static int[,] _num2 = new int[7, 10] { { 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 }, { 0, 1, 1, 1, 0, 0, 0, 1, 1, 1 }, { 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 }, { 1, 1, 0, 0, 0, 1, 1, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 1, 1, 1, 0, 0, 0, 1, 1 }, { 0, 1, 1, 1, 0, 0, 0, 0, 1, 1 } }; static int[,] _num3 = new int[7, 10] { { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 }, { 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }, { 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0, 0 } }; static int[,] _num4 = new int[7, 10] { { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 }, { 0, 0, 1, 1, 1, 0, 1, 1, 0, 0 }, { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 } }; static int[,] _num5 = new int[7, 10] { { 0, 0, 0, 1, 1, 1, 0, 1, 1, 0 }, { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 0, 0, 1, 1 }, { 1, 1, 0, 1, 1, 0, 0, 0, 1, 1 }, { 1, 1, 0, 1, 1, 0, 0, 0, 1, 1 }, { 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }, { 1, 1, 0, 0, 0, 1, 1, 1, 0, 0 } }; static int[,] _num6 = new int[7, 10] { { 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, { 1, 1, 1, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 0, 1, 1, 1, 1, 0 } }; static int[,] _num7 = new int[7, 10] { { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 1, 1, 1, 0, 0, 0, 0 }, { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 } }; static int[,] _num8 = new int[7, 10] { { 0, 1, 1, 1, 0, 0, 1, 1, 1, 0 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 1, 0, 0, 1, 1, 1, 0 } }; static int[,] _num9 = new int[7, 10] { { 0, 1, 1, 1, 1, 0, 0, 1, 1, 0 }, { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 } }; static private int[,] getNum(Bitmap bmp, int index) { //分割图片 int[,] _num = new int[7, 10]; for (int i = index * 10 + 2; i < index * 10 + 9; i++) { for (int j = 6; j < 16; j++) { Color c = bmp.GetPixel(i, j); if (c.R < 100) { _num[i - 2 - index * 10, j - 6] = 1; } } } return _num; } static private int CheckNumber(int[,] number) { if (CheckNumber(_num0, number) == true) return 0; if (CheckNumber(_num1, number) == true) return 1; if (CheckNumber(_num2, number) == true) return 2; if (CheckNumber(_num3, number) == true) return 3; if (CheckNumber(_num4, number) == true) return 4; if (CheckNumber(_num5, number) == true) return 5; if (CheckNumber(_num6, number) == true) return 6; if (CheckNumber(_num7, number) == true) return 7; if (CheckNumber(_num8, number) == true) return 8; if (CheckNumber(_num9, number) == true) return 9; return 6; } static private bool CheckNumber(int[,] dic, int[,] number) { //逐个匹配 for (int i = 0; i < 7; i++) { for (int j = 0; j < 10; j++) { if (dic[i, j] == 1 && number[i, j] != 1) { return false; } } } return true; } static public string getNumber(Bitmap bmp) { //调用 string str = ""; for (int i = 0; i <= 3; i++) { int[,] number = getNum(bmp, i); int m = CheckNumber(number); str += m.ToString(); } return str; } } }
用以下代码调用就可以看到输出结果为9637了,这个识别代码没有用到任何高级算法,所以也只能识别初级的验证码,但是对特征库扩展之后也可以识别出规范的字母。
System.Net.WebClient wb = new System.Net.WebClient(); byte[] b=wb.DownloadData("http://p.blog.csdn.net/images/p_blog_csdn_net/jinjazz/355056/o_rrr.bmp"); System.IO.MemoryStream ms=new System.IO.MemoryStream(b); System.Drawing.Bitmap bmp = new Bitmap(ms); string str = BmpNumber.Number.getNumber(bmp); Console.WriteLine(str);