本文参考了知乎上的一篇文章,只做了少许改动,感觉挺好玩的,自己实现了一下,准确率比原作者的要高一些。如果想要了解原创文章的话,请移步知乎:使用深度学习来破解captcha验证码

本文通过keras深度学习框架来实现captcha验证码的识别,具体的环境配置如下:

Python:2.7.12

keras:1.2.2

theano:0.9.0rc2

captcha:0.2.4

numpy:1.12.0

matplotlib:1.5.3

所有的代码都已经开源在github上:https://github.com/chyang2015/keras_captcha

captcha是用Python写成的生成验证码的库,它支持图片验证码和语音验证码,本文使用的是图片验证码。与参考文章中的设置一样,我们的验证码的格式为数字加大写字母的组合。

先看一个利用captcha生成验证码的例子:

from captcha.image import ImageCaptcha
import matplotlib.pyplot as plt
import numpy as np
import pylab
import random
import string
characters = string.digits + string.ascii_uppercase
print(characters)
width, height, n_len, n_class = 170, 80, 4, len(characters)
generator = ImageCaptcha(width=width, height=height)
random_str = ''.join([random.choice(characters) for j in range(4)])
img = generator.generate_image(random_str)
plt.imshow(img)
plt.title(random_str)
pylab.show()

数据生成器

训练模型的时候,我们可以选择两种方式来生成我们的训练数据,一种是一次性生成几万张图,然后开始训练,一种是定义一个数据生成器,然后利用 fit_generator 函数来训练。

第一种方式的好处是训练的时候显卡利用率高,如果你需要经常调参,可以一次生成,多次使用;第二种方式的好处是你不需要生成大量数据,训练过程中可以利用 CPU 生成数据,而且还有一个好处是你可以无限生成数据。

X

X 的形状是 (batch_size, 3, height, width),比如一批生成32个样本,图片宽度为170,高度为80,那么形状就是 (32, 3, 80, 170),取第一张图就是 X[0]。

这里要注意的是keras后端在图像格式上的差异:tensorflow和theano的数据格式是不一样的:

tf(tensorflow)模式:(num, channel, height, weight)

th(theano)模式:(num, height, weight, channel)

要根据自己选择的后端的不同选择不同的数据格式,注意图像数据的转化。

y

y 的形状是四个 (batch_size, n_class),如果转换成 numpy 的格式,则是 (n_len, batch_size, n_class),比如一批生成32个样本,验证码的字符有36种,长度是4位,那么它的形状就是4个 (32, 36),也可以说是 (4, 32, 36),解码函数在下个代码块。

# 定义数据生成器,默认一批生成32张图片
def gen(batch_size = 32):X = np.zeros((batch_size,3,height,width),dtype=np.uint8)y = [np.zeros((batch_size,n_class),dtype=np.uint8) for i in range(n_len)]generator = ImageCaptcha(height=height,width=width)while True:for i in range(batch_size):random_str = ''.join([random.choice(characters) for j in range(4)])X[i] = np.array(generator.generate_image(random_str)).transpose((2,0,1))for j, ch in enumerate(random_str):y[j][i,:] = 0y[j][i,characters.find(ch)] = 1yield X,y

上面就是一个可以无限生成数据的例子,我们将使用这个生成器来训练我们的模型。

使用生成器

生成器的使用方法很简单,只需要用 next 函数即可。下面是一个例子,生成32个数据,然后显示第一个数据。当然,在这里我们还对生成的 One-Hot 编码后的数据进行了解码,首先将它转为 numpy 数组,然后取36个字符中最大的数字的位置,因为神经网络会输出36个字符的概率,然后将概率最大的四个字符的编号转换为字符串。

# 将概率最大的四个字符的编号转换为字符串
def decode(y):y = np.argmax(np.array(y),axis=2)[:,0]return ''.join([characters[x] for x in y])

构建深度卷积神经网络

# 构建模型
def captcha_model():width, height, n_len, n_class = 170,80,4,36input_tensor = Input(shape=(3,height,width))x = input_tensorfor i in range(4):x = Convolution2D(32*2**i,3,3,activation='relu')(x)x = Convolution2D(32*2**i,3,3,activation='relu')(x)x = BatchNormalization(axis=1)(x)x = MaxPooling2D((2,2))(x)x = Flatten()(x)x = [Dense(n_class,activation='softmax',name='c%d' % (i+1))(x) for i in range(4)]model = Model(input=input_tensor,output=x)return model

