TensorFlow - 基于 CNN 破解验证码-云服务器玩法在线实验

[复制链接]
查看: 547|回复: 0

13

主题

13

帖子

55

积分

注册会员

Rank: 2

积分
55
发表于 2020-12-28 11:29:32 | 显示全部楼层 |阅读模式

实验内容

TensorFlow是由Google开发的用于数值计算的开源软件库,本实验采用 Captcha 库生成验证码,将验证码识别问题转化为分类问题,采用 CNN 网络模型进行训练,最终实现对验证码的破解。

免费在线实验地址:点击进入

实验资源:云服务器,没有云服务器的朋友推荐1折抢购:69元/年的阿里云服务器或者88元/年的腾讯云服务器

软件环境Ubuntu 16.04.1 LTS 64 位



传统的验证码识别算法一般需要把验证码分割为单个字符,然后逐个识别。本教程将验证码识别问题转化为分类的问题,实现对验证码进行整体识别。
步骤简介
本教程一共分为四个部分
  • generate_captcha.py - 利用 Captcha 库生成验证码;
  • captcha_model.py - CNN 模型;
  • train_captcha.py - 训练 CNN 模型;
  • predict_captcha.py - 识别验证码。
数据学习
任务时间:时间未知
安装 captcha 库
  1. pip install captcha
复制代码
获取训练数据
本教程使用的验证码由数字、大写字母、小写字母组成,每个验证码包含 4 个字符,总共有 62^4 种组合,所以一共有 62^4 种不同的验证码。
示例代码:
现在您可以在 /home/ubuntu 目录下创建源文件 generate_captcha.py,内容可参考:
示例代码:/home/ubuntu/generate_captcha.py
  1. #-*- coding:utf-8 -*-
  2. from captcha.image import ImageCaptcha
  3. from PIL import Image
  4. import numpy as np
  5. import random
  6. import string

  7. class generateCaptcha():
  8.     def __init__(self,
  9.                  width = 160,#验证码图片的宽
  10.                  height = 60,#验证码图片的高
  11.                  char_num = 4,#验证码字符个数
  12.                  characters = string.digits + string.ascii_uppercase + string.ascii_lowercase):#验证码组成,数字+大写字母+小写字母
  13.         self.width = width
  14.         self.height = height
  15.         self.char_num = char_num
  16.         self.characters = characters
  17.         self.classes = len(characters)

  18.     def gen_captcha(self,batch_size = 50):
  19.         X = np.zeros([batch_size,self.height,self.width,1])
  20.         img = np.zeros((self.height,self.width),dtype=np.uint8)
  21.         Y = np.zeros([batch_size,self.char_num,self.classes])
  22.         image = ImageCaptcha(width = self.width,height = self.height)

  23.         while True:
  24.             for i in range(batch_size):
  25.                 captcha_str = ''.join(random.sample(self.characters,self.char_num))
  26.                 img = image.generate_image(captcha_str).convert('L')
  27.                 img = np.array(img.getdata())
  28.                 X[i] = np.reshape(img,[self.height,self.width,1])/255.0
  29.                 for j,ch in enumerate(captcha_str):
  30.                     Y[i,j,self.characters.find(ch)] = 1
  31.             Y = np.reshape(Y,(batch_size,self.char_num*self.classes))
  32.             yield X,Y

  33.     def decode_captcha(self,y):
  34.         y = np.reshape(y,(len(y),self.char_num,self.classes))
  35.         return ''.join(self.characters[x] for x in np.argmax(y,axis = 2)[0,:])

  36.     def get_parameter(self):
  37.         return self.width,self.height,self.char_num,self.characters,self.classes

  38.     def gen_test_captcha(self):
  39.         image = ImageCaptcha(width = self.width,height = self.height)
  40.         captcha_str = ''.join(random.sample(self.characters,self.char_num))
  41.         img = image.generate_image(captcha_str)
  42.         img.save(captcha_str + '.jpg')

  43.         X = np.zeros([1,self.height,self.width,1])
  44.         Y = np.zeros([1,self.char_num,self.classes])
  45.         img = img.convert('L')
  46.         img = np.array(img.getdata())
  47.         X[0] = np.reshape(img,[self.height,self.width,1])/255.0
  48.         for j,ch in enumerate(captcha_str):
  49.             Y[0,j,self.characters.find(ch)] = 1
  50.         Y = np.reshape(Y,(1,self.char_num*self.classes))
  51.         return X,Y
复制代码
理解训练数据
  • X:一个 mini-batch 的训练数据,其 shape 为 [ batch_size, height, width, 1 ],batch_size 表示每批次多少个训练数据,height 表示验证码图片的高,width 表示验证码图片的宽,1 表示图片的通道。
  • Y:X 中每个训练数据属于哪一类验证码,其形状为 [ batch_size, class ] ,对验证码中每个字符进行 One-Hot 编码,所以 class 大小为 4*62。
