tensorfolw_训练验证码

使用captcha.image.Image 生成随机验证码,随机生成的验证码为0到9的数字,验证码有4位数字组成,这是一个自己生成验证码,自己不断训练的模型

使用三层卷积层,三层池化层,二层全连接层来进行组合
导入库

import numpy as np  
import tensorflow.compat.v1 as tf
from captcha.image import ImageCaptcha
import numpy as np  
import matplotlib.pyplot as plt  
from PIL import Image  
import random   

1、定义生成随机验证码图片

number = ['0','1','2','3','4','5','6','7','8','9']
# alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
# ALPHABET = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']

def random_captcha_text(char_set=number, captha_size=4):
    captha_texts = []
    for i in range(captha_size):
        # 随机抽取数字,添加到列表中
        captha_texts.append(random.choice(char_set))
    return captha_texts

def gen_captcha_text_and_image():
    image = ImageCaptcha()
    captcha_texts = random_captcha_text()
    # 列表转换为字符串
    captcha_texts = ''.join(captcha_texts)
    # 产生图片
    captcha = image.generate(captcha_texts)
    captcha_image = Image.open(captcha)
    captcha_image = np.array(captcha_image)
    # 返回字符串和图片
    return captcha_texts, captcha_image

2、 生成训练样本

# 把彩图转换为灰度图
def convert2gray(image):
    if len(image.shape)> 2:
        grey = np.mean(image, -1)
        return grey
    else:
        return image
# 把文本转换为可用的标签维度是40
def text2vec(text):
    text_len = len(text)
    int(text[0])
    if text_len > MAX_CAPTCHA:
        raise ValueError('验证码最长4个字符')
    vec = np.zeros(MAX_CAPTCHA*CHAR_SET_LEN)
    for index, c in enumerate(text):

        now_index = index * CHAR_SET_LEN + int(c.strip())
        vec[now_index] = 1
    return vec
# 生成训练样本
def get_next_batch(batch_size=128):
    batch_x = np.zeros([batch_size, IMAGE_HEIGHT*IMAGE_WEIGHT])
    batch_y = np.zeros([batch_size, MAX_CAPTCHA*CHAR_SET_LEN])
    # 有时候生成的图像大小不是(60, 160, 3), 重新生成
    def wrap_gen_captcha_text_and_image():
        text, image = gen_captcha_text_and_image()
        while True:
            if image.shape == (60, 160, 3):
                return text, image

    for i in range(batch_size):
        text, image = wrap_gen_captcha_text_and_image()
        image = convert2gray(image)
        # 转换成的一维的灰度图,使得其范围为(0, 1)
        batch_x[i, :] = image.flatten() / 255  # (image.flatten()-128)/128  mean为0
       # 把输入的文本转换为标签类型
        batch_y[i, :] = text2vec(text)

    return batch_x, batch_y

3、 定义CNN,这里的CNN为3层卷积,3层池化, 2层全连接

# 定义CNN
def crack_captcha_cnn(w_alpha=0.01, b_alpha=0.1):
    # [-1, IMAGE_HEIGHT, IMAGE_WEIGHT, 1] -1表示batch_size,1表示样本深度,也就是RGB通道的个数 
    x = tf.reshape(X, [-1, IMAGE_HEIGHT, IMAGE_WEIGHT, 1])

    # 创建w_c1和b_c1的初始化变量
    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)

    # 第一个全连接层
    #8*20*64表示conv3的维度, 60/2/2/2 = 8 160/2/2/2=20 
    w_d = tf.Variable(w_alpha * tf.random_normal([8 * 20 * 64, 1024]))
    b_d = tf.Variable(b_alpha * tf.random_normal([1024]))
    dense = tf.reshape(conv3, [-1, w_d.get_shape().as_list()[0]])
    print(tf.matmul(dense, w_d).shape, b_d.shape)
    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_SET_LEN]))
    b_out = tf.Variable(b_alpha * tf.random_normal([MAX_CAPTCHA*CHAR_SET_LEN]))

    out = tf.add(tf.matmul(dense, w_out), b_out)
    return out

4、 定义训练CNN函数

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_SET_LEN])
    max_idx_p = tf.argmax(predict, 2)
    max_idx_l = tf.argmax(tf.reshape(Y, [-1, MAX_CAPTCHA, CHAR_SET_LEN]), 2)
    correct_pred = tf.equal(max_idx_p, max_idx_l)
    accr = 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
        # 让它一直都训练直到精度大于0.5
        while True:
            # 生成64个样本
            batch_x, batch_y = get_next_batch(batch_size=64)
            __, _loss = sess.run([optimizer, loss], feed_dict={X:batch_x, Y:batch_y, keep_prob: 0.75})
            print(step, _loss)

            # 每一百次循环计算一次返回值
            if step%100 == 0 :
                batch_text_x, batch_text_y = get_next_batch(batch_size=128)
                acc = sess.run(accr, feed_dict={X:batch_text_x, Y:batch_text_y, keep_prob:1.})
                print(acc)
                # 如果准确率大于0.5就保存模型
                if acc > 0.5:
                    saver.save(sess, '.model/crack_captcha/model')
                    break
            step += 1

5、定义训练好后的预测模型

# 用于训练好后的模型进行预测
def crack_captcha(captcha_image):
    
    output = crack_captcha_cnn()
    # 初始化保存数据
    saver = tf.train.Saver()
    with tf.Session() as sess:
        # 重新加载sess
        saver.restore(sess, '.model/crack_captcha/model')
        
        predict = tf.reshape(output, [-1, MAX_CAPTCHA, CHAR_SET_LEN], 2)
        # 获得CNN之后的结果
        text_list = sess.run(predict, feed_dict={X:[captcha_image], keep_prob:1})
        # 让输出结果变成一个列表
        text = text_list[0].tolist()
        return text

6、主要函数用来进行训练,或者测试

if __name__ == '__main__':
    #获得文本和图片
    train = 0
    # 当train=0时进行训练
    if train==0:
        number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        text, image = gen_captcha_text_and_image()

        IMAGE_HEIGHT = 60
        IMAGE_WEIGHT = 160
        MAX_CAPTCHA = len(text)
        print('验证码文本最长字符数', MAX_CAPTCHA)
        char_set = number
        CHAR_SET_LEN = len(char_set)

        X = tf.placeholder(tf.float32, [None, IMAGE_HEIGHT*IMAGE_WEIGHT])
        Y = tf.placeholder(tf.float32, [None, MAX_CAPTCHA*CHAR_SET_LEN])
        keep_prob = tf.placeholder(tf.float32)

        train_crack_captcha_cnn()
    # 当trian=1时进行测试    
    elif train == 1:
        text, image = gen_captcha_text_and_image()
        # 将模型转换为灰度图以后再进行测试
        image = convert2gray(image)
        image = image.flatten() / 255
        IMAGE_HEIGHT = 60
        IMAGE_WEIGHT = 160
        MAX_CAPTCHA = len(text)
        print('验证码文本最长字符数', MAX_CAPTCHA)
        char_set = number
        CHAR_SET_LEN = len(char_set)
        X = tf.placeholder(tf.float32, [None, IMAGE_HEIGHT * IMAGE_WEIGHT])
        Y = tf.placeholder(tf.float32, [None, MAX_CAPTCHA * CHAR_SET_LEN])
        keep_prob = tf.placeholder(tf.float32)
        pred_text = crack_captcha(image)
        print('真实值', text, '测试值', pred_text)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值