深度学习基于TF破解验证码

来源:互联网 发布:web java开发就业前景 编辑:程序博客网 时间:2024/06/09 22:58

前言

学习腾讯的开发者课程以后,感觉很不错,记录一下,验证码主要用于防刷,传统的验证码识别算法一般需要把验证码分割为单个字符,然后逐个识别,如果字符之间相互重叠,传统的算法就然并卵了,本文采用cnn对验证码进行整体识别。通过本文的学习,大家可以学到几点:1.captcha库生成验证码;2.如何将验证码识别问题转化为分类问题;3.可以训练自己的验证码识别模型。

步骤

  1. prepare_data.py - 验证码生成,使用python库captcha来生成,速度快,数量多
  2. prepare_model.py - 两层RNN网络模型,采用LSTM模型;
  3. train.py - 训练CNN模型(3 层隐藏层、2 层全连接层)
  4. predict.py - 使用图片进行预测

生成数据

安装 captcha 库

captcha 可以生成语音和图片验证码,我们采用生成图片验证码功能,验证码是由数字、大写字母、小写字母组成(当然你也可以根据自己的需求调整,比如添加一些特殊字符),长度为 4,所以总共有 62^4 种组合验证码,没有的自行安装

sudo pip install captcha

下面是生成验证码的代码:

#!/usr/bin/python# -*- coding: utf-8 -*from captcha.image import ImageCaptchafrom PIL import Imageimport numpy as npimport randomimport stringclass generateCaptcha():    def __init__(self,                 width = 160,#验证码图片的宽                 height = 60,#验证码图片的高                 char_num = 4,#验证码字符个数                 characters = string.digits + string.ascii_uppercase + string.ascii_lowercase):#验证码组成,数字+大写字母+小写字母        self.width = width        self.height = height        self.char_num = char_num        self.characters = characters        self.classes = len(characters)    def gen_captcha(self,batch_size = 50):        X = np.zeros([batch_size,self.height,self.width,1])        img = np.zeros((self.height,self.width),dtype=np.uint8)        Y = np.zeros([batch_size,self.char_num,self.classes])        image = ImageCaptcha(width = self.width,height = self.height)        while True:            for i in range(batch_size):                captcha_str = ''.join(random.sample(self.characters,self.char_num))                img = image.generate_image(captcha_str).convert('L')                img = np.array(img.getdata())                X[i] = np.reshape(img,[self.height,self.width,1])/255.0                for j,ch in enumerate(captcha_str):                    Y[i,j,self.characters.find(ch)] = 1            Y = np.reshape(Y,(batch_size,self.char_num*self.classes))            yield X,Y    def decode_captcha(self,y):        y = np.reshape(y,(len(y),self.char_num,self.classes))        return ''.join(self.characters[x] for x in np.argmax(y,axis = 2)[0,:])    def get_parameter(self):        return self.width,self.height,self.char_num,self.characters,self.classes    def gen_test_captcha(self):        image = ImageCaptcha(width = self.width,height = self.height)        captcha_str = ''.join(random.sample(self.characters,self.char_num))        img = image.generate_image(captcha_str)        img.save(captcha_str + '.jpg')

准备模型

对每层都进行 dropout。input——>conv——>pool——>dropout——>conv——>pool——>dropout——>conv——>pool——>dropout——>fully connected layer——>dropout——>fully connected layer——>output ,所有对图片处理都需要这些步骤,只是层数不同而已。

#!/usr/bin/python# -*- coding: utf-8 -*import tensorflow as tfimport mathclass captchaModel():    def __init__(self,                 width = 160,                 height = 60,                 char_num = 4,                 classes = 62):        self.width = width        self.height = height        self.char_num = char_num        self.classes = classes    def conv2d(self,x, W):        return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')    def max_pool_2x2(self,x):        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],                              strides=[1, 2, 2, 1], padding='SAME')    def weight_variable(self,shape):        initial = tf.truncated_normal(shape, stddev=0.1)        return tf.Variable(initial)    def bias_variable(self,shape):        initial = tf.constant(0.1, shape=shape)        return tf.Variable(initial)    def create_model(self,x_images,keep_prob):        #first layer        w_conv1 = self.weight_variable([5, 5, 1, 32])        b_conv1 = self.bias_variable([32])        h_conv1 = tf.nn.relu(tf.nn.bias_add(self.conv2d(x_images, w_conv1), b_conv1))        h_pool1 = self.max_pool_2x2(h_conv1)        h_dropout1 = tf.nn.dropout(h_pool1,keep_prob)        conv_width = math.ceil(self.width/2)        conv_height = math.ceil(self.height/2)        #second layer        w_conv2 = self.weight_variable([5, 5, 32, 64])        b_conv2 = self.bias_variable([64])        h_conv2 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout1, w_conv2), b_conv2))        h_pool2 = self.max_pool_2x2(h_conv2)        h_dropout2 = tf.nn.dropout(h_pool2,keep_prob)        conv_width = math.ceil(conv_width/2)        conv_height = math.ceil(conv_height/2)        #third layer        w_conv3 = self.weight_variable([5, 5, 64, 64])        b_conv3 = self.bias_variable([64])        h_conv3 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout2, w_conv3), b_conv3))        h_pool3 = self.max_pool_2x2(h_conv3)        h_dropout3 = tf.nn.dropout(h_pool3,keep_prob)        conv_width = math.ceil(conv_width/2)        conv_height = math.ceil(conv_height/2)        #first fully layer        conv_width = int(conv_width)        conv_height = int(conv_height)        w_fc1 = self.weight_variable([64*conv_width*conv_height,1024])        b_fc1 = self.bias_variable([1024])        h_dropout3_flat = tf.reshape(h_dropout3,[-1,64*conv_width*conv_height])        h_fc1 = tf.nn.relu(tf.nn.bias_add(tf.matmul(h_dropout3_flat, w_fc1), b_fc1))        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)        #second fully layer        w_fc2 = self.weight_variable([1024,self.char_num*self.classes])        b_fc2 = self.bias_variable([self.char_num*self.classes])        y_conv = tf.add(tf.matmul(h_fc1_drop, w_fc2), b_fc2)        return y_conv

