项目简介

  在之前的文章keras入门(三)搭建CNN模型破解网站验证码中,笔者介绍介绍了如何用Keras来搭建CNN模型来破解网站的验证码,其中验证码含有字母和数字。

  让我们一起回顾一下那篇文章的处理思路:

  • 利用OpenCV对图像进行单个字符的切割,大概400多张图片;
  • 对切割好的单个字符进行人工手动标记;
  • 搭建合适的CNN模型,对标记好的数据集进行训练;
  • 对于新的验证码,先切割单个字符,再对单个字符进行预测,组成总的预测结果。

  这一次,笔者将会换种思路,使用CNN模型来破解网站的验证码。我们的数据集如下:

一共是946张图片,这里只展示了一部分,可以看到,这些验证码全部由数字组成。那么,新的破解验证码的思路是什么呢?如下:

  • 直接对验证码进行标记,标记的结果见上图;
  • 搭建合适的CNN模型对标记好的数据集进行训练;
  • 对新验证码进行预测。

这种思路的好处是,不需要对验证码进行繁琐的预处理,只需要简单的数据标记即可。

  下面,笔者将会具体展示这个过程。

数据标记

  数据标记绝对是个累活,当我想到要对946张图片进行标记并重命名,而且还要保证标记的准确性的时候,我开始是有点拒绝的心态,毕竟这项工作费时费力,而且能不能保证识别的效果还是个未知数。

  就这么纠结了一段时间,原本年前就想做的项目一直拖到了现在,后来我想,能不能写个脚本,能够帮助我快速地进行数据标注,并自动保存呢?这么想着,我就动手自己做了一个由Tornado实现的前端页面,可以帮助我快速地标记数据并保存图片,页面如下:

界面虽然简陋,却能帮助我很好地提升数据标记的速度,只需要在value文本框中输入自己识别的结果,程序就能自动保存标记好的图片,并切换至下一张未标记的验证码。有了如此好的工具,结果我用了不到一小时就标记完了这946张验证码(其实是1000张,因为标记好的结果会有重复)。有机会笔者会介绍这个验证码标记的项目~

模型训练

  标记完验证码后,我们就利用这946张验证码作为训练数据,训练CNN模型。我们使用Keras框架,CNN模型的结构图如下:

模型训练的Python代码如下:

  1. # CNN模型训练
  2. # -*- coding: utf-8 -*-
  3. import cv2
  4. import os
  5. import random
  6. import numpy as np
  7. from keras.models import *
  8. from keras.layers import *
  9. from keras import callbacks
  10. characters = '0123456789'
  11. width, height, n_len, n_class = 50, 22, 4, 10
  12. # 产生训练的一批图片,默认是32张图片
  13. def gen(dir, batch_size=32):
  14. X = np.zeros((batch_size, height, width, 3), dtype=np.uint8)
  15. y = [np.zeros((batch_size, n_class), dtype=np.uint8) for _ in range(n_len)]
  16. files = os.listdir(dir)
  17. while True:
  18. for i in range(batch_size):
  19. path = random.choice(files)
  20. imagePixel = cv2.imread(dir+'/'+path, 1)
  21. filename = path[:4]
  22. X[i] = imagePixel
  23. for j, ch in enumerate(filename):
  24. y[j][i, :] = 0
  25. y[j][i, characters.find(ch)] = 1
  26. yield X, y
  27. input_tensor = Input((height, width, 3))
  28. x = input_tensor
  29. # 产生有四个block的卷积神经网络
  30. for i in range(4):
  31. # 卷积层
  32. x = Conv2D(32 * 2 ** i, (3, 3), activation='relu', padding='same')(x)
  33. x = Conv2D(32 * 2 ** i, (3, 3), activation='relu', padding='same')(x)
  34. # 池化层
  35. x = MaxPooling2D((2, 2))(x)
  36. x = Flatten()(x)
  37. x = Dropout(0.25)(x)
  38. # 多输出模型,使用了4个'softmax'來分别预测4個字母的输出
  39. x = [Dense(n_class, activation='softmax', name='c%d' % (i + 1))(x) for i in range(4)]
  40. model = Model(inputs=input_tensor, outputs=x)
  41. model.summary()
  42. # 保存模型结构图
  43. from keras.utils.vis_utils import plot_model
  44. plot_model(model, to_file="./model.png", show_shapes=True)
  45. model.compile(loss='categorical_crossentropy',
  46. optimizer='adadelta',
  47. metrics=['accuracy'])
  48. # 保存效果最好的模型
  49. cbks = [callbacks.ModelCheckpoint("best_model.h5", save_best_only=True)]
  50. dir = './result'
  51. history = model.fit_generator(gen(dir, batch_size=8), # 每次生成器会产生8张小批量的图片
  52. steps_per_epoch=120, # 每次的epoch要训练120批图片
  53. epochs=50, # 总共训练50次
  54. callbacks=cbks, # 保存最好的模型
  55. validation_data=gen(dir), # 验证数据也是用生成器來产生
  56. validation_steps=10 # 用10组图片来进行验证
  57. )
  58. # 绘制损失值图像
  59. import matplotlib.pyplot as plt
  60. def plot_train_history(history, train_metrics, val_metrics):
  61. plt.plot(history.history.get(train_metrics), '-o')
  62. plt.plot(history.history.get(val_metrics), '-o')
  63. plt.ylabel(train_metrics)
  64. plt.xlabel('Epochs')
  65. plt.legend(['train', 'validation'])
  66. # 打印整体的loss与val_loss,并保存图片
  67. plot_train_history(history, 'loss', 'val_loss')
  68. plt.savefig('./all_loss.png')
  69. plt.figure(figsize=(12, 4))
  70. # 第一个数字的正确率
  71. plt.subplot(2, 2, 1)
  72. plot_train_history(history, 'c1_acc', 'val_c1_acc')
  73. # 第二个数字的正确率
  74. plt.subplot(2, 2, 2)
  75. plot_train_history(history, 'c2_acc', 'val_c2_acc')
  76. # 第三個数字的正確率
  77. plt.subplot(2, 2, 3)
  78. plot_train_history(history, 'c3_acc', 'val_c3_acc')
  79. # 第四個数字的正确率
  80. plt.subplot(2, 2, 4)
  81. plot_train_history(history, 'c4_acc', 'val_c4_acc')
  82. # 保存图片
  83. plt.savefig('./train.png')

