C# + tesseract 8位图( 调色板索引)的简单消噪和验证码破解的实现

最近针对一批网站做采集,做着做着突然发现有个网站居然要验证码,以前哥在学校也看过这方面的资料,只是没具体做,真的自己做这个破解会需要很多数学知识和其他知识,可是哥已经工作了,哪来那么多时间写这个东西,于是用现存的开源库就最好,在网上搜了搜,找到一个还不错的库,叫tesseract,参见Tesseract-OCR引擎 入门,自己找了几个图片,发现个问题,就是当验证码很多噪声时,就识别不出来,于是必须消噪。

又在网上找了下,没有找到C#的,java和C++倒是有很多,可是C++很长时间没写,而且图片格式需要自己解析,很麻烦,很容易出错,于是决定还是用C#,很幸运的搜到了c#使用指针快速操作图片这篇文章,这篇文章有个缺点,就是这个不是基于调色板的图片,如果按照这篇文章的颜色赋值会出错误,于是在System.Drawing.Imaging目录下搜索,发现了有Palette这个元素,可是还是不会,就在上网一搜,果然就发现了用法,于是照着写就好了。
        以上是C#操作位图的具体方式的查找,那么怎么实现消噪了,我觉的方法有很多,比如这个样例里,

噪点很多,可以考虑统计颜色出现的次数,把噪点出现的颜色都设置成白色,再交给tesseract处理(我是过,下过不是很好,噪点重复会导致颜色区别比较大);比如说根据数据颜色设定一个颜色范围值,但是有个缺点,就是RGB三原色的组合很多,不一定准,只适合能确定数据颜色比较固定的,我这个偷了赖,我发现这个网站的噪声颜色和数据颜色基本是固定,很明显看出数据是偏黑色额,而噪点是偏蓝色的,而我在Palette.Entries中发现GetBrightness()这个方法,搜了一下msdn,发现0.0代表黑色,1.0代表白色,于是就用这个方法,废话不多说,上代码(代码中的0.2是试出来的,看官要设置成自己合适的值),

        public void JPEGDenosing(string jpg)
        {
            Bitmap bp = new Bitmap(jpg);
            Rectangle rect = new Rectangle(0, 0, bp.Width, bp.Height);
            ColorPalette palette = bp.Palette;
            int pc = palette.Entries.Length;
            //BitmapData bpData = bp.LockBits(rect, ImageLockMode.ReadWrite, bp.PixelFormat);

            //IntPtr ptr = bpData.Scan0;
            //System.Drawing.Imaging.ColorPalette
            //int bytes = bp.Width * bp.Height;   //不用乘3,因为这是个8bit的
            //byte[] regValues = new byte[bytes];
            //以下设置将会不正确。因为8位位图使用的是索引,而不是实际的值
            //System.Runtime.InteropServices.Marshal.Copy(ptr, regValues, 0, bytes);
            //for (int count = 0; count < regValues.Length; ++count )
            //{
                //这种修改只适合8位以上的位图
                //regValues[count] = 0;
            //}

            //System.Runtime.InteropServices.Marshal.Copy(regValues, 0, ptr, bytes);
            //bp.UnlockBits(bpData);
            for (int i = 0; i < pc; ++i)
            {
                if (((double)palette.Entries[i].GetBrightness()) > 0.2 )
                {
                    palette.Entries[i] = Color.FromArgb(255, 255, 255);
                }
            }

            bp.Palette = palette;

            bp.Save(@"C:\11.jpg");
        }
很好,现在得出的图片就成这个样子了:

那么得出来的图片再怎么用了呢?这就非常简单了,可以通过调用cmd程序来间接调用,或者通过调用tesseract.exe并传参数来实现,再来读取txt文件就好了。经过测试,经过这种处理的图片可以正常识别。

至于有人怀疑C#速度会比较慢,那么还是请参考c#使用指针快速操作图片这篇文章。由于验证码图片一般比较小,而且我这个还属于原型验证阶段,所以就先这样了。

你可能感兴趣的:(C#.采集)