Aforge.net之旅——开篇:从识别验证码开始

使用C#进行验证码识别 C#是一种强大的编程语言,具有广泛的图像处理库和丰富的生态系统。使用C#进行验证码识别是完全可行的,特别是在需要与.NET生态系统集成的项目中。虽然Python仍然是一个流行的选择,但根据项目需求,选择C#作为开发语言可能是一个更好的选择。一旦您有了验证码图像,接下来的任务是进行图像处理。使用AForge.NET Framework或其他图像处理库可以帮助您处理图像,提取出验证码的文本。在进行验证码识别之前,您需要获取验证码图像。现在您已经从图像中提取了文本,可以将其用于验证码识别。// 打开验证码图像。 阅读详情

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

资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域,这个系列研究的重点就是瞎几把搞下AForge.Imaging这个命名空间下面的东东,下载网址:http://www.aforgenet.com/framework/downloads.html

在这里插入图片描述
上去看了后,哟呵~ 还有个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%吧。

C#图片验证码识别技术实现指南 验证码的原理与分类部分详细介绍了验证码的基本工作原理以及它们的主要类型和特点。每种验证码类型都有其优缺点,而选择哪一种通常取决于应用的具体需求和用户体验的考虑。在后续章节中,我们将探讨如何使用C#技术来实现验证码的识别和处理,以及如何利用高级工具和技术来克服验证码识别中遇到的挑战。预处理是验证码识别流程的第一步,目的在于改善图像质量,以便后续步骤能够更准确地处理图像数据。常见的预处理步骤包括图像二值化、去噪、旋转校正等。// 示例代码:图像二值化处理// 创建一个彩色的位图的副本。 阅读详情

相关推荐

C#编程:HTTP模拟、验证码识别与QQ协议解析