在这个代码中,我们总共训练了50个epoch,每个epoch共120次批次,每个批次是8张验证码,每张验证码的大小为50*22。

  运行该训练模型,后几个epoch的输出结果如下:

总的损失值图像如下:

四个数字每个数字的损失值图像如下:

训练完后,程序会将训练效果最好的epoch保存为best_model.h5文件,便于后续的模型预测。由输出的结果及图像来看,该CNN模型的训练效果应该是相当好的,下面,我们来看看对新验证码的预测效果。

模型预测

  新的验证码共有20张,如下:

模型预测的Python代码如下:

  1. # 使用训练好的CNN模型对新图片进行预测
  2. # -*- coding: utf-8 -*-
  3. from keras.models import load_model
  4. import cv2
  5. import numpy as np
  6. # 导入训练好的模型
  7. model = load_model('best_model.h5')
  8. batch_size = 20
  9. width, height, n_len, n_class = 50, 22, 4, 10
  10. # 导入验证码数据并进行预测
  11. X = np.zeros((batch_size, height, width, 3), dtype=np.uint8)
  12. for i in range(batch_size):
  13. X_test = cv2.imread('./new_image/code%d.png' %(i+1), 1)
  14. X[i] = X_test
  15. y_pred = model.predict(X)
  16. y_pred = np.argmax(y_pred, axis=2)
  17. # 输出每张验证码的预测结果
  18. for i in range(batch_size):
  19. print('第%d张验证码的识别结果为:' %(i+1), end='')
  20. print(''.join(map(str, y_pred[:, i].tolist())))

运行该模型,得到的输出结果如下:

  1. 1张验证码的识别结果为:3568
  2. 2张验证码的识别结果为:5402
  3. 3张验证码的识别结果为:6051
  4. 4张验证码的识别结果为:6769
  5. 5张验证码的识别结果为:2675
  6. 6张验证码的识别结果为:2450
  7. 7张验证码的识别结果为:2364
  8. 8张验证码的识别结果为:6879
  9. 9张验证码的识别结果为:3702
  10. 10张验证码的识别结果为:3459
  11. 11张验证码的识别结果为:5895
  12. 12张验证码的识别结果为:8042
  13. 13张验证码的识别结果为:6897
  14. 14张验证码的识别结果为:6558
  15. 15张验证码的识别结果为:9428
  16. 16张验证码的识别结果为:5662
  17. 17张验证码的识别结果为:5431
  18. 18张验证码的识别结果为:4981
  19. 19张验证码的识别结果为:0567
  20. 20张验证码的识别结果为:5239

对这20张新的验证码,预测完全正确!不得不说,CNN模型的识别效果非常好!

总结

  本文采用了一种新的思路,搭建CNN模型来实现验证码的识别,取得了不错的识别效果,而且识别的验证码是从网页中下载下来的,具有实际背景,增强了该项目的应用性。

  本项目已放至Github,地址为:https://github.com/percent4/CAPTCHA-Recognizition

注意:本人现已开通微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注哦~~

