当前位置: 首页 > 编程笔记 >

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

齐飞星
2023-03-14
本文向大家介绍使用C#的aforge类库识别验证码实例,包括了使用C#的aforge类库识别验证码实例的使用技巧和注意事项,需要的朋友参考一下

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

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

  这个系列我们玩玩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();

<1>图片灰度化

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


            //灰度化

            b = new Grayscale(0.2125, 0.7154, 0.0721).Apply(b);


<2>二值化

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


            //二值化

            b = new Threshold(50).Apply(b);


<3> 去噪点

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


            //去噪点

            new BlobsFiltering(1, 1, b.Width, b.Height).Apply(b);


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

<4>切割图片

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

代码如下:


/// <summary>

        /// 按照 Y 轴线 切割

        /// (丢弃等于号)

        /// </summary>

        /// <param name="?"></param>

        /// <returns></returns>

        public List<Bitmap> Crop_Y(Bitmap b)

        {

            var list = new List<Bitmap>();

            //统计每一列的“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;         }

        /// <summary>         /// 按照 X 轴线 切割         /// </summary>         /// <param name="b"></param>         /// <returns></returns>         public List<Bitmap> Crop_X(List<Bitmap> list)         {             var corplist = new List<Bitmap>();

            //再对分割的图进行上下切割,取出上下的白边             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;         }

<5> 图片精处理

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


/// <summary>

        /// 重置图片的指定大小并且居中

        /// </summary>

        /// <param name="list"></param>

        /// <returns></returns>

        public List<Bitmap> ToResizeAndCenterIt(List<Bitmap> list, int w = 20, int h = 20)

        {

            List<Bitmap> resizeList = new List<Bitmap>();

            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;         }

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

<6> 模板匹配识别

  既然模板图片都制作好了,一切都差不多水到渠成了,下次来的验证码我都切好后做成精图片后跟模板进行匹配,在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<string>();

            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%吧。

 类似资料:
  • 本文向大家介绍python验证码识别的实例详解,包括了python验证码识别的实例详解的使用技巧和注意事项,需要的朋友参考一下 其实关于验证码识别涉及很多方面的内容,入手难度大,但是入手后,可拓展性又非常广泛,可玩性极强,成就感也很足,对这感兴趣的朋友们下面跟着小编一起来学习学习吧。 依赖 利用google ocr来识别验证码 但是pytesseract本身识别率不高,而且一般网站的验证码都带有大

  • 本文向大家介绍Python识别验证码的实现示例,包括了Python识别验证码的实现示例的使用技巧和注意事项,需要的朋友参考一下 废话不多说,直接开干! 首先安装库 然后按照tesseract程序下载安装 tessercat下载地址:https://digi.bib.uni-mannheim.de/tesseract/ //请依据自己的操作系统下载exe文件安装 用户变量,系统变量都添加:PATH

  • 本文向大家介绍c#实现识别图片上的验证码数字,包括了c#实现识别图片上的验证码数字的使用技巧和注意事项,需要的朋友参考一下 C#识别验证码图片通用类 以上2则都是使用C#实现的orc识别的代码,希望对大家学习C#有所帮助。

  • 本文向大家介绍Python验证码识别处理实例,包括了Python验证码识别处理实例的使用技巧和注意事项,需要的朋友参考一下 一、准备工作与代码实例 (1)安装PIL:下载后是一个exe,直接双击安装,它会自动安装到C:\Python27\Lib\site-packages中去, (2)pytesser:下载解压后直接放C:\Python27\Lib\site-packages(根据你安装的Pyth

  • 本文向大家介绍python opencv pytesseract 验证码识别的实现,包括了python opencv pytesseract 验证码识别的实现的使用技巧和注意事项,需要的朋友参考一下 一、环境配置 需要 pillow 和 pytesseract 这两个库,pip install 安装就好了。 安装好Tesseract-OCR.exe pytesseract 库的配置:搜索找到pyt

  • 本文向大家介绍Perl使用Tesseract-OCR实现验证码识别教程,包括了Perl使用Tesseract-OCR实现验证码识别教程的使用技巧和注意事项,需要的朋友参考一下 一、Tesseract-OCR 是什么 An OCR Engine that was developed at HP Labs between 1985 and 1995… and now at Google 基于Lepto