HTTP是一种无状态的协议,最初设计用于从服务器传输超文本到本地浏览器。它使用TCP/IP协议作为传输层,并运行在默认的端口80。HTTP使用请求/响应模型,客户端发送请求并接收来自服务器的响应。每次请求都包含一个HTTP方法(如GET、POST、PUT等),一个或多个HTTP头部,可能还有一个实体正文,例如用户上传的数据。HTTP(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。

weixin_35749796的博客 1496

C#用Aforge.net类库调用摄像头实现监控或者拍照功能

在项目里有个功能需要调取监视器实现摄像功能,在网上找到了一些Demo虽然也没看太懂,但是基本功能还是做到了,在此做个笔记。 本文源码下载地址:https://download.csdn.net/download/qq_42757964/12259466 AForge引用类包下载地址:https://download.csdn.net/download/qq_42757964/12255300 简单...

帅boy的博客 5060

C#实战:车牌识别与验证码识别的图像处理全流程

图像识别技术是现代计算机视觉的核心领域,广泛应用于工业自动化、智能交通与安全验证场景。从基本原理看,任何字符类识别任务都遵循“图像采集→目标定位→预处理→字符分割→分类识别”的通用管线,车牌识别与验证码识别正是这一管线的典型代表。在C#工程实践中,开发者常借助Emgu CV、AForge.NET等库实现摄像头取帧与图像处理,通过形态学或YOLO模型完成目标定位,再结合投影分割或连通域分析切分字符,最终利用ML.NET或ONNX Runtime部署识别模型。这类技术不仅能够快速集成到上位机系统中,还能有效解决

weixin_29057695的博客 324

AForge.NET介绍

丰富的文档和示例:虽然不是每个方法都有详细的文档,但主要的模块都有足够的信息供开发者参考,并且提供了Image Processing Prototyper和AForge.NET Debugging Visualizers等开发工具。总的来说,AForge.NET是一个功能全面、易于使用和扩展的开源计算机视觉和机器学习库,适用于各种涉及图像处理、计算机视觉、人工智能等领域的开发任务。提供了一些机器人的工具类库,帮助开发者进行机器人控制和编程。提供了用于遗传计算的接口和类,支持优化、近似等问题的解决。

星河队长 609

Aforge .net类库、文档、示例

最新版Aforge .net2.2.5 全套类库、文档、示例,工具等

AForge.NET Framework所必须的dll文件

AForge.NET Framework-2.2.5

用 aforge.net 小试一下验证码识别

今天来小玩一下aforge.net套用官方的话就是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的资源,还有很多应用程序例子,包括计算机视觉与人工智能...

dotNET跨平台 781

Aforge.net库源代码

C#开源库Aforg最新源代码,有助于使用此库的人学习和修改库。

使用AForge.NET框架和Tesseract识别验证码

using AForge.Imaging.Filters; using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using Tesseract; namespace RecogCaptcha { public partial class Form1 : Form { public Form1() { I

极客神殿 823

基于net.sourceforge.tess4j库的OCR验证码识别Java设计源码

本项目是一个基于net.sourceforge.tess4j库的Java OCR验证码识别系统,包含20个文件,包括9个Java源文件、2个GIF图片文件、2个traineddata文件、1个Markdown文件、1个XML文件、1个tessdata配置文件、1个ttf字体文件以及1个ttx文件。该系统利用tess4j库实现验证码的识别功能,适用于需要进行验证码识别的场景。

ubuntu18.04安装R——无法连接上 dl.google.com:80 (6.6.6.6),连接超时&&E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。

安装R的时候,sudo apt update 的时候出现错误: 查资料要修改/etc/apt/sources.list.d/google-chrome.list 文件 原来是: deb http://dl.google.com/linux/chrome/deb/ stable main 改为: deb [arch=amd64] http://dl.google.com/linux/chrom...

许希律的博客 4347

用C#模版匹配识别新教务系统登录验证码

学校教务网的系统终于换了,原来那个100W从清华还是哪里买来的放到现在简直就是本科毕设水平,前端丑爆不说,后端用的Java1.5,登录一点验证都没有,稍有点常识的人都能看出来,如果hack的铁蹄继续前进,这个螳臂当车的歹徒……   不过前几天学校上线了新的教务系统,应该是找公司外包的,现在看起来还不错,没有深入分析,只简单的看了下登录的逻辑。

奇迹工坊 3770

使用Eggjs做服务端获取微信小程序云开发数据库的access_token

最近自己想写了一个微信小程序,恰巧里面有个云开发,恰巧里面有个数据库,那懒人的我,就直接用云开发里面的数据库了,做测试或者正式也好,对于刚开始来说,免费的配额是够用的。 后来想到在小程序云开发上面的数据怎么看才方便?刚好微信小程序有一个服务端API,那就方便很多了,那就直接敲个服务端来获取云开发上数据库的数据出来到自己的后台上面,那以后管理起来也方便很多。 看了一下服务端api之后,发现有三个重要...

kalenE992的博客 1703

C# 识别验证码,识别发票编号

常用临界点阈值确定算法 噪点判断及去除 二值化 图片分割 图片分割的主要算法 边缘检测分割算法 字模制作 验证码识别 字模库维护 图片处理类的设计

月亮哥的专栏 337

VHDL按键消抖(状态机版本)

检测下降沿:设置一个和,分别代表之前的之前和之前的信号状态,若两个信号key_in_d2=1,key_in_d1=0,他俩的not key_in_d2 and key_in_d1为1,则说明下降沿产生,把它设置为标志位key_flag。延时计数:50MHz的板子每次计数需要20ns,而抖动时间大约为5-10ms。所以取7ms,作为延时时间。可以看见当检测到下降沿时,开始计数计数计满再次检测,若为低电平则为按下按键,否则为抖动。通过检测下降沿来临,延时计数再次检测,如果为低电平则为按键按下。

qq_69639216的博客 1083

Qlib+backtrader:2014.1.1-2023.9.20最新回测结果,可以实盘吗?

今年以来,在研究了qlib和backtrader的基础上,把二者结合起来进行了一个策略研究。简单说就是用qlib在200只股票的股票池中进行滚动训练与预测(walk forward),总体数据范围是2005到2023年,以20日间隔滚动训练和预测,最终得到2014.1.1-2023.9.20共10年测试期的收益率预测结果。将预测结果代入backtrader进行回测,得到如下回测结果。

qtbgo的博客 1783

Aforge.net识别简易数字验证码问题

参考:https://www.bbsmax.com/A/rV57LjWGdP/ https://blog.csdn.net/louislong007/article/details/47683035 简易验证码样例: 验证码识别流程: 首先进行图像获取:火狐浏览器,找到获取验证码地址,获取验证码图像,传递给类,直接获取到验证码! 验证码获取: /// &l...

weixin_34009794的博客 366

调试GMS应用,报错“此设备未获得play保护机制认证”问题解决

不少同学在调试GMS相关应用时,需登录Google账号,有时会弹出如下通知。Google登录界面也会出现如下提示这个报错的原因是设备未通过Google认证,google服务器未配置荣耀设备的型号白名单导致国内网页有一些指导方法在鸿蒙\荣耀的设备上消除这个提示,但本质的问题没有解决,无法登录Google账号。

胡同老道的博客 2万+

paip 验证码识别---图像处理类库

paip 验证码识别---图像处理类库

sdfhncfw的博客 159

Cesium 相机操作

Cesium 提供了三种方式对相机的位置进行摆放。

虎康的博客 2585

SXU—软件测试方法和技术-朱少民-第四部分 软件测试流程和规范-附考点

软件测试方法和技术-朱少民-第四章 软件测试流程和规范—这本书最后一部分的考点整理,考点分析

weixin_63597914的博客 1752
上一篇: NET GridView中添加CheckBox取值问题
下一篇: AForge.NET实现图中找水印(或图像匹配)并用颜色填充
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值