定义好模型和数据后,下面开始训练

训练

每批次采用 64 个训练样本,每 100 次循环采用 100 个测试样本检查识别准确度,当准确度大于 99% 时,训练结束,采用 GPU 需要 5-6 个小时左右,CPU 大概需要 20 个小时左右
—-来自腾讯大大

#!/usr/bin/pythonimport tensorflow as tfimport numpy as npimport stringimport generate_captchaimport captcha_modelif __name__ == '__main__':    captcha = generate_captcha.generateCaptcha()    width,height,char_num,characters,classes = captcha.get_parameter()    x = tf.placeholder(tf.float32, [None, height,width,1])    y_ = tf.placeholder(tf.float32, [None, char_num*classes])    keep_prob = tf.placeholder(tf.float32)    model = captcha_model.captchaModel(width,height,char_num,classes)    y_conv = model.create_model(x,keep_prob)    cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y_,logits=y_conv))    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)    predict = tf.reshape(y_conv, [-1,char_num, classes])    real = tf.reshape(y_,[-1,char_num, classes])    correct_prediction = tf.equal(tf.argmax(predict,2), tf.argmax(real,2))    correct_prediction = tf.cast(correct_prediction, tf.float32)    accuracy = tf.reduce_mean(correct_prediction)    saver = tf.train.Saver()    with tf.Session() as sess:        sess.run(tf.global_variables_initializer())        step = 0        while True:            batch_x,batch_y = next(captcha.gen_captcha(64))            _,loss = sess.run([train_step,cross_entropy],feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.75})            print ('step:%d,loss:%f' % (step,loss))            if step % 100 == 0:                batch_x_test,batch_y_test = next(captcha.gen_captcha(100))                acc = sess.run(accuracy, feed_dict={x: batch_x_test, y_: batch_y_test, keep_prob: 1.})                print ('###############################################step:%d,accuracy:%f' % (step,acc))                if acc > 0.99:                    saver.save(sess,"capcha_model.ckpt")                    break            step += 1

题外话

免训练的快速通道:

wget http://tensorflow-1253902462.cosgz.myqcloud.com/captcha/capcha_model.zipunzip capcha_model.zip

预测

鸡冻人心的时刻来了

#!/usr/bin/pythonfrom PIL import Image, ImageFilterimport tensorflow as tfimport numpy as npimport stringimport sysimport generate_captchaimport captcha_modelif __name__ == '__main__':    captcha = generate_captcha.generateCaptcha()    width,height,char_num,characters,classes = captcha.get_parameter()    gray_image = Image.open(sys.argv[1]).convert('L')    img = np.array(gray_image.getdata())    test_x = np.reshape(img,[height,width,1])/255.0    x = tf.placeholder(tf.float32, [None, height,width,1])    keep_prob = tf.placeholder(tf.float32)    model = captcha_model.captchaModel(width,height,char_num,classes)    y_conv = model.create_model(x,keep_prob)    predict = tf.argmax(tf.reshape(y_conv, [-1,char_num, classes]),2)    init_op = tf.global_variables_initializer()    saver = tf.train.Saver()    gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.95)    with tf.Session(config=tf.ConfigProto(log_device_placement=False,gpu_options=gpu_options)) as sess:        sess.run(init_op)        saver.restore(sess, "capcha_model.ckpt")        pre_list =  sess.run(predict,feed_dict={x: [test_x], keep_prob: 1})        for i in pre_list:            s = ''            for j in i:                s += characters[j]            print s

运行如下:
“`
python predict_captcha.py Tc0m.jpg
这里写图片描述
如果没有测试图片,使用prepare_data下的gen_test_captcha()方法即可生成一张。

所有代码托管于:https://github.com/tengxing/tensorflow-learn/captcha 欢迎start!

原创粉丝点击