执行:
  • 获取验证码和对应的分类
    1. cd /home/ubuntu;
    2. python
    3. from generate_captcha import generateCaptcha
    4. g = generateCaptcha()
    5. X,Y = g.gen_test_captcha()
    复制代码

  • 查看训练数据
    1. X.shape
    2. Y.shape
    复制代码
    可以在 /home/ubuntu 目录下查看生成的验证码,jpg 格式的图片可以点击查看。
    模型学习
    任务时间:时间未知
    CNN 模型
    总共 5 层网络,前 3 层为卷积层,第 4、5 层为全连接层。对 4 层隐藏层都进行 dropout。网络结构如下所示: input——>conv——>pool——>dropout——>conv——>pool——>dropout——>conv——>pool——>dropout——>fully connected layer——>dropout——>fully connected layer——>output
    示例代码:
    现在您可以在 /home/ubuntu 目录下创建源文件 captcha_model.py,内容可参考:
    示例代码:/home/ubuntu/captcha_model.py
    1. # -*- coding: utf-8 -*
    2. import tensorflow as tf
    3. import math

    4. class captchaModel():
    5.     def __init__(self,
    6.                  width = 160,
    7.                  height = 60,
    8.                  char_num = 4,
    9.                  classes = 62):
    10.         self.width = width
    11.         self.height = height
    12.         self.char_num = char_num
    13.         self.classes = classes

    14.     def conv2d(self,x, W):
    15.         return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    16.     def max_pool_2x2(self,x):
    17.         return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
    18.                               strides=[1, 2, 2, 1], padding='SAME')

    19.     def weight_variable(self,shape):
    20.         initial = tf.truncated_normal(shape, stddev=0.1)
    21.         return tf.Variable(initial)

    22.     def bias_variable(self,shape):
    23.         initial = tf.constant(0.1, shape=shape)
    24.         return tf.Variable(initial)

    25.     def create_model(self,x_images,keep_prob):
    26.         #first layer
    27.         w_conv1 = self.weight_variable([5, 5, 1, 32])
    28.         b_conv1 = self.bias_variable([32])
    29.         h_conv1 = tf.nn.relu(tf.nn.bias_add(self.conv2d(x_images, w_conv1), b_conv1))
    30.         h_pool1 = self.max_pool_2x2(h_conv1)
    31.         h_dropout1 = tf.nn.dropout(h_pool1,keep_prob)
    32.         conv_width = math.ceil(self.width/2)
    33.         conv_height = math.ceil(self.height/2)

    34.         #second layer
    35.         w_conv2 = self.weight_variable([5, 5, 32, 64])
    36.         b_conv2 = self.bias_variable([64])
    37.         h_conv2 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout1, w_conv2), b_conv2))
    38.         h_pool2 = self.max_pool_2x2(h_conv2)
    39.         h_dropout2 = tf.nn.dropout(h_pool2,keep_prob)
    40.         conv_width = math.ceil(conv_width/2)
    41.         conv_height = math.ceil(conv_height/2)

    42.         #third layer
    43.         w_conv3 = self.weight_variable([5, 5, 64, 64])
    44.         b_conv3 = self.bias_variable([64])
    45.         h_conv3 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout2, w_conv3), b_conv3))
    46.         h_pool3 = self.max_pool_2x2(h_conv3)
    47.         h_dropout3 = tf.nn.dropout(h_pool3,keep_prob)
    48.         conv_width = math.ceil(conv_width/2)
    49.         conv_height = math.ceil(conv_height/2)

    50.         #first fully layer
    51.         conv_width = int(conv_width)
    52.         conv_height = int(conv_height)
    53.         w_fc1 = self.weight_variable([64*conv_width*conv_height,1024])
    54.         b_fc1 = self.bias_variable([1024])
    55.         h_dropout3_flat = tf.reshape(h_dropout3,[-1,64*conv_width*conv_height])
    56.         h_fc1 = tf.nn.relu(tf.nn.bias_add(tf.matmul(h_dropout3_flat, w_fc1), b_fc1))
    57.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    58.         #second fully layer
    59.         w_fc2 = self.weight_variable([1024,self.char_num*self.classes])
    60.         b_fc2 = self.bias_variable([self.char_num*self.classes])
    61.         y_conv = tf.add(tf.matmul(h_fc1_drop, w_fc2), b_fc2)

    62.         return y_conv
    复制代码
    训练 CNN 模型
    每批次采用 64 个训练样本,每 100 次循环采用 100 个测试样本检查识别准确度,当准确度大于 99% 时,训练结束,采用 GPU 需要 4-5 个小时左右,CPU 大概需要 20 个小时左右。
    示例代码:
    现在您可以在 /home/ubuntu 目录下创建源文件 train_captcha.py,内容可参考:
    示例代码:/home/ubuntu/train_captcha.py
    1. #-*- coding:utf-8 -*-
    2. import tensorflow as tf
    3. import numpy as np
    4. import string
    5. import generate_captcha
    6. import captcha_model

    7. if __name__ == '__main__':
    8.     captcha = generate_captcha.generateCaptcha()
    9.     width,height,char_num,characters,classes = captcha.get_parameter()

    10.     x = tf.placeholder(tf.float32, [None, height,width,1])
    11.     y_ = tf.placeholder(tf.float32, [None, char_num*classes])
    12.     keep_prob = tf.placeholder(tf.float32)

    13.     model = captcha_model.captchaModel(width,height,char_num,classes)
    14.     y_conv = model.create_model(x,keep_prob)
    15.     cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y_,logits=y_conv))
    16.     train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

    17.     predict = tf.reshape(y_conv, [-1,char_num, classes])
    18.     real = tf.reshape(y_,[-1,char_num, classes])
    19.     correct_prediction = tf.equal(tf.argmax(predict,2), tf.argmax(real,2))
    20.     correct_prediction = tf.cast(correct_prediction, tf.float32)
    21.     accuracy = tf.reduce_mean(correct_prediction)

    22.     saver = tf.train.Saver()
    23.     with tf.Session() as sess:
    24.         sess.run(tf.global_variables_initializer())
    25.         step = 1
    26.         while True:
    27.             batch_x,batch_y = next(captcha.gen_captcha(64))
    28.             _,loss = sess.run([train_step,cross_entropy],feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.75})
    29.             print ('step:%d,loss:%f' % (step,loss))
    30.             if step % 100 == 0:
    31.                 batch_x_test,batch_y_test = next(captcha.gen_captcha(100))
    32.                 acc = sess.run(accuracy, feed_dict={x: batch_x_test, y_: batch_y_test, keep_prob: 1.})
    33.                 print ('###############################################step:%d,accuracy:%f' % (step,acc))
    34.                 if acc > 0.99:
    35.                     saver.save(sess,"./capcha_model.ckpt")
    36.                     break
    37.             step += 1
    复制代码
    然后执行:
    1. cd /home/ubuntu;
    2. python train_captcha.py
    复制代码
    执行结果:
    1. step:75193,loss:0.010931
    2. step:75194,loss:0.012859
    3. step:75195,loss:0.008747
    4. step:75196,loss:0.009147
    5. step:75197,loss:0.009351
    6. step:75198,loss:0.009746
    7. step:75199,loss:0.010014
    8. step:75200,loss:0.009024
    9. ###############################################step:75200,accuracy:0.992500
    复制代码
    使用训练好的模型:
    作为实验,你可以通过调整 train_captcha.py 文件中 if acc > 0.99: 代码行的准确度节省训练时间(比如将 0.99 为 0.01),体验训练过程;我们已经通过长时间的训练得到了一个训练好的模型,可以通过如下命令将训练集下载到本地。
    1. wget http://tensorflow-1253902462.cosgz.myqcloud.com/captcha/capcha_model.zip
    2. unzip -o capcha_model.zip
    复制代码
    识别验证码测试数据集:
    我们在腾讯云的 COS 上准备了 100 个验证码作为测试集,使用 wget 命令获取:
    1. wget http://tensorflow-1253902462.cosgz.myqcloud.com/captcha/captcha.zip
    2. unzip -q captcha.zip
    复制代码
    示例代码:
    现在您可以在 /home/ubuntu 目录下创建源文件 predict_captcha.py,内容可参考:
    示例代码:/home/ubuntu/predict_captcha.py
    1. #-*- coding:utf-8 -*-
    2. from PIL import Image, ImageFilter
    3. import tensorflow as tf
    4. import numpy as np
    5. import string
    6. import sys
    7. import generate_captcha
    8. import captcha_model

    9. if __name__ == '__main__':
    10.     captcha = generate_captcha.generateCaptcha()
    11.     width,height,char_num,characters,classes = captcha.get_parameter()

    12.     gray_image = Image.open(sys.argv[1]).convert('L')
    13.     img = np.array(gray_image.getdata())
    14.     test_x = np.reshape(img,[height,width,1])/255.0
    15.     x = tf.placeholder(tf.float32, [None, height,width,1])
    16.     keep_prob = tf.placeholder(tf.float32)

    17.     model = captcha_model.captchaModel(width,height,char_num,classes)
    18.     y_conv = model.create_model(x,keep_prob)
    19.     predict = tf.argmax(tf.reshape(y_conv, [-1,char_num, classes]),2)
    20.     init_op = tf.global_variables_initializer()
    21.     saver = tf.train.Saver()
    22.     gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.95)
    23.     with tf.Session(config=tf.ConfigProto(log_device_placement=False,gpu_options=gpu_options)) as sess:
    24.         sess.run(init_op)
    25.         saver.restore(sess, "capcha_model.ckpt")
    26.         pre_list =  sess.run(predict,feed_dict={x: [test_x], keep_prob: 1})
    27.         for i in pre_list:
    28.             s = ''
    29.             for j in i:
    30.                 s += characters[j]
    31.             print(s)
    复制代码
    然后执行:
    1. cd /home/ubuntu;
    2. python predict_captcha.py captcha/0hWn.jpg
    复制代码
    执行结果:
    1. 0hWn
    复制代码
    完成实验

腾讯云
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

精彩图文



在线客服(工作时间:9:00-22:00)
400-600-6565

内容导航

微信客服

Copyright   ©2015-2019  云服务器社区  Powered by©Discuz!  技术支持:尊托网络     ( 湘ICP备15009499号-1 )