zoukankan      html  css  js  c++  java
  • CNN识别验证码1

    之前学习python的时候,想尝试用requests实现自动登陆,但是现在网站登陆都会有验证码保护,主要是为了防止暴力破解,任意用户注册。最近接触深度学习,cnn能够进行图像识别,能够进行验证码识别。

    主要步骤:

    1、采样制作样本文件

    2、根据样本文件类型创建识别模型

    3、对样本文件分为训练样本和测试样本来训练识别模型

    4、保存识别模型和验证

    第一步生成验证码,保存文件为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 
     8 class generateCaptcha():
     9     def __init__(self,
    10                  width = 160,#验证码图片的宽
    11                  height = 60,#验证码图片的高
    12                  char_num = 4,#验证码字符个数
    13                  characters = string.digits + string.ascii_uppercase + string.ascii_lowercase):#验证码组成,数字+大写字母+小写字母
    14         self.width = width
    15         self.height = height
    16         self.char_num = char_num
    17         self.characters = characters
    18         self.classes = len(characters)  #10+26+26=62
    19 
    20     def gen_captcha(self,batch_size = 50):
    21         X = np.zeros([batch_size,self.height,self.width,1])
    22         img = np.zeros((self.height,self.width),dtype=np.uint8)
    23         Y = np.zeros([batch_size,self.char_num,self.classes])
    24         image = ImageCaptcha(width = self.width,height = self.height)
    25 
    26         while True:
    27             for i in range(batch_size):
    28                 captcha_str = ''.join(random.sample(self.characters,self.char_num))
    29                 img = image.generate_image(captcha_str).convert('L')
    30                 img = np.array(img.getdata())
    31                 X[i] = np.reshape(img,[self.height,self.width,1])/255.0
    32                 for j,ch in enumerate(captcha_str):
    33                     Y[i,j,self.characters.find(ch)] = 1
    34             Y = np.reshape(Y,(batch_size,self.char_num*self.classes))
    35             yield X,Y
    36 
    37     def decode_captcha(self,y):
    38         y = np.reshape(y,(len(y),self.char_num,self.classes))
    39         return ''.join(self.characters[x] for x in np.argmax(y,axis = 2)[0,:])
    40 
    41     def get_parameter(self):
    42         return self.width,self.height,self.char_num,self.characters,self.classes
    43 
    44     def gen_test_captcha(self):
    45         image = ImageCaptcha(width = self.width,height = self.height)
    46         captcha_str = ''.join(random.sample(self.characters,self.char_num))
    47         img = image.generate_image(captcha_str)
    48         img.save(captcha_str + '.jpg')
    49 
    50         X = np.zeros([1,self.height,self.width,1])
    51         Y = np.zeros([1,self.char_num,self.classes])
    52         img = img.convert('L')
    53         img = np.array(img.getdata())
    54         X[0] = np.reshape(img,[self.height,self.width,1])/255.0
    55         for j,ch in enumerate(captcha_str):
    56             Y[0,j,self.characters.find(ch)] = 1
    57         Y = np.reshape(Y,(1,self.char_num*self.classes))
    58         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。

    调用这个类的时候会生成这样的验证码图片:

    第二步创建识别模型

    这里用到了 5 层网络,前 3 层为卷积层,第 4、5 层为全连接层。对 4 层隐藏层都进行 dropout。网络结构如下所示: input——>conv——>pool——>dropout——>conv——>pool——>dropout——>conv——>pool——>dropout——>fully connected layer——>dropout——>fully connected layer——>output

    主要代码(captcha_model.py):

     1 # -*- coding: utf-8 -*
     2 import tensorflow as tf
     3 import math
     4 
     5 class captchaModel():
     6     def __init__(self,
     7                  width = 160,
     8                  height = 60,
     9                  char_num = 4,
    10                  classes = 62):
    11         self.width = width
    12         self.height = height
    13         self.char_num = char_num
    14         self.classes = classes
    15 
    16     def conv2d(self,x, W):
    17         return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')  #步长是1,卷积的时候图片大小没有缩小。最大池化的时候图片减为一半。
    18 
    19     def max_pool_2x2(self,x):
    20         return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],                      #用2*2的过滤器
    21                               strides=[1, 2, 2, 1], padding='SAME')       #最大池化步长是2
    22 
    23     def weight_variable(self,shape):
    24         initial = tf.truncated_normal(shape, stddev=0.1)
    25         return tf.Variable(initial)
    26 
    27     def bias_variable(self,shape):
    28         initial = tf.constant(0.1, shape=shape)
    29         return tf.Variable(initial)
    30 
    31     def create_model(self,x_images,keep_prob):
    32         #first layer
    33         w_conv1 = self.weight_variable([5, 5, 1, 32])   #通过过滤器计算权重值5*5*32
    34         b_conv1 = self.bias_variable([32])               #32是[5,5,1,32]中的32的输出。a[1]=Relu(w[1]a[0]+b[1]),因为w[1]a[0]是32,矩阵相加。
    35         h_conv1 = tf.nn.relu(tf.nn.bias_add(self.conv2d(x_images, w_conv1), b_conv1))
    36         h_pool1 = self.max_pool_2x2(h_conv1)
    37         h_dropout1 = tf.nn.dropout(h_pool1,keep_prob)
    38         conv_width = math.ceil(self.width/2)
    39         conv_height = math.ceil(self.height/2)
    40 
    41         #second layer
    42         w_conv2 = self.weight_variable([5, 5, 32, 64])
    43         b_conv2 = self.bias_variable([64])
    44         h_conv2 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout1, w_conv2), b_conv2))
    45         h_pool2 = self.max_pool_2x2(h_conv2)
    46         h_dropout2 = tf.nn.dropout(h_pool2,keep_prob)
    47         conv_width = math.ceil(conv_width/2)
    48         conv_height = math.ceil(conv_height/2)
    49 
    50         #third layer
    51         w_conv3 = self.weight_variable([5, 5, 64, 64])
    52         b_conv3 = self.bias_variable([64])
    53         h_conv3 = tf.nn.relu(tf.nn.bias_add(self.conv2d(h_dropout2, w_conv3), b_conv3))
    54         h_pool3 = self.max_pool_2x2(h_conv3)
    55         h_dropout3 = tf.nn.dropout(h_pool3,keep_prob)
    56         conv_width = math.ceil(conv_width/2)
    57         conv_height = math.ceil(conv_height/2)
    58 
    59         #first fully layer
    60         conv_width = int(conv_width)
    61         conv_height = int(conv_height)
    62         w_fc1 = self.weight_variable([64*conv_width*conv_height,1024])  #64*20*8
    63         b_fc1 = self.bias_variable([1024])
    64         h_dropout3_flat = tf.reshape(h_dropout3,[-1,64*conv_width*conv_height])
    65         h_fc1 = tf.nn.relu(tf.nn.bias_add(tf.matmul(h_dropout3_flat, w_fc1), b_fc1))
    66         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
    67 
    68         #second fully layer
    69         w_fc2 = self.weight_variable([1024,self.char_num*self.classes])
    70         b_fc2 = self.bias_variable([self.char_num*self.classes])
    71         y_conv = tf.add(tf.matmul(h_fc1_drop, w_fc2), b_fc2)
    72 
    73         return y_conv

    第三步,有了样本和模型可以训练识别模型

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

    主要代码(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 
     8 if __name__ == '__main__':
     9     captcha = generate_captcha.generateCaptcha()
    10     width,height,char_num,characters,classes = captcha.get_parameter()
    11 
    12     x = tf.placeholder(tf.float32, [None, height,width,1]) #占位符
    13     y_ = tf.placeholder(tf.float32, [None, char_num*classes])
    14     keep_prob = tf.placeholder(tf.float32)
    15 
    16     model = captcha_model.captchaModel(width,height,char_num,classes)
    17     y_conv = model.create_model(x,keep_prob)
    18     cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y_,logits=y_conv))#將tensor取平均,第二個參數代表沿著那一維取平均
    19     train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)  #优化器
    20 
    21     predict = tf.reshape(y_conv, [-1,char_num, classes])    #y_conv通过模型获得的
    22     real = tf.reshape(y_,[-1,char_num, classes])
    23     correct_prediction = tf.equal(tf.argmax(predict,2), tf.argmax(real,2))
    24     correct_prediction = tf.cast(correct_prediction, tf.float32)
    25     accuracy = tf.reduce_mean(correct_prediction)
    26 
    27     saver = tf.train.Saver()
    28     with tf.Session() as sess:
    29         sess.run(tf.global_variables_initializer())
    30         step = 1
    31         while True:
    32             batch_x,batch_y = next(captcha.gen_captcha(64))
    33             _,loss = sess.run([train_step,cross_entropy],feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.75})
    34             print ('step:%d,loss:%f' % (step,loss))
    35             if step % 100 == 0:
    36                 batch_x_test,batch_y_test = next(captcha.gen_captcha(100))
    37                 acc = sess.run(accuracy, feed_dict={x: batch_x_test, y_: batch_y_test, keep_prob: 1.})
    38                 print ('###############################################step:%d,accuracy:%f' % (step,acc))
    39                 if acc > 0.99:                      #准确率
    40                     saver.save(sess,"capcha_model.ckpt")  #保存模型文件
    41                     break
    42             step += 1

    进行训练,查看训练过程(这里为了快速得到模型,我们将acc改的很小。训练模型也不准确):

    当训练好后会生成以下模型文件,其中checkpoint保存模型路劲和一些模型信息,方便下次训练:

    第四步,进行预测:

    主要代码(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 
    10 if __name__ == '__main__':
    11     captcha = generate_captcha.generateCaptcha()
    12     width,height,char_num,characters,classes = captcha.get_parameter()
    13 
    14     gray_image = Image.open('./captcha/0hwn.jpg').convert('L')        #要预测的验证码图片位置
    15 #     gray_image = Image.open(sys.argv[1]).convert('L')
    16     img = np.array(gray_image.getdata())
    17     test_x = np.reshape(img,[height,width,1])/255.0
    18     x = tf.placeholder(tf.float32, [None, height,width,1])
    19     keep_prob = tf.placeholder(tf.float32)
    20 
    21     model = captcha_model.captchaModel(width,height,char_num,classes)
    22     y_conv = model.create_model(x,keep_prob)
    23     predict = tf.argmax(tf.reshape(y_conv, [-1,char_num, classes]),2)
    24     init_op = tf.global_variables_initializer()
    25     saver = tf.train.Saver()
    26     gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.95)
    27     with tf.Session(config=tf.ConfigProto(log_device_placement=False,gpu_options=gpu_options)) as sess:
    28         sess.run(init_op)
    29         saver.restore(sess, "./capcha_model.ckpt")   #训练好模型文件的位置
    30         pre_list =  sess.run(predict,feed_dict={x: [test_x], keep_prob: 1})
    31         for i in pre_list:
    32             s = ''
    33             for j in i:
    34                 s += characters[j]
    35             print(s)

    查看结果:

    参考链接:

    https://xianzhi.aliyun.com/forum/topic/1470/

    https://xianzhi.aliyun.com/forum/topic/1505/

    https://xianzhi.aliyun.com/forum/topic/1552/

    https://cloud.tencent.com/developer/labs/lab/10325

    GitHub:https://github.com/Afant1
    不忘初心、方得始终
    Copyright@2021 Afant1
    [转载文章务必保留出处和署名,谢谢!]
  • 相关阅读:
    optparse--强大的命令行参数处理包
    B/S和C/S架构的区别
    Document
    Document
    Document
    Document
    Document
    Document
    Document
    Document
  • 原文地址:https://www.cnblogs.com/afanti/p/8030110.html
Copyright © 2011-2022 走看看