验证码识别实践1:自己动手C#实现

本文乃Siliphen原创,转载请注明出处:

我的验证码识别实践一共有3篇文章。

下一篇(验证码识别实践2):

把最近学的一些知识总结了下。

然后,写了这个么一个小程序。

这个小程序的作用是,识别出简单的验证码。

程序运行截图如下:

语言C#。

用C++写的话,调用OpenCV库,做这个就没有什么难度了

所以用C#,自己手写算法的实现,锻炼一下。呵呵。

本程序的下载地址:

本程序对于如下几种验证码的识别率达到:100%

呵呵。不信?你下载下来试试看。。

网址1,https://www.ed3688.com/sb2/me/generate_validation_code.jsp

截图:

网址2:?634900445434772000

截图:

网址3:?

截图:

(注意,要识别这个验证码的话,需要在程序界面上选择:“定点1”,否者不能识别)

考虑到做这种程序需要做大量的实验和测试

为了方便性我在程序上做了图片下载功能,

可以直接把验证码下载下来识别。

当然,这个是C#的优点了。

要是用C++不借助第三方库,

直接Socket Http请求下载图片,可要麻烦死。

本程序对于下面这个验证码,也有一定的识别率。但很低

网址4:?SR=d590fc460740e24e7af4

截图:

其原因,我在如下解说。

总结:

验证码的识别。最主要有2大步骤。

1.字符的分割

2.字符的分类

字符的分割,其实是一个广义概念。

我最初以为把字符所在的那个子图给“抠”出来,就算是分割了。

其实不然,,分割有:阈值分割,自适应阈值分割,提取连通分量,查找轮廓等

这些操作都最终都围绕着把字符的“形状”信息给提取出来的目的

阈值分割是让图像的信息减少,从而使后续操作简单。

(只处理二值图像当然简单了)

有些分割,会直接用到彩色图像。比如:字符具有某种颜色,

那么,就提取这种颜色的位置连通分量。

字符分类的话。就是把字符信息作为某种算法(或者称为分类器)的输入

然后,返回出这个形状属于那种分类(字符)

我做的这个识别程序,主要流程如下:

1.图像预处理。

2.字符分割

3.对分割后的信息提取特征

4.用特征和样本进行匹配

1.图像预处理。

我的图像预处理,就是二值化图像。

然后,统计一下,白色和黑色的比例。决定是否反转图像的颜色。

为什么要反转图像颜色呢。因为,有些验证码的字符的颜色是浅色背景是深色,

而有些是字符深色背景浅色。为了使后续的操作简单。

把它们都统一处理成字符黑色背景白色。

我的处理是,对于整个图像,如果黑色比例比白色多

那么,就认为黑色是背景。对整个图像进行颜色反转。

2.字符分割

字符的分割,我用的是提取连通分量的做法。

连通分量(Connected Component)是图论上的说法,

好像到了图像处理的书,一般都叫连通区域(Connected Region)

(这2个说法都是等价的吧?呵呵,我不知道,期待你来回答我)

提取连通分量的实现一般都是 DFS(深度优先搜索)算法啦。

我写的算法用的是8邻域连通,

把纯黑色的像素都提取出来。

(实际上有一个回调函数,可以在算法外部决定提取什么颜色)

返回的是这些像素的点的坐标。

(有坐标就足够了,已经能够表达形状了,这一步后,根本不需要字符的颜色信息)

数据结构如下:List<Point> Region ;

如上图,

界面左边的图像是原图。

先对左边的原图像进行二值化处理。

然后,提取连通分量。

界面右边的图像,用于调试。

我把提取到的每个独立的连通分量都染成了红色。

并且,遍历了那些连通分量上的点,计算出最小包围矩形。

矩形用蓝色显示。

提取连通分量有一个好处,就是不管字符在图像的什么位置

都可以“抓”到它。当然,这个是需要有颜色信息分明的前提的。

3.对分割后的信息提取特征

提取到连通分量后,就可以计算特征了。

特征计算目的就是把高维度的表示降成低维度的表示。

我的理解,就是说,“去掉很多细节表示,只留下个大概模糊的轮廓描述”

特征提取,方法很多。比如:矩(Moment)

因为我水平有限。!- –

So,这里使用的是一种简单的“N*M比例特征法“

就是把连通分量按照每个点的几何位置信息先套上一个最小包围矩形

然后,把这个矩形分割为N行M列的小格子。

再然后,把连通分量的点按照位置信息归类进对应的小格子中。

最后,计算小格子中的点的数量与小格子的面积的比值。

每个小格子最后对应一个标量。

我是5*5切分,所以,最后25个标量,

组成一个25维的向量作为一个连通分量的特征。

4.用特征和样本进行匹配

最后一步,分类。也就是识别。

分类器搞到很复杂的有什么:支持向量机,人工神经网络 等

同样是水平有限,这里,我实现了最简单的分类:最近邻法

最近邻法就是说,把要匹配的特征和样本库中的所有样本特征进行计算

取欧氏距离最短的那个样本的类别作为输出

最后说下,

为什么会对网址4的验证码识别率很低呢

最主要的原因出在分割这个环节上。如下图:

如果能正确分割出字符,获取其形状描述(点集合)

那么,就可以达到100%识别。

我实现的只是简单的阈值化。没有用自适应阈值。

所以,阈值后,不一定会”凸显“字符的轮廓。

其实,这个码可能用自适应阈值也不好处理,

因为,字符灰度值有可能比局部计算出来的阈值灰度值低或高

所以,到底定义比自适应阈值的阈值是高还是低呢?

如果舍得花费功夫的话,用一些统计学的方法

应该可以大幅度提高识别率,我个人认为。。。

不做任何解释。没有人明白,

验证码识别实践1:自己动手C#实现

相关文章:

你感兴趣的文章:

标签云: