当前位置:  编程技术>.net/c#/asp.net

使用C#的aforge类库识别验证码实例

    来源: 互联网  发布时间:2014-11-02

    本文导语:  时间过得真快啊,转眼今年就要过去了,大半年都没有写博客了,要说时间嘛,花在泡妹子和搞英语去了,哈哈。。。前几天老大问我 怎么这么长时间都没写博客了,好吧,继续坚持,继续分享我的心得体会。   这个系列...

时间过得真快啊,转眼今年就要过去了,大半年都没有写博客了,要说时间嘛,花在泡妹子和搞英语去了,哈哈。。。前几天老大问我

怎么这么长时间都没写博客了,好吧,继续坚持,继续分享我的心得体会。

  这个系列我们玩玩aforge.net,套用官方都话就是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的

资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域,这个系列研究的重点

就是瞎几把搞下AForge.Imaging这个命名空间下面的东东,下载网址:http://www.aforgenet.com/framework/downloads.html

    对了,不知道有多少公司是用得仕卡作为员工的福利卡,我们公司就是这样的,每个月公司都会充值一些money,然后我们这些屁码农每个月15号就都开心的去看看发了多少。

上去看了后,哟呵~ 还有个90年代的验证码,我想这年头估计找到这样验证码的网站已经不多了,如果懂一点图像处理都话,这张验证码

跟没有一个样,谢谢。。。这篇我们看看怎么去识别它。

一: 验证码处理

1.  一般处理原则

    这种验证码为什么说跟没有一样,第一点:字体规范工整,第二点:不旋转扭曲粘连,第三点:字体颜色单一,下面看处理步骤。

这里要注意的是,aforge只接受像素格式为24/32bpp的像素格式图片,所以处理前,先进行格式转化。

代码如下:

//转化图片像素格式
            var bnew = new Bitmap(b.Width, b.Height, PixelFormat.Format24bppRgb);

            Graphics g = Graphics.FromImage(bnew);

            g.DrawImage(b, 0, 0);

            g.Dispose();

图片灰度化

这是图像识别通常都要走的第一步,图片灰度化有助于减少后续对rgb的计算量,同时也方便我们进行二值化,在aforge中我们有专门的类一步搞定,简洁方便。

代码如下:

            //灰度化
            b = new Grayscale(0.2125, 0.7154, 0.0721).Apply(b);

二值化

  二值化顾名思义就是二种值,比如非白即黑,非黑即白,那么白和黑的标准就需要提供一个阈值,大于或者小于怎么样,在aforge同样也有相似的类进行处理

代码如下:

            //二值化
            b = new Threshold(50).Apply(b);

去噪点

  从上面的图片可以发现有很多红点点,搞得像皮肤病一样,仔细观察可以看到这种噪点具有独立,体积小的特征,所以判断的标准就是如果图中某个区块的大小在我设置的阈值内,就将其去掉,同样也有专门的类进行处理。

代码如下:

            //去噪点
            new BlobsFiltering(1, 1, b.Width, b.Height).Apply(b);

  这里具体怎么传递参数,后续系列会慢慢解读。

切割图片

   切图片的好处在于我们需要知道真正要识别的元素的有效范围是多大,同时也方便我们将这些图片作为模板保存下来。

代码如下:

代码如下:

