0%

利用深度学习 PyTorch 识别滑动验证码缺口

在前面写过一篇文章介绍深度学习识别滑动验证码缺口的文章,在这篇文章里,我们使用华为云 ModelArts 轻松完成了滑动验证码缺口的识别。但是那种实现方案依赖于 ModelArts,是华为云提供的深度学习平台所搭建的识别模型,其实其内部是用的深度学习的某种目标检测算法实现的,如果利用平台的话,我们无需去申请 GPU、无需去了解其内部的基本原理究竟是怎么回事,它提供了一系列标注、训练、部署的流程。 但用上述方法是有一定的弊端的,比如使用会一直收费,另外不好调优、不好更好地定制自己的一些需求等等。所以这里再发一篇文章来介绍一下直接使用 Python 的深度学习模型来实现滑动验证码缺口识别的方法。

效果

目前可以做到只需要几百张缺口标注图片即可训练出精度高的识别模型,并且可扩展修改为其他任何样式的缺口识别,识别效果样例: 样例 只需要给模型输入一张带缺口的验证码图片,模型就能输出缺口的轮廓和边界信息。 感兴趣的可以继续向下看具体的实现流程。

基础了解

缺口识别属于目标检测问题,关于什么是目标检测这里就不再赘述了,可以参考之前写的这篇文章。 当前做目标检测的算法主要有两种路子,有一阶段式和两阶段式,英文叫做 One stage 和 Two stage,简述如下:

  • Two Stage:算法首先生成一系列目标所在位置的候选框,然后再对这些框选出来的结果进行样本分类,即先找出来在哪,然后再分出来是啥,俗话说叫「看两眼」,这种算法有 R-CNN、Fast R-CNN、Faster R-CNN 等,这些算法架构相对复杂,但准确率上有优势。
  • One Stage:不需要产生候选框,直接将目标定位和分类的问题转化为回归问题,俗话说叫「看一眼」,这种算法有 YOLO、SSD,这些算法虽然准确率上不及 Two stage,但架构相对简单,检测速度更快。

所以这次我们选用 One Stage 的有代表性的目标检测算法 YOLO 来实现滑动验证码缺口的识别。 YOLO,英文全称叫做 You Only Look Once,取了它们的首字母就构成了算法名, 目前 YOLO 算法最新的版本是 V3 版本,这里算法的具体流程我们就不过多介绍了,感兴趣的可以搜一下相关资料了解下,另外也可以了解下 YOLO V1-V3 版本的不同和改进之处,这里列几个参考链接。

  • YOLO V3 论文:https://pjreddie.com/media/files/papers/YOLOv3.pdf
  • YOLO V3 介绍:https://zhuanlan.zhihu.com/p/34997279
  • YOLO V1-V3 对比介绍:https://www.cnblogs.com/makefile/p/yolov3.html

数据准备

回归我们本节的主题,我们要做的是缺口的位置识别,那么第一步应该做什么呢? 我们的目标是要训练深度学习模型,训练模型,那我们总得需要让模型知道要学点什么东西吧,这次我们做缺口识别,那么我们需要让模型学的就是这个缺口在哪里。由于一张验证码图片只有一个缺口,要分类就是一类,所以我们只需要找到缺口位置就行了。 好,那模型要学缺口在哪里,那我们就得提供点样本数据让模型来学习才行。数据怎样的呢?那数据就得有带缺口的验证码图片以及我们自己标注的缺口位置。只有把这两部分都告诉模型,模型才能去学习。等模型学好了,等我们再给个新的验证码,那就能检测出缺口在哪里了,这就是一个成功的模型。 OK,那我们就开始准备数据和缺口标注结果吧。 数据这里用的是网易盾的验证码,验证码图片可以自行收集,写个脚本批量保存下来就行。标注的工具可以使用 LabelImg,GitHub 链接为:https://github.com/tzutalin/labelImg,利用它我们可以方便地进行检测目标位置的标注和类别的标注,如这里验证码和标注示例如下标注效果 标注完了会生成一系列 xml 文件,你需要解析 xml 文件把位置的坐标和类别等处理一下,转成训练模型需要的数据。 在这里我先把我整理的数据集放出来吧,完整 GitHub 链接为:https://github.com/Python3WebSpider/DeepLearningSlideCaptcha,我标注了 200 多张图片,然后处理了 xml 文件,变成训练 YOLO 模型需要的数据格式,验证码图片和标注结果见 data/captcha 文件夹。 如果要训练自己的数据,数据格式准备见:https://github.com/eriklindernoren/PyTorch-YOLOv3#train-on-custom-dataset

初始化

上一步我已经把标注好的数据处理好了,可以直接拿来训练了。 由于 YOLO 模型相对比较复杂,所以这个项目我就直接基于开源的 PyTorch-YOLOV3 项目来修改了,模型使用的深度学习框架为 PyTorch,具体的 YOLO V3 模型的实现这里不再阐述了。 另外推荐使用 GPU 训练,不然拿 CPU 直接训练速度很慢。我的 GPU 是 P100,几乎十几秒就训练完一轮。 下面就直接把代码克隆下来吧。 由于本项目我把训练好的模型也放上去了,使用了 Git LFS,所以克隆时间较长,克隆命令如下:

1
git clone https://github.com/Python3WebSpider/DeepLearningSlideCaptcha.git

如果想加速克隆,暂时先跳过大文件模型下载,可以执行命令:

1
GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/Python3WebSpider/DeepLearningSlideCaptcha.git

环境安装

代码克隆下载之后,我们还需要下载一些预训练模型。 YOLOV3 的训练要加载预训练模型才能有不错的训练效果,预训练模型下载命令如下:

