赞
踩
1、需求分析
1.1 需求背景
随着人工智能技术的发展, 信息技术行业与软件行业对人工智能的需求也越来越大, 而 对于爬虫或者数据挖掘软件来说,最头疼的莫过于程序卡在验证码上,这样既无法爬取到数 据,也很容易降低效率。因此验证码识别对于数据分析师或者爬虫程序员来说是非常需要的。 同时,通俗来说,验证码识别不仅仅只可以识别验证码。由于验证码噪点多,干扰线粗长, 字符形状不固定, 其识别难度是非常大的, 而一旦能识别验证码, 大部分可读性字符,例如 交通摄像头拍摄车牌识别, 文章书籍识别, 场景标题监测, 工厂流水线货物产品检测等等都 可以实现。
并且人工智能技术融入当代互联网技术、自动化电子技术, 信息技术这些已经是大势所 趋, 难以逆反,将其接受, 容纳,转化为生产技术的一部分是至关重要的。验证码分析识别 同样如此, 在自动获取网络数据, 分析信息数据等等过程中, 都需要绕过验证码进行大量识 别,因此验证码识别是生产过程中虽然毫不起眼当时也非常重要的一环。
1.2 功能性需求
1.2.1 验证码生成性功能与标准验证码库
鉴于目前并没有找到官方统一的验证码标准库, 并且经过大量调查, 不少网站验证码生 成都基于 Captcha 库, 因此将 Captcha 验证码生成算法(即第三方库)作为理论与实践的数 据标准。由于在制作时考虑到日后神经网络训练所需配置高低的问题, 所以验证码生成的数 据只由数字组成,这能降低开发和训练所带来的高昂成本。
验证码生成不仅需要带有噪点、干扰线、以及形状变化等特点,同时在同一张图片中还 需要具备不同的颜色, 以保证其真实性和难度, 做到能人眼识别的同时也能让机器识别其字 符码,并且尽可能具有标准化和通用化。
1.2.2 图像处理
图像处理应当具有可展示性,并且能够具备不同的处理进度和算法展示,包括灰度化、 模糊化、二值化等算法处理, 在处理识别的过程中应当展示出来, 以便供提供处理进展数据 和方便人员进行分析, 图像处理还应当在之后的识别同时在图形界面中逐张展示, 提供即时 性的处理和让人员进行分析。
1.2.3 神经网络训练和识别
神经网络应当符合现阶段的技术发展,在图像识别上应当使用有比较优良技术价值的算 法, 例如 CNN 内部的卷积层、池化层等, 并在确保验证码数据足够庞大的同时能够让神经
网络具有长时间不间断的训练, 以便能确保能达到良好的准确率。而神经网络的识别应体现 在模型的识别上, 具体为神经网络在训练后输出带有接口的模型, 并且模型能够在后期进行 函数调用。
1.2.4 图形界面—交互特性需求
图形界面是用户与程序交互的主要方式, 这能有效降低用户操作程序的成本。并且能直 观展现程序处理结果和过程。图形界面因具有打开数据, 输入数据,处理数据, 展现数据等 核心功能以及一些别的辅助性功能。在用户输入图片,并开始测试之后, 图形界面应当调用 并显示处理过程中的图片和处理结果, 如果作为网络接口, 可以在不要求图形界面显示处理 结果的同时要通过通信端返回结果。
1.3 非功能性需求
1.3.1 输出监控日志以及处理时间计算
程序处理以及模型识别过程中, 可能需要逐模块分析其运作形式, 因此需要具备监控日 志的功能, 在需要完成识别和测试的时候, 通过查看日志可以了解程序运行的行为, 运行方 式,以及判断可能出现的错误等。
需要展示程序运行时间, 以便能判断神经网络训练出来模型的优良好坏, 模型的好坏不 仅取决于其准确率,还取决于运行的效率,程序也同样如此。程序/模型处理时间应该展现 在图形界面上, 方便进行分析。作为程序,运行时间应当具备: 响应时间快,能及时反馈结 果和过程
1.3.2 通讯传输数据
通讯传输数据可以作为测试性需求进行开发,将程序应用到实际场合中需要程序将识别 出来的结果进行 C/S 或者 B/S 传输。这样可以进行远程自主识别和结果返回。
1.4 设计定位
鉴于开发平台为微软windows10 系统,因此运行平台也必须为windows10 后者windows7 系列平台,以便能展现最佳效果。 程序编程语言为 python,并指定为主要编程语言,能在 python==3.7 的环境中运行,由于开发 IDE 为 PyCharm,因此推荐运行环境也为 PyCharm, 并导入附录中的第三方库,即可有效运行。
运行功能定位为验证码自动识别,包括手动识别, 挂载在服务器上识别以及作为测试功 能的自动抓取识别和传输结果。
该程序平台主要通过极限编程的模式进行开发,主体或者说唯一编程语言为 python,主 要编程平台框架为 Anaconda,人工智能训练框架为 Tensorflow2.1 版本,并采用 CNN 卷积 神经网络算法进行搭建。
2、概要设计
程序主要采用结构化设计, 通过仅有的参数传递尽可能降低每个模块之间的耦合, 并尽 可能将功能划分成模块以提高模块内聚性,各个模块以及其中的关系如图 2- 1 所示:
图 2-1 模块结构图
图像处理模块针对验证码图像进行各种处理,包括灰度化、模糊化、二值化, 梯度化等, 神经网络识别模块针对处理后的图像进行识别。图像文件管理模块针对用户打开验证码, 和 随机挑选验证码进行管理和调用,通讯传输模块是针对识别结果进行本地传送通讯的测试模 块。
打开图形界面后, 用户可以打开验证码图像导入到程序中, 开始测试之后, 用户通过打 开主函数直接调用 GUI 图形界面,而图形界面本身也有三个模块组成, 各自通过函数调用 组成 GUI 。进入 GUI 后可以在菜单栏打开图片、打开随机图片、进行测试、查询帮助和版 本。然后再进行测试中,再主函数内部进行各个模块的调用,依次为处理图像, 图像识别, 生成结果, 计算准确率以及计算运行时间。并且可以在生成结果之后查看监控日志, 分析程 序处理过程,模块关系功能如图 2-2 所示。
图 2-2 系统软件结构
3、详细设计
3.1 主要功能设计
3.1.1 验证码生成
验证码生成模块主要是生成验证码数据的, 既是作为神经网络训练的标准数据源, 也是 测试神经网络模型的数据集。验证码的生成方式采用 Python 官方提供的 Captcha 验证码库, 并在此基础上,调用其内部算法进行生成。 具体编程流程如图 3- 1 所示:
图 3-1 编程流程
在生成随机字符列表中,主要采用调用第三方随机库函数实现, 在已经定义好的函数内 调用随机库,让其在之前已经定义好的设定的验证码字符数据中进行随机选择, 生成 4 位字 符并以列表方式展现, 而到了生成随机验证码函数的时候, 函数就将列表转换成字符串,再 将字符串传入验证码生成库进行图片化处理。主要两个函数的部分代码(包含可理解的逻辑 注释) 如图 3-2、图 3-3 所示:
图 3-2 获取随机字符并导入到列表
图 3-3 生成字符对应的验证码
3.1.2 图像处理
图像处理等同于数据预处理, 是深度学习最重要的步骤之一,神经网络训练的成本、效 率、结果很大程度上取决于前期数据预处理的效果。如果数据处理得好, 就能有效去除大部 分图像噪点和干扰线, 从而让图片的特征更好的体现出来, 因而能非常有效降低神经网络的 训练成本, 减少出错率, 提高效率。 图像处理流程如图 3-4 所示:
图 3-4 图像处理流程
图像处理包含几大处理算法:灰度化、模糊化、二值化、梯度化、计算轮廓、形态学处 理的的膨胀化、计算列像素数量等。这几项算法根据滤波理论(均值、中值、各项异性、高 斯) 等依次进行排序处理, 而在进行前期滤波灰度、高斯模糊之后, 进行二值化的时候就能 有效解决大部分噪点的问题, 这非常能有效提取出验证码的特征。但为了保险起见, 在二值 化之后还是有可能存在非常大的、无用的噪点, 这时候就进行膨胀,将图像特征细瘦化, 这 也能有效将其他大部分噪点给膨胀去掉。而上述几种,基本都是以滤波计算为基础, 通过查
阅几十种 OpenCV 库内部的算法之后,确定下来效果比较显著的算法模型。 部分重要代码 以及模型调用算法如下图所示。
读取原图图像代码如图 3-5 到所示
如图 3-5 读取原图像图
灰度与模糊处理代码如图 3- 1-6 所示
图 3-6 灰度化以及模糊化
模糊图像二值化代码如图 3- 1-7 所示
图 3-7 图像二值化
膨胀华代码如图 3- 1-8 所示
图 3-8 图像形态学膨胀
对于定位图像分割位置, 以及切割图象, 由于代码过长, 只截取部分重要代码以及分割 后的结果图像。
判断图像分割位置: 主体思想为以 X 轴(横轴)为基准先从轴最左边开始遍历垂直分 割后图像的每一列的像素, 如果该列有 0 个黑像素点,这判断该列为像素分割终点, 然后计 算从最左端的 0 点开始到结束分割点中间的像素总和,判断总和与噪点阈值的大小, 如果小 于阈值,则判断为噪点或空值,如果大于阈值, 则判断为字符。
在判断位置之后, 需要转换像素分割的左右点, 届时,就把前一个像素分割终点作为新 的像素起始点,而程序也将继续遍历下一行的像素,一共会返回 8 个像素分割点位置。
垂直投影像素代码如图 3-9 所示。
图 3-9 垂直投影像素
记录每列像素量以及位置如图 3- 10 所示
如图 3-10 记录每列像素量以及位置
分割图像: 主要是想就是将 8 个分割点转换双值列表,每个列表有两个值, 分别对应每
个区块的分割起始点和分割终点。然后进行循环分割。
裁剪图像代码如图 3- 11 所示
图 3-11 裁剪图像
但是毕竟会极有可能存在像素值大于阈值的噪点, 或者字符连在一起,甚至重叠在一起 的情况,这样的话会很容易出现切割错误。这也就是垂直投影以及切割图像、 KNN 近邻算 法会被放弃而转换成神经网络识别的原因。
而以上这些图像等,将会在测试报告章节那里做详细阐释以及会放出实际图像的切割情 况。
在整体图像成功分割成单个字符图像后, 后期还有一系列配套模块进行处理,包括扩充 图像背景, 统一图像尺寸, 进一步二值化等。所示代码将刚分割出来的条状矩形图像填充白 色背景并转换成正方形图像,如图 3- 12 所示,并进行保存。所示代码将图像重新统一尺寸 为 28 像素*28 像素如图 3- 13 所示。
图 3-12 填充并修改尺寸
图 3-13 重新修改尺寸
3.1.3 神经网络训练以及识别
神经网络模型为程序的最核心部分, 该部分的最主要功能是识别判断验证码字符, 并输 出结果, 作为当前比较新的技术, 程序采用 tensorflow2.0 版本内部的继承模型, 并参照官方 模板进行修改和测试。由于是图像识别, 因此将着重采用卷积神经网络进行模型搭建, 并且 将进行多种激励函数的测试。
在进行神经网络训练的时候,程序将数据进行批次化传送训练,按照每批(batch)128 张,每个轮回(epoch)训练 4 批, 一次(time)为 4 个轮回。并且在内部进行原生的验证 码生成而不是传入之前生成的验证码,即每次训练都会拥有不同的验证码, 验证码重复率比 较低。以下为神经网络搭建以及训练的核心代码部分,包含注释。
(1)封装与修改批次
将验证码进行批次化封装,并返回文本标签与修改后的图像。每张图像都要使用 NumPy 进行数值矩阵化,然后进行修改尺寸和图像处理,并传出封装好的图像和标签,如图 3- 14 所示。
3-14 封装与修改批次
(2)构建神经网络模型
首先要初始化一个继承于官方内部模型的类,并在最开始的时候进行卷积化、线性矫正、 池化等操作。这个卷积神经网络模型由卷积核来提取特征,通过池化层对显著特征进行提取, 经过多次的堆叠, 得到比较高级的特征, 最后可以用分类器来分类。这是 CNN 模型的一个 大概流程, 其具体实现的结构是丰富多样的,但总的思想是统一的。
第一个卷积层,可能只是从原始图像像素中学习到一些边缘特征, 但是到了第二个卷积 层可以从这些边缘特征中探测到简单的形状特征, 然后接下来的卷积层, 就可以用这些简单
的形状特征探测到更高级的特征。以下为该作品模型内卷积层提取特征的过程, 将三通道图 像经过 3*3 的滤波器从而提取出新的特征层,如图 3- 15 所示。
3-15 卷积层工作原理
之所以要在每个卷积层后面加入池化层, 是因为池化层可以提取显著特征的同时降低模 型的参数, 从而降低模型的过拟合。因为只是提取了显著特征, 而舍弃了不显著的信息, 是 的模型的参数减少了, 从而一定程度上可以缓解过拟合的产生。在每层卷积层后面加入池化 层这也就能尽可能防止卷积层过多而造成的过拟合问题。 比如下面的 MaxPooling,采用了 一个 2×2 的窗口, 并取 stride=2 ,如图 3- 16 所示。
3-16 池化层工作原理
池化层还具有局部不变性。所谓局部不变性, 比如图像, 就是图像经过简单的平移、旋 转、尺度放缩,池化层在相同的位置依旧可以提取到相同的特征。包括平移不变性, 旋转不 变性, 尺度不变性。这对类似验证码的字符旋转, 形状变化等有很大的纠正性, 能有效在每 一层中提取出更正确的特征。但是局部不变性只能保证小幅度的变换,如果变换幅度较大,
池化层并不能保证这种局部不变性。 图 3- 17 为模型的神经网络的核心代码。
图 3-17 神经网络核心代码
由于验证码图像的像素只有 160*60,本身是比较小的图像和数量级比较低的像素,因 此, 刚开始的卷积核不能太大,根据官方推荐的阶级,采用 32 做开始的卷积核,并且在后 面几层不断增大卷积层数量, 以方便提取特征。并且对于卷积神经网络而言, 卷积核越小越 有利于提取出特征, “ 小而深”是卷积神经网络有效发挥的特点。
在经过数次卷积和池化之后, 我们 最后会先将多维的数据进行“扁平化”,也就是把 (图 像高,图像宽,图像像素通道)的数据压缩成长度为 height ×width ×channel 的一维数组, 这有利于与全连接层进行对接, 降低后面神经网络的训练成本。而整体模型结构图也如下图 3- 18 神经网络结构图所示。
3-18 神经网络结构
在数据进入全连接层之后, 需要对其进行传统的激活函数处理, 以保证权重和偏值的正 确。 该作品模型的激活函数采用 softmax 进行处理。该函数又称归一化指数函数。它是二分 类函数 sigmoid 在多分类上的推广, 目的是将多分类的结果以概率的形式展现出来。该类函 数主要作用就是通过概率化将数据分类, 即主要用于多分类问题, 并且该函数在卷积神经网 络中经常使用。
模型经过扁平化, 标准神经网络全连接层之后, 就能获得结果输出, 模型的搭建等也基 本结束。
(3)模型训练
在神经网络模型完成搭建之后, 就可以开始着重进行模型训练, 而模型的训练需要调用 之前已经搭建好的神经网络模型以及数据封装模块,在训练过程中,则需要根据训练次数来 保存模型, 以方便在后期调用最新的训练模型,如图 3- 19 模型训练所示。
3-19 模型训练
通过使用 model.compile 函数定义编译的优化器、损失函数以及数据列表等, 而 numpy.argmax()函数则作为索引函数找到最有可能的值, 而内部的变量则为模型的预测函数。 训练次数设定为 50 万次,本来预想进行为期差不多一个月的模型训练, 但是其实在连续训 练到第 2 天左右, 平均准确率已经基本达到 75%以上,因此使用该模型做识别已经足够。
每次在进行一次完整的模型训练后都会进行保存, 下一轮训练的时候就调用上一次模型继续 进行。
3.1.4 图形界面设计
图形界面是用户与程序交互的关键链接, 作为图像识别平台, 用户需要借助图形界面进 行分析图像像素和图像。 该程序通过调用 Tkinter 库模块进行搭建, 以下为最初打开后以及 经过处理的的识别的平台。
在启动程序里面, 主要通过是先生成显示的图形界面,然后用户再通过调用各个模块进 行程序交互,并且在图形界面里面,还具有各种不同的显示信息如图 3-20 所示。
平台分有菜单栏、原始图像显示区、图像处理过程显示区、数据处理时间区以及结果显 示区,在菜单栏部分,设计了与一般软件一样的文件打开栏,可以打开选定的验证码图片, 在测试区, 具备和界面下方按钮一样的功能: “开始识别” 、“输出日志” 、“ 随机验证码” 。如 果想查看版本或者帮助还可以在帮助界面进行查询,而接口部分可以进行测试功能, 包括目 前开发的 socket 通讯传输。
3.2 辅助功能设计
3.2.1 程序时间计算
计算程序运行时间是用于分析程序响应速度以及模型优化程度的功能,在前中期的模型 搭建的优劣和模块耦合关系的复杂度等问题具有客观指导作用。设定起始时间和截止时间, 并嵌入进总体运行过程和核心模型运行过程, 并将四个参数传入时间计算函数, 计算各自的 差值, 并输出到 GUI 图形界面(可在 GUI 图形界面的数据处理时间区域中看到输出结果)。 时间计算大体流程架构如图 3-21 所示:
图 3-21 时间计算架构
3.2.2 传输测试
该程序中目前采用 socket 库进行通讯传输,目前也仅通过本地端口进行端口双程序传 输。 由于是单线程编程,发送端与接收端不能同时进行, 因此, 很多情况下在成功进行结果 传输之后发送端进程会处于挂起(睡眠) 状态, 出现“未响应” 的情况, 而解决办法就是关闭 接收端窗口, 这样发送端就能重新被唤醒并继续执行新的图像识别任务。图传送端与接收端 为传送结果如图 3-22 所示。
图 3-22 传送段与接收端示例图
传输过程中需要保持端口不被其他程序占用(程序代码固定端口为 27060),在进行测 试的时候, 先运行 socket_server.py 文件, 这是模拟接收端的部分,在没有接收到结果的时 候是没有任何反应的,同时在验证码识别的发送端, 执行完图像识别显示结果后, 在菜单栏 上的“接口中” 点击“测试 3”就会开始进行传输通讯, 然后接收端就会弹出界面,显示接收的 结果。具体架构流程图 3-23 所示:
图 3-23 传输流程示意图
3.2.3 监控日志
监控日志可以作为分析程序运行的过程, 并且可以判断程序出错的位置和可能出现错误 的原因。查看监控日志可以在 GUI 图形界面中点击“输出日志”按钮,以消息框的方式查看, 或者在程序目录中直接打开“log.txt”以 txt 形式查看。监控日志示例图为查看监控日志的示例 以及界面如图 3-24 所示。
图 3-24 监控日志示例图
4、测试报告
4.1 各项图像处理测试
测试所显示的图片采用 matplotlib 模块显示,matplotlib 模块与 OpenCV 模块不同,它所 计算的灰白、模糊等一系列图像均不以灰、黑、白的形式展示, 而是以黄、紫色调为主的色 调代替。在以下的图片测试结果中,左图依次展示原图像、灰度化、模糊化、二值化、形态 学膨胀化、梯度轮廓、垂直像素、腐蚀化, 右图显示垂直投影后的调用自己写的图像切割函 数所切割出的图像, 如下图所示。
…
…
…
5、安装及使用
5.1 开发环境安装
(1)安装 Anaconda(下载地址:https://www.anaconda.com/products/individual)。 (2)在 Anaconda 内部创建以 python3.7 为基础的新环境,如图 5-0 安装 Anaconda。
5-0 安装 Anaconda
(3)在 anaconda 建立的新环境中安装以下第三方库:Tensorflow2.0 以及以上、pillow、 matplotlib 、captcha 、numpy 、glob 等。
OpenCV 安装包已在目录里面,具体安装详情:
https://blog.csdn.net/iracer/article/details/80498732。
注意关键点:
使用 ctrl+r 打开 cmd 命令行窗口,使用 cd 命令进入上一步下载好 opencv_xxx.whl 文件所在 目录
输入如下代码安装该文件:
…
…
…
5.2 程序安装以及使用
5.2.1 代码模式
安装完上述开发环境之后, 在保持文件目录、文件名等不变的情况下, 进入 IDE 内通 过代码可以行 app_main.py,即可编译生成程序。
5.2.2 已编译模式
直接运行目录下的 app_main.exe 可执行文件, 直接进行使用,不过由于 python 本身的 局限性,完全由 python 编译出来的单线程程序启动的速度非常慢。正常情况下双击后会显 示没有任何输出的控制台窗口,并且需要等待三分钟左右的时间才正式启动完毕,GUI 图形 界面窗口才能显示出来。控制台窗口同时也是监控日子的输出窗口,可以实时查看程序的处 理输出。 不过需要注意,路径尽量不要有中文!!不然可能会出错!
如果要进行通讯传输的测试,需要先运行“socket_server”文件,无论是代码模式下还是 已编译模式下,若为代码模式下,需要先运行“socket_server.py”待其静默运行后,再进行 “app_main.py”的运行,进行识别后再从接口菜单中点击“测试 3”触发 socket 传输。
如果是再已编译模式下,则先在同目录内运行“socket_server.exe”文件,待其弹出控制台, 如果有有询问是否允许联网,请点击允许公网和私网下两项允许。届时则表示静默运行完毕, 然后就可以打开“app_main.exe”执行文件,等待数分钟后弹出 GUI 界面, 然后进行验证码 识别,进行识别后再从接口菜单中点击“测试 3”触发 socket 传输。
需要注意的是, 前面说过, 由于没有调用多线程, 因此这两个程序是同时占用同一个进 程, 当接收端顺利接收结果, 并展示的时候, 识别平台作为发送端是处于“未响应”状态, 这 时候只需要关闭接收端的图形界面,识别平台就能被重新唤醒,能继续进行工作。图 5-2、 图 5-3 分别为可执行程序运行图
图 5-2
…
…
…
6、项目总结
6.1 面对的困难
刚开始是决定运用 KNN(K 近邻)算法实想验证码识别,后来实在在像素垂直投影以 及分割上遇到很大的困难, 才决定转型去深度学习神经网络做训练模型, 尽管神经网络在制 作上比 KNN 容易得太多,而且在识别上准确率也比 KNN 精确得多。 只是当时想尝试传统 的机器学习算法去进行验证码识别
6.2 水平提升
在进行神经网络模型搭建的时候,起初觉得将前面的卷积层和池化层做得越多越好, 但 是在后期的训练发现, 过多的卷积层和池化层并不会对训练准确度有很大的提升, 反而极大 降低了模型训练的效率, 消耗很多服务器系统资源。经过多次协调权衡之后才决定制作 3~5 层的卷积层和池化层作为特征提取。
6.3 升级演进
其实在制作该程序时, 就已经考虑其升级版本, 奈何时间不充足, 来不及做,而升级版 本就是通过完善的网络 socket 技术,将该验证码程序挂靠在服务器端, 并执行自动获取验 证码数据, 自动识别, 自动返回结果到本地或爬虫等程序上, 并且作为验证码识别本身就拥 有比较高的准确率, 所以可以将模型和程序识别对象进行转化, 例如车辆牌照识别、文字识 别、甚至是人脸识别等。
完整方案及源码地址:https://download.csdn.net/download/lijunhcn/88763004
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。