Keras入门(四)之利用CNN模型轻松破解网站验证码的更多相关文章

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

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

  2. Keras入门(二)模型的保存、读取及加载

    本文将会介绍如何利用Keras来实现模型的保存.读取以及加载.   本文使用的模型为解决IRIS数据集的多分类问题而设计的深度神经网络(DNN)模型,模型的结构示意图如下: 具体的模型参数可以参考文章 ...

  3. Keras入门(六)模型训练实时可视化

      在北京做某个项目的时候,客户要求能够对数据进行训练.预测,同时能导出模型,还有在页面上显示训练的进度.前面的几个要求都不难实现,但在页面上显示训练进度当时笔者并没有实现.   本文将会分享如何在K ...

  4. keras训练cnn模型时loss为nan

    keras训练cnn模型时loss为nan 1.首先记下来如何解决这个问题的:由于我代码中 model.compile(loss='categorical_crossentropy', optimiz ...

  5. Spring Cloud实战之初级入门(四)— 利用Hystrix实现服务熔断与服务监控

    目录 1.环境介绍 2.服务监控 2.1 加入依赖 2.2 修改配置文件 2.3 修改启动文件 2.4 监控服务 2.5 小结 3. 利用hystrix实现消费服务熔断 3.1 加入服务熔断 3.2 ...

  6. Keras入门(一)搭建深度神经网络(DNN)解决多分类问题

    Keras介绍   Keras是一个开源的高层神经网络API,由纯Python编写而成,其后端可以基于Tensorflow.Theano.MXNet以及CNTK.Keras 为支持快速实验而生,能够把 ...

  7. 【翻译】借助 NeoCPU 在 CPU 上进行 CNN 模型推理优化

    本文翻译自 Yizhi Liu, Yao Wang, Ruofei Yu.. 的  "Optimizing CNN Model Inference on CPUs" 原文链接: h ...

  8. Keras如何构造简单的CNN网络

    1. 导入各种模块 基本形式为: import 模块名 from 某个文件 import 某个模块 2. 导入数据(以两类分类问题为例,即numClass = 2) 训练集数据data 可以看到,da ...

  9. 深度学习:Keras入门(一)之基础篇

    1.关于Keras 1)简介 Keras是由纯python编写的基于theano/tensorflow的深度学习框架. Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结 ...

随机推荐

  1. java 四舍五入保留两位小数

    // 保留两位小数 System.out.println(Double.parseDouble(String.format("%.2f", 55.5454545454))); // ...

  2. Python创建微信机器人

    微信,一个日活10亿的超级app,不仅在国内社交独领风骚,在国外社交也同样占有一席之地,今天我们要将便是如何用Python来生成一个微信机器人,突然想起鲁迅先生曾经说过的一句话:因为是微信机器人系列的 ...

  3. pandas和spark的dataframe互转

    pandas的dataframe转spark的dataframe from pyspark.sql import SparkSession # 初始化spark会话 spark = SparkSess ...

  4. 初探奥尔良(Orleans)

    由于工作上关系目前经常被各种并发数据问题搞得焦头烂额,要么要性能舍弃数据上得一致性,要么要一致性但是却得到了特别糟糕的响应.难道鱼和熊掌真的无法兼得吗? 然后找到了类似奥尔良这种基于Actor模型的k ...

  5. 通过改进团队流程最大限度发挥Scrum的优势

    团队如何最大限度地发挥Scrum和敏捷的优势? 回想一下,Scrum团队在Scrum的框架内定义了自己的流程.这其中包括方法.工具和互动以及如何履行Scrum角色的职责.如何使用工件和事件等. 如何确 ...

  6. vue安装jquery和配置(不需要在页面引入直接可以使用)

    首先在命令行工具上输入 npm install jquery --save-dev 安装完成之后在build文件夹下的webpack.base.conf.js进行配置,在顶部添加:const webp ...

  7. Java 学习笔记 Junit4单元测试使用

    Junit使用 1.导入Junit包 到官网下载个Junit4.12.jar文件,放在lib目录 或者在类的空白处打@Test,之后按下alt+enter,选择添加Junit4依赖 之后就会弹出一个窗 ...

  8. 我学Java我傲娇

    今天,终于把学习了一年多的<Java核心技术36讲>第一遍完结了,历时一年多,花出去的钱终于感觉有了第一笔回报. 这是我在极客时间的第一门付费课程,刚出来的时候,正巧自己转到全职Java开 ...

  9. Java实现简易联网坦克对战小游戏

    目录 介绍 本项目的Github地址 基础版本 游戏的原理, 图形界面(非重点) 游戏逻辑 网络联机 客户端连接上服务器 定义应用层协议 TankNewMsg TankMoveMsg MissileN ...

  10. 正确分析结构使用正确的HTML标签。CSS样式写一起。

    在内容中 一行内容包括三张图片,每张图片下面有标题和具体介绍,那么可以使用: 分析和解决如下步骤: 1,一行三块,先向左浮动成为一行float:left. 2,把他们的宽度平分三份,33.3%.三份都 ...