模型结构很简单,特征提取部分使用的是两个卷积,一个池化的结构,这个结构是学的 VGG16 的结构。之后我们将它 Flatten,然后添加 Dropout ,尽量避免过拟合问题,最后连接四个分类器,每个分类器是36个神经元,输出36个字符的概率。

构建CNN这一块我采用了与原作者几乎一样的网络架构,只是我删除了网络的Dropout层,添加了BatchNormalization层,对每一次的梯度更新中的梯度值做了规范化。

模型可视化

利用keras自带的可视化工具,可以仅用一行代码就实现网络的可视化。
plot(model,to_file='model.png',show_shapes=True)

训练模型

训练模型反而是所有步骤里面最简单的一个,直接使用 model.fit_generator 即可,这里的验证集使用了同样的生成器,由于数据是通过生成器随机生成的,所以我们不用考虑数据是否会重复。注意,这段代码在笔记本上可能要耗费一下午时间。如果你想让模型预测得更准确,可以将 nb_epoch改为 10 或者 20,但它也将耗费成倍的时间。注意我们这里使用了一个小技巧,添加 nb_worker=2 参数让 Keras 自动实现多进程生成数据,摆脱 python 单线程效率低的缺点。如果不添加,耗时120秒,添加则只需80秒。(这个技巧由于我电脑配置的原因,我并没有加进去)
checkpointer =ModelCheckpoint(filepath="net-weight\\net-epoch.hdf5", verbose=1, save_best_only=True)
model.compile(loss='categorical_crossentropy',optimizer='adadelta',metrics=['accuracy'])
model.fit_generator(gen(),samples_per_epoch=51200,nb_epoch=5,validation_data=gen(),nb_val_samples=1280,callbacks=[checkpointer])

这里我设置了回调函数checkpointer,以保留训练过程中得到的最优模型的权重,预测的时候要加载权重。

测试模型

当我们训练完成以后,可以识别一个验证码试试看:

from captcha_model import captcha_model
from captcha_generate_image import gen,decode
import matplotlib.pyplot as plt
import pylab
model = captcha_model()
model.load_weights("net-weight\\net-epoch.hdf5")
X,y = next(gen(1))
y_pred = model.predict(X)
plt.title('real:%s\npred:%s' % (decode(y),decode(y_pred)))
plt.imshow(X[0].transpose((1,2,0)),cmap='gray')
pylab.show()

训练过程

训练过程中的各种输出我也列在这里,可以看到,最终每个类别的准确率几乎都达到了98%,效果还是比参考文章中略高一些。