1
bash prepare.sh

执行这个脚本,就能下载 YOLO V3 模型的一些权重文件,包括 yolov3 和 weights 还有 darknet 的 weights,在训练之前我们需要用这些权重文件初始化 YOLO V3 模型。

注意:Windows 下建议使用 Git Bash 来运行上述命令。

另外还需要安装一些必须的库,如 PyTorch、TensorBoard 等,建议使用 Python 虚拟环境,运行命令如下:

1
pip3 install -r requirements.txt

这些库都安装好了之后,就可以开始训练了。

训练

本项目已经提供了标注好的数据集,在 data/captcha,可以直接使用。 当前数据训练脚本:

1
bash train.sh

实测 P100 训练时长约 15 秒一个 epoch,大约几分钟即可训练出较好效果。 训练差不多了,我们可以使用 TensorBoard 来看看 loss 和 mAP 的变化,运行 TensorBoard:

1
tensorboard --logdir='logs' --port=6006 --host 0.0.0.0

loss_1 变化如下: loss 变化 val_mAP 变化如下: mAP 变化 可以看到 loss 从最初的非常高下降到了很低,准确率也逐渐接近 100%。 另外训练过程中还能看到如下的输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
\---- [Epoch 99/100, Batch 27/29] ----
+------------+--------------+--------------+--------------+
| Metrics | YOLO Layer 0 | YOLO Layer 1 | YOLO Layer 2 |
+------------+--------------+--------------+--------------+
| grid_size | 14 | 28 | 56 |
| loss | 0.028268 | 0.046053 | 0.043745 |
| x | 0.002108 | 0.005267 | 0.008111 |
| y | 0.004561 | 0.002016 | 0.009047 |
| w | 0.001284 | 0.004618 | 0.000207 |
| h | 0.000594 | 0.000528 | 0.000946 |
| conf | 0.019700 | 0.033624 | 0.025432 |
| cls | 0.000022 | 0.000001 | 0.000002 |
| cls_acc | 100.00% | 100.00% | 100.00% |
| recall50 | 1.000000 | 1.000000 | 1.000000 |
| recall75 | 1.000000 | 1.000000 | 1.000000 |
| precision | 1.000000 | 0.800000 | 0.666667 |
| conf_obj | 0.994271 | 0.999249 | 0.997762 |
| conf_noobj | 0.000126 | 0.000158 | 0.000140 |
+------------+--------------+--------------+--------------+
Total loss 0.11806630343198776

这里显示了训练过程中各个指标的变化情况,如 loss、recall、precision、confidence 等,分别代表训练过程的损失(越小越好)、召回率(能识别出的结果占应该识别出结果的比例,越高越好)、精确率(识别出的结果中正确的比率,越高越好)、置信度(模型有把握识别对的概率,越高越好),可以作为参考。

测试

训练完毕之后会在 checkpoints 文件夹生成 pth 文件,可直接使用模型来预测生成标注结果。 如果你没有训练自己的模型的话,这里我已经把训练好的模型放上去了,可以直接使用我训练好的模型来测试。如之前跳过了 Git LFS 文件下载,则可以使用如下命令下载 Git LFS 文件:

1
git lfs pull

此时 checkpoints 文件夹会生成训练好的 pth 文件。 测试脚本:

1
sh detect.sh

该脚本会读取 captcha 下的 test 文件夹所有图片,并将处理后的结果输出到 result 文件夹。 运行结果样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Performing object detection:
+ Batch 0, Inference Time: 0:00:00.044223
+ Batch 1, Inference Time: 0:00:00.028566
+ Batch 2, Inference Time: 0:00:00.029764
+ Batch 3, Inference Time: 0:00:00.032430
+ Batch 4, Inference Time: 0:00:00.033373
+ Batch 5, Inference Time: 0:00:00.027861
+ Batch 6, Inference Time: 0:00:00.031444
+ Batch 7, Inference Time: 0:00:00.032110
+ Batch 8, Inference Time: 0:00:00.029131

Saving images:
(0) Image: 'data/captcha/test/captcha_4497.png'
+ Label: target, Conf: 0.99999
(1) Image: 'data/captcha/test/captcha_4498.png'
+ Label: target, Conf: 0.99999
(2) Image: 'data/captcha/test/captcha_4499.png'
+ Label: target, Conf: 0.99997
(3) Image: 'data/captcha/test/captcha_4500.png'
+ Label: target, Conf: 0.99999
(4) Image: 'data/captcha/test/captcha_4501.png'
+ Label: target, Conf: 0.99997
(5) Image: 'data/captcha/test/captcha_4502.png'
+ Label: target, Conf: 0.99999
(6) Image: 'data/captcha/test/captcha_4503.png'
+ Label: target, Conf: 0.99997
(7) Image: 'data/captcha/test/captcha_4504.png'
+ Label: target, Conf: 0.99998
(8) Image: 'data/captcha/test/captcha_4505.png'
+ Label: target, Conf: 0.99998

拿几个样例结果看下: 这里我们可以看到,利用训练好的模型我们就成功识别出缺口的位置了,另外程序还会打印输出这个边框的中心点和宽高信息。 有了这个边界信息,我们再利用某些手段拖动滑块即可通过验证了。本节不再展开讲解。

总结

本篇文章我们介绍了使用深度学习识别滑动验证码缺口的方法,包括标注、训练、测试等环节都进行了阐述。 GitHub 代码:https://github.com/Python3WebSpider/DeepLearningSlideCaptcha。 欢迎 Star、Folk,如果遇到问题,可以在 GitHub Issue 留言。