验证码进阶,TensorFlow--基于卷积神经网络的验证码识别

本人的第一个深度学习实战项目,参考了网络上诸多牛人的代码,在此谢过,因时间久已,不记出处,就不一一列出,罪过罪过。

我的数据集是我用脚本在网页上扒的,标签是用之前写的验证码识别方法打的。大概用了4000+多张图训练。

我的数据集都经过处理了,降噪,二值化,最后裁剪为18*60的大小,详细见我之前的验证码简单识别那篇随笔。

#coding:utf-8
import tensorflow as tf
from PIL import Image
import os
import random
import numpy as np

img_height = 18
img_width = 60
max_captcha = 4   #验证码长度
char_len =63    #用63个二进制数表示一个字符

def get_name_image():
    all_image = os.listdir('D:\sctest')
    random_file = random.randint(0,4000)
    base = os.path.basename('D:\sctest\\' + all_image[random_file])
    name = os.path.splitext(base)[0]
    image = Image.open('D:\sctest\\' + all_image[random_file])
    image = np.array(image)
    return name,image、
#我的标签就是图片名
#标签转成向量 def name2vec(name): vector = np.zeros(max_captcha*char_len) def char2pos(c): if c == '_': k = 62 return k k = ord(c) - 48 if k > 9: k = ord(c) - 55 if k > 35: k = ord(c) - 61 if k > 61: raise ValueError('No Map') return k for i, c in enumerate(name): idx = i * char_len + char2pos(c) vector[idx] = 1 return vector #将向量装成名字,也就是输出结果,最后预测的时候用到 def vec2name(vec): name = [] for i, c in enumerate(vec): char_idx = c % char_len if char_idx < 10: char_code = char_idx + ord('0') elif char_idx < 36: char_code = char_idx - 10 + ord('A') elif char_idx < 62: char_code = char_idx - 36 + ord('a') elif char_idx == 62: char_code = ord('_') else: raise ValueError('error') name.append(chr(char_code)) return "".join(name) def get_next_batch(batch_size=64): batch_x = np.zeros([batch_size, img_height*img_width]) batch_y = np.zeros([batch_size, max_captcha*char_len]) for i in range(batch_size): name, image = get_name_image() batch_x[i, :] = 1*(image.flatten()) batch_y[i, :] = name2vec(name) return batch_x, batch_y
X = tf.placeholder(tf.float32,[None,img_width*img_height]) Y = tf.placeholder(tf.float32,[None,max_captcha*char_len]) keep_prob = tf.placeholder(tf.float32) #CNN def crack_captcha_cnn(w_alpha=0.01,b_alpha=0.1): x = tf.reshape(X, shape=[-1, img_height, img_width, 1]) w_c1 = tf.Variable(w_alpha * tf.random_normal([3,3, 1, 32])) b_c1 = tf.Variable(b_alpha * tf.random_normal([32])) conv1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x, w_c1, strides=[1, 1, 1, 1], padding='SAME'), b_c1)) conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv1 = tf.nn.dropout(conv1, keep_prob) w_c2 = tf.Variable(w_alpha * tf.random_normal([3, 3, 32, 64])) b_c2 = tf.Variable(b_alpha * tf.random_normal([64 ])) conv2 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1, w_c2, strides=[1, 1, 1, 1], padding='SAME'), b_c2)) conv2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv2 = tf.nn.dropout(conv2, keep_prob) w_c3 = tf.Variable(w_alpha * tf.random_normal([3,3, 64, 64])) b_c3 = tf.Variable(b_alpha * tf.random_normal([64])) conv3 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2, w_c3, strides=[1, 1, 1, 1], padding='SAME'), b_c3)) conv3 = tf.nn.max_pool(conv3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv3 = tf.nn.dropout(conv3, keep_prob) w_d = tf.Variable(w_alpha * tf.random_normal([3 * 8 * 64, 1024])) b_d = tf.Variable(b_alpha * tf.random_normal([1024])) dense = tf.reshape(conv3,[-1, w_d.get_shape().as_list()[0]]) dense = tf.nn.relu(tf.add(tf.matmul(dense, w_d), b_d)) dense = tf.nn.dropout(dense, keep_prob) w_out = tf.Variable(w_alpha * tf.random_normal([1024, max_captcha * char_len])) b_out = tf.Variable(b_alpha * tf.random_normal([max_captcha * char_len])) out = tf.add(tf.matmul(dense, w_out), b_out) return out #训练 def train_crack_captcha_cnn(): output = crack_captcha_cnn() loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=output, labels=Y)) optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) predict = tf.reshape(output, [-1, max_captcha, char_len]) max_idx_p = tf.argmax(predict, 2) max_idx_l = tf.argmax(tf.reshape(Y, [-1, max_captcha, char_len]), 2) correct_pred = tf.equal(max_idx_p, max_idx_l) accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32)) saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) step = 0 while True: batch_x, batch_y = get_next_batch(64) _, loss_ = sess.run([optimizer, loss], feed_dict={X: batch_x, Y: batch_y, keep_prob: 0.5}) print(step, loss_) # 每100 step计算一次准确率 if step % 100 == 0: batch_x_test, batch_y_test = get_next_batch(100) acc = sess.run(accuracy, feed_dict={X: batch_x_test, Y: batch_y_test, keep_prob: 1.}) print(step, acc) # acc大于0.9999保存模型退出 if acc > 0.9999: saver.save(sess, "./crack_capcha.model", global_step=step) break step += 1 train_crack_captcha_cnn() #训练完成后注释掉train_crack_captcha_cnn()方法,跑下面的预测方法,进行预测。 def crack_captcha(): output = crack_captcha_cnn() saver = tf.train.Saver() with tf.Session() as sess: saver.restore(sess, tf.train.latest_checkpoint('.')) n = 1 while n <= 100: name, image = get_name_image() image = 1 * (image.flatten()) predict = tf.argmax(tf.reshape(output, [-1, max_captcha, char_len]), 2) name_list = sess.run(predict, feed_dict={X: [image], keep_prob: 1}) vec = name_list[0].tolist() predict_text = vec2name(vec) print("正确: {} 预测: {}".format(name, predict_text)) n += 1 crack_captcha()

跑了2800步,acc为1,又用1000多张图进行测试,有一张G,C识别错误。准确率在99.9%以上。