Epoch 1/5
51168/51200 [============================>.] - ETA: 0s - loss: 3.9187 - c1_loss: 1.1468 - c2_loss: 0.8826 - c3_loss: 1.0020 - c4_loss: 0.8873 - c1_acc: 0.6875 - c2_acc: 0.7496 - c3_acc: 0.7168 - c4_acc: 0.7520Epoch 00000: val_loss improved from inf to 0.82390, saving model to net-weight\net-epoch.hdf5
51200/51200 [==============================] - 648s - loss: 3.9164 - c1_loss: 1.1461 - c2_loss: 0.8821 - c3_loss: 1.0015 - c4_loss: 0.8868 - c1_acc: 0.6877 - c2_acc: 0.7497 - c3_acc: 0.7170 - c4_acc: 0.7522 - val_loss: 0.8239 - val_c1_loss: 0.1846 - val_c2_loss: 0.1971 - val_c3_loss: 0.2559 - val_c4_loss: 0.1863 - val_c1_acc: 0.9484 - val_c2_acc: 0.9477 - val_c3_acc: 0.9359 - val_c4_acc: 0.9453
Epoch 2/5
51168/51200 [============================>.] - ETA: 0s - loss: 0.3697 - c1_loss: 0.0706 - c2_loss: 0.0773 - c3_loss: 0.1280 - c4_loss: 0.0937 - c1_acc: 0.9780 - c2_acc: 0.9741 - c3_acc: 0.9583 - c4_acc: 0.9697Epoch 00001: val_loss improved from 0.82390 to 0.75851, saving model to net-weight\net-epoch.hdf5
51200/51200 [==============================] - 651s - loss: 0.3697 - c1_loss: 0.0706 - c2_loss: 0.0773 - c3_loss: 0.1280 - c4_loss: 0.0937 - c1_acc: 0.9779 - c2_acc: 0.9741 - c3_acc: 0.9583 - c4_acc: 0.9696 - val_loss: 0.7585 - val_c1_loss: 0.1449 - val_c2_loss: 0.1911 - val_c3_loss: 0.2266 - val_c4_loss: 0.1959 - val_c1_acc: 0.9703 - val_c2_acc: 0.9547 - val_c3_acc: 0.9523 - val_c4_acc: 0.9633
Epoch 3/5
51168/51200 [============================>.] - ETA: 0s - loss: 0.2306 - c1_loss: 0.0446 - c2_loss: 0.0498 - c3_loss: 0.0763 - c4_loss: 0.0600 - c1_acc: 0.9844 - c2_acc: 0.9820 - c3_acc: 0.9744 - c4_acc: 0.9797Epoch 00002: val_loss did not improve
51200/51200 [==============================] - 647s - loss: 0.2307 - c1_loss: 0.0445 - c2_loss: 0.0498 - c3_loss: 0.0764 - c4_loss: 0.0600 - c1_acc: 0.9844 - c2_acc: 0.9820 - c3_acc: 0.9743 - c4_acc: 0.9796 - val_loss: 1.4278 - val_c1_loss: 0.2712 - val_c2_loss: 0.3074 - val_c3_loss: 0.4099 - val_c4_loss: 0.4392 - val_c1_acc: 0.9305 - val_c2_acc: 0.9281 - val_c3_acc: 0.9016 - val_c4_acc: 0.8906
Epoch 4/5
51168/51200 [============================>.] - ETA: 0s - loss: 0.1713 - c1_loss: 0.0330 - c2_loss: 0.0399 - c3_loss: 0.0551 - c4_loss: 0.0433 - c1_acc: 0.9883 - c2_acc: 0.9856 - c3_acc: 0.9815 - c4_acc: 0.9854Epoch 00003: val_loss improved from 0.75851 to 0.58820, saving model to net-weight\net-epoch.hdf5
51200/51200 [==============================] - 647s - loss: 0.1712 - c1_loss: 0.0330 - c2_loss: 0.0400 - c3_loss: 0.0551 - c4_loss: 0.0432 - c1_acc: 0.9883 - c2_acc: 0.9856 - c3_acc: 0.9815 - c4_acc: 0.9854 - val_loss: 0.5882 - val_c1_loss: 0.1112 - val_c2_loss: 0.1240 - val_c3_loss: 0.1604 - val_c4_loss: 0.1925 - val_c1_acc: 0.9734 - val_c2_acc: 0.9719 - val_c3_acc: 0.9633 - val_c4_acc: 0.9570
Epoch 5/5
51168/51200 [============================>.] - ETA: 0s - loss: 0.1372 - c1_loss: 0.0271 - c2_loss: 0.0324 - c3_loss: 0.0411 - c4_loss: 0.0367 - c1_acc: 0.9904 - c2_acc: 0.9886 - c3_acc: 0.9859 - c4_acc: 0.9871Epoch 00004: val_loss improved from 0.58820 to 0.36915, saving model to net-weight\net-epoch.hdf5
51200/51200 [==============================] - 647s - loss: 0.1373 - c1_loss: 0.0271 - c2_loss: 0.0324 - c3_loss: 0.0410 - c4_loss: 0.0367 - c1_acc: 0.9904 - c2_acc: 0.9887 - c3_acc: 0.9859 - c4_acc: 0.9871 - val_loss: 0.3691 - val_c1_loss: 0.0730 - val_c2_loss: 0.0932 - val_c3_loss: 0.1108 - val_c4_loss: 0.0922 - val_c1_acc: 0.9852 - val_c2_acc: 0.9789 - val_c3_acc: 0.9742 - val_c4_acc: 0.9836

总结

总的来说,今天一天就干了这么多事情,特别感谢原作者分享的文章,既让自己有个实战的参考,也能基于原作者进行一些网络上的改进。原作者后面提到的改进方法基于一类特殊的循环神经网络GRU,由于自己在这方面没有什么研究,就不献丑了。

参考文章:使用深度学习来破解captcha验证码