///
        /// 按照 Y 轴线 切割
        /// (丢弃等于号)
        ///
        ///
        ///
        public List Crop_Y(Bitmap b)
        {
            var list = new List();

            //统计每一列的“1”的个数,方便切除
            int[] cols = new int[b.Width];

            /*
             *  纵向切割
             */
            for (int x = 0; x < b.Width; x++)
            {
                for (int y = 0; y < b.Height; y++)
                {
                    //获取当前像素点像素
                    var pixel = b.GetPixel(x, y);

                    //说明是黑色点
                    if (pixel.R == 0)
                    {
                        cols[x] = ++cols[x];
                    }
                }
            }

            int left = 0, right = 0;

            for (int i = 0; i < cols.Length; i++)
            {
                //说明该列有像素值(为了防止像素干扰,去噪后出现空白的问题,所以多判断一下,防止切割成多个)
                if (cols[i] > 0 || (i + 1 < cols.Length && cols[i + 1] > 0))
                {
                    if (left == 0)
                    {
                        //切下来图片的横坐标left
                        left = i;
                    }
                    else
                    {
                        //切下来图片的横坐标right
                        right = i;
                    }
                }
                else
                {
                    //说明已经有切割图了,下面我们进行切割处理
                    if ((left > 0 || right > 0))
                    {
                        Crop corp = new Crop(new Rectangle(left, 0, right - left + 1, b.Height));

                        var small = corp.Apply(b);

                        //居中,将图片放在20*50的像素里面

                        list.Add(small);
                    }

                    left = right = 0;
                }
            }

            return list;
        }

        ///
        /// 按照 X 轴线 切割
        ///
        ///
        ///
        public List Crop_X(List list)
        {
            var corplist = new List();

            //再对分割的图进行上下切割,取出上下的白边
            foreach (var segb in list)
            {
                //统计每一行的“1”的个数,方便切除
                int[] rows = new int[segb.Height];

                /*
                 *  横向切割
                 */
                for (int y = 0; y < segb.Height; y++)
                {
                    for (int x = 0; x < segb.Width; x++)
                    {
                        //获取当前像素点像素
                        var pixel = segb.GetPixel(x, y);

                        //说明是黑色点
                        if (pixel.R == 0)
                        {
                            rows[y] = ++rows[y];
                        }
                    }
                }

                int bottom = 0, top = 0;

                for (int y = 0; y < rows.Length; y++)
                {
                    //说明该行有像素值(为了防止像素干扰,去噪后出现空白的问题,所以多判断一下,防止切割成多个)
                    if (rows[y] > 0 || (y + 1 < rows.Length && rows[y + 1] > 0))
                    {
                        if (top == 0)
                        {
                            //切下来图片的top坐标
                            top = y;
                        }
                        else
                        {
                            //切下来图片的bottom坐标
                            bottom = y;
                        }
                    }
                    else
                    {
                        //说明已经有切割图了,下面我们进行切割处理
                        if ((top > 0 || bottom > 0) && bottom - top > 0)
                        {
                            Crop corp = new Crop(new Rectangle(0, top, segb.Width, bottom - top + 1));

                            var small = corp.Apply(segb);

                            corplist.Add(small);
                        }

                        top = bottom = 0;
                    }
                }
            }

            return corplist;
        }

图片精处理

  这里要注意的是,比如数字“2”,切除上下左右的空白后,再加上噪点的干扰,不一定每次切下来的图片大小都一样,所以这里为了方便更好的识别,我们需要重置下图片的大小,并且将“数字2”进行文字居中。

代码如下:

///
        /// 重置图片的指定大小并且居中
        ///
        ///
        ///
        public List ToResizeAndCenterIt(List list, int w = 20, int h = 20)
        {
            List resizeList = new List();


            for (int i = 0; i < list.Count; i++)
            {
                //反转一下图片
                list[i] = new Invert().Apply(list[i]);

                int sw = list[i].Width;
                int sh = list[i].Height;

                Crop corpFilter = new Crop(new Rectangle(0, 0, w, h));

                list[i] = corpFilter.Apply(list[i]);

                //再反转回去
                list[i] = new Invert().Apply(list[i]);

                //计算中心位置
                int centerX = (w - sw) / 2;
                int centerY = (h - sh) / 2;

                list[i] = new CanvasMove(new IntPoint(centerX, centerY), Color.White).Apply(list[i]);

                resizeList.Add(list[i]);
            }

            return resizeList;
        }

其实精处理后,这些图片就可以作为我们的模板库的图片了,可以将每张模板图都标记下具体的数字,后续我们再遇到时,计算下其相似度就可以了,下面就是已经制作好的模板。

模板匹配识别

  既然模板图片都制作好了,一切都差不多水到渠成了,下次来的验证码我都切好后做成精图片后跟模板进行匹配,在afroge里面

有一个ExhaustiveTemplateMatching,专门用来进行模板匹配用的,很方便。

代码如下:

 ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.9f);

这里的0.9f就是设定的阈值,只有大于0.9的阈值,我才认为该模板与目标图片相似,然后在所有大于0.9的相似度中取到最大的一个作为

我们最后识别的图像。

代码如下:

var files = Directory.GetFiles(Environment.CurrentDirectory + "\Template\");

            var templateList = files.Select(i => { return new Bitmap(i); }).ToList();
            var templateListFileName = files.Select(i => { return i.Substring(30, 1); }).ToList();

            var result = new List();

            ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.9f);

            //这里面有四张图片,进行四张图的模板匹配
            for (int i = 0; i < list.Count; i++)
            {
                float max = 0;
                int index = 0;

                for (int j = 0; j < templateList.Count; j++)
                {
                    var compare = templateMatching.ProcessImage(list[i], templateList[j]);

                    if (compare.Length > 0 && compare[0].Similarity > max)
                    {
                        //记录下最相似的
                        max = compare[0].Similarity;
                        index = j;
                    }
                }

                result.Add(templateListFileName[index]);
            }

最后的效果还是不错的,识别率基本100%吧。


    
 
 

您可能感兴趣的文章:

  • c#中SAPI使用总结——SpVoice的使用方法
  • android 弹出提示框的使用(图文实例) iis7站长之家
  • 请问在工作岗位的朋友!使用java开发的公司对c#的态度如何?
  • c#自带缓存使用方法 c#移除清理缓存
  • C#中的switch case使用介绍
  • c# 空合并运算符“??”的使用详解
  • 使用C#实现在屏幕上画图效果的代码实例
  • 深入C#中使用SqlDbType.Xml类型参数的使用详解
  • c#闭包使用方法示例
  • c# split分隔字符串使用方法
  • c#的params参数使用示例
  • c#使用资源文件的示例
  • 使用C# Winform应用程序获取网页源文件的解决方法
  • C#将时间转成文件名使用方法
  • C# 使用匿名函数解决EventHandler参数传递的难题
  • 使用C#获取系统特殊文件夹路径的解决方法
  • C#使用带like的sql语句时防sql注入的方法
  • C#可选参数的相关使用
  • C# 静态构造函数使用总结
  • C# WndProc的使用方法示例
  • 使用libpcap读取tcpdump抓取的文件并解析c代码实例
  • 类的方法和实例方法,类字段和实例字段有什么不同,在使用上?
  • Python namedtuple(命名元组)使用实例
  • LINUX中实现单实例功能使用哪种IPC好啊?
  • boost库区间range基本原理及使用实例
  • android 弹出提示框的使用(图文实例)
  • c++类库Boost::bimap(双向映射)介绍及使用实例
  • 使用PackageManager获得应用信息实例方法
  • mongodb 数据库常用命令使用实例
  • android自动安装apk代码实例(不使用apk安装器安装)
  • java获取当前日期使用实例
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • simon语音识别系统的使用
  • 在REDHAT 9.0中,如何识别及使用PCMCIA FLASH卡?
  • linux下如何识别并使用磐正Epox 8RDA+ 主板集成的网卡?(万分焦急)
  • 使用Virtual PC安装Red Hat Linux 9.0时显卡识别错误,如何改回来?
  • 使用test如何识别变量为空字符串?
  • 能在Linux系统中使用的语音识别系统
  • android使用gesturedetector手势识别示例分享
  • Android上使用ZXing识别条形码与二维码的方法
  • C++ I/O 成员 tellg():使用输入流读取流指针
  • 在测试memset函数的执行效率时,分为使用Cash和不使用Cash辆种方式,该如何控制是否使用缓存?
  • C++ I/O 成员 tellp():使用输出流读取流指针
  • 求ibm6000的中文使用手册 !从来没用过服务器,现在急需使用它,不知如何使用! 急!!!!!
  • Python不使用print而直接输出二进制字符串
  • 请问:在使用oracle数据库作开发时,是使用pro*c作开发好些,还是使用库函数如oci等好一些啊?或者它们有什么区别或者优缺点啊?
  • Office 2010 Module模式下使用VBA Addressof
  • 急求结果!!假设一个有两个元素的信号量集S,表示了一个磁带驱动器系统,其中进程1使用磁带机A,进程2同时使用磁带机A和B,进程3使用磁带机B。
  • windows下tinyxml.dll下载安装使用(c++解析XML库)
  • 使用了QWidget的程序,如何使用后台程序启动它?
  • tcmalloc内存泄露优化c++开源库下载,安装及使用介绍
  • 共享内存一般是怎么使用的,是同消息队列配合使用么
  • sharepoint 2010 使用STSNavigate函数实现文件下载举例
  • Jsp可否使用带有GUI的JavaBean,如何使用?
  • c/c++预处理命令预#,##使用介绍
  • asp程序使用的access在Linux下如何使用!
  • 在div中使用css让文字底部对齐的方法
  • 新装的Linux使用root用户不能使用FTP?
  • MySQL Workbench的下载安装与使用教程
  • LINUX下使用Eclipse,如何使用交叉编译器?
  • nginx Windows版相关问题及使用说明
  • redhat9内存使用率高达73%,怎么查看内存具体使用情况


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3