利用keras破解captcha验证码相关推荐

  1. 如何利用Python破解12306验证码和浏览车次为例!你学会了吗?

    本节重点讲的是python爬虫中的session和cookie在爬虫中的应用,所以12306验证码的破解可能相比手工操作更麻烦,但未来会讲解更容易的验证码破解和12306登陆~ cookie和sess ...

  2. 国外大神一张图学会python-12306看了会沉默,国外大神利用机器学习15分钟破解网站验证码!...

    原标题:12306看了会沉默,国外大神利用机器学习15分钟破解网站验证码! 相信很多同学,都曾被12306的神级验证码虐到过怀疑人生,但是看了下面这一位国外一位大神的分享,小蓝我算是知道为什么1230 ...

  3. 【图片验证码识别】使用深度学习来 识别captcha 验证码

    谷歌图形验证码在AI 面前已经形同虚设,所以谷歌宣布退出验证码服务,这是为什么呢? 以下文章也许可以解释原因 本文会通过 Keras 搭建一个深度卷积神经网络来识别 captcha 验证码,建议使用显 ...

  4. 使用深度学习来识别 captcha 验证码

    谷歌图形验证码在AI 面前已经形同虚设,所以谷歌宣布退出验证码服务,这是为什么呢? 以下文章也许可以解释原因 本文会通过 Keras 搭建一个深度卷积神经网络来识别 captcha 验证码,建议使用显 ...

  5. 【破解旋转验证码】百度拖动旋转验证码识别方案

    前言 百度的验证码又双叒更新了. 当然出于好奇,猫又拿起了键盘开始挑战. 正文来了. 先来看看继上次破解百度旋转验证码后,百度的大佬又做出了哪些改变. 1.抓取图片时加上了马赛克 2.增加了图片库 抓 ...

  6. Python搭建Keras CNN模型破解网站验证码

    在本项目中,将会用Keras来搭建一个稍微复杂的CNN模型来破解以上的验证码.验证码如下: 利用Keras可以快速方便地搭建CNN模型,本项目搭建的CNN模型如下: 将数据集分为训练集和测试集,占比为 ...

  7. keras入门(三)搭建CNN模型破解网站验证码

    项目介绍   在文章CNN大战验证码中,我们利用TensorFlow搭建了简单的CNN模型来破解某个网站的验证码.验证码如下: 在本文中,我们将会用Keras来搭建一个稍微复杂的CNN模型来破解以上的 ...

  8. Python Selenium破解滑块验证码最新版!

    通过率高达百分之95!真的强! 一.滑块验证码简述 有爬虫,自然就有反爬虫,就像病毒和杀毒软件一样,有攻就有防,两者彼此推进发展.而目前最流行的反爬技术验证码,为了防止爬虫自动注册,批量生成垃圾账号, ...

  9. python手工打码_使用Python + Selenium破解滑块验证码

    在前面一篇博客,介绍了 Selenium 的基本用法和爬虫开发过程中经常使用的一些小技巧,利用这些写出一个浏览器爬虫已经完全没有问题了.看了前一篇博客,可能有人会有疑惑,浏览器爬虫的优势感觉并不比传统 ...

最新文章

  1. 谨慎跟随初始目的不被关联问题带偏
  2. linux grunt环境,安装 Grunt - Grunt: JavaScript 世界的构建工具 | Grunt 中文网
  3. 加密模式||填充模式
  4. 学习笔记Hadoop(二)—— Hadoop介绍(2)——Hadoop 核心组件
  5. ant指定servlet版本_阅读SpringMVC源码前,不妨看下简易版本SpringMVC框架的搭建
  6. android--仿网易新闻主界面
  7. python快递代取系统_代取快递的变现方式,校园跑腿的经营范围有多大?
  8. 今年圣诞,麋鹿第一次请假
  9. Android蓝牙设备名显示修改
  10. C++中的继承(派生)的一些误区
  11. rt1052 usb速率_rt1052 spi flash 读数据好慢
  12. UNIX环境高级编程之第6章:系统数据文件和信息
  13. 【转载】svn代码回滚命令
  14. 《人月神话》之外科手术队伍
  15. php中strtotime函数,PHP中strtotime函数用法举例
  16. CAD文件如何转JPG图片?分享两种转换方法
  17. html横向导航二级菜单代码,横向二级导航菜单
  18. cannot import name ‘mean_squared_erro‘ from ‘sklearn.metrics‘
  19. [1025]python地理处理包shapely
  20. 新一代网状网协议T-Mesh无线通信技术优势介绍

热门文章

  1. 对称密钥系统和公开密钥系统
  2. 计算机上电自检的作用,为什么每次开机都要自检?电脑每次开机都自检怎么办?...
  3. 计算机网络造成拥塞的原因,网络拥塞问题分析及控制的策略.doc
  4. express,multer,jQuery前端后端上传单个文件
  5. 海贼王热血航线服务器维护,航海王热血航线连接服务器失败?解决方法一览
  6. 卷积码译码:硬判决维特比(Viterbi)译码
  7. 算法图解第十章笔记与习题(KNN算法)
  8. Less:less的使用方法及如何使less文件
  9. 项目管理手记 12 ERP选型,不要做 充气哈蟆
  10. Terminate快捷键