06. 识别验证码逻辑

1. 验证码的识别案例分析

1.1. 识别原理分析(图)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.2. 处理数据 图片 标签文件

在这里插入图片描述

1.3. 识别验证码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4. 代码实现

1.4.1. 把验证码图片和标签值写入到tfrecords文件中(测试中发现了一个问题 dense tensor??)

import tensorflow as tf
import os
os.environ[‘TF_CPP_MIN_LOG_LEVEL’] = ‘2’

FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_string(“tfrecords_dir”, “./tfrecords/captcha.tfrecords”, “验证码tfrecords文件”)
tf.app.flags.DEFINE_string(“captcha_dir”, “…/data/Genpics/”, “验证码图片路径”)
tf.app.flags.DEFINE_string(“letter”, “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789”, “验证码字符的种类”)
tf.app.flags.DEFINE_integer(“sample_num”, 1263, “图片的样本数量”)
tf.app.flags.DEFINE_integer(“captcha_img_height”, 40, “验证码图片的高度”)
tf.app.flags.DEFINE_integer(“captcha_img_width”, 135, “验证码图片的宽度”)
tf.app.flags.DEFINE_integer(“captcha_img_channel”, 3, “验证码图片的通道(彩色图片还是黑白图片)”)

def dealwithlabel(label_str):

# 构建字符索引 {0:'A', 1:'B'......}
num_letter = dict(enumerate(list(FLAGS.letter)))

# 键值对反转 {'A':0, 'B':1......}
letter_num = dict(zip(num_letter.values(), num_letter.keys()))

print(letter_num)

# 构建标签的列表
array = []

# 给标签数据进行处理[[b"NZPP"]......]
for string in label_str:

    letter_list = []  # [1,2,3,4]

    # 修改编码,b'FVQJ'到字符串,并且循环找到每张验证码的字符对应的数字标记
    for letter in string.decode('utf-8'):
        letter_list.append(letter_num[letter])

    array.append(letter_list)

# [[13, 25, 15, 15], [22, 10, 7, 10], [22, 15, 18, 9], [16, 6, 13, 10], [1, 0, 8, 17], [0, 9, 24, 14].....]
print(array)

# 将array转换成tensor类型
label = tf.constant(array)

return label

def get_captcha_image():
“”"
获取验证码图片数据
file_list: 路径 +文件名列表
return: image
“”"
# 构造文件名
filename = []

for i in range(FLAGS.sample_num):
    string = str(i) + ".jpg"
    filename.append(string)

# 构造路径+文件
file_list = [os.path.join(FLAGS.captcha_dir, file) for file in filename]

# 构造文件队列
file_queue = tf.train.string_input_producer(file_list, shuffle=False)

# 构造阅读器
reader = tf.WholeFileReader()

# 读取图片数据内容
key, value = reader.read(file_queue)

# 解码图片数据
image = tf.image.decode_jpeg(value)

image.set_shape([FLAGS.captcha_img_height, FLAGS.captcha_img_width, FLAGS.captcha_img_channel])

# 批处理数据 [1263, 40, 135, 3]
image_batch = tf.train.batch([image], batch_size=FLAGS.sample_num, num_threads=1, capacity=6000)

return image_batch

def get_captcha_label():
“”"
读取验证码图片标签数据
:return: label
“”"
file_queue = tf.train.string_input_producer(["…/data/Genpics/labels.csv"], shuffle=False)

reader = tf.TextLineReader()

key, value = reader.read(file_queue)

records = [[1], ["None"]]

number, label = tf.decode_csv(value, record_defaults=records)

# [["NZPP"], ["WKHK"], ["ASDY"]]
label_batch = tf.train.batch([label], batch_size=6000, num_threads=1, capacity=6000)

return label_batch

def write_to_tfrecords(image_batch, label_batch):
“”"
将图片内容和标签写入到tfrecords文件当中
:param image_batch: 特征值
:param label_batch: 标签纸
:return: None
“”"
# 转换类型
label_batch = tf.cast(label_batch, tf.uint8)

print(label_batch)

# 建立TFRecords 存储器
writer = tf.python_io.TFRecordWriter(FLAGS.tfrecords_dir)

# 循环将每一个图片上的数据构造example协议块,序列化后写入
for i in range(1263):
    # 取出第i个图片数据,转换相应类型,图片的特征值要转换成字符串形式
    image_string = image_batch[i].eval().tostring()

    # 标签值,转换成相应的类型
    label_string = label_batch[i].eval().tostring()

    # 构造协议块
    example = tf.train.Example(features=tf.train.Features(feature={
        "image": tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_string])),
        "label": tf.train.Feature(bytes_list=tf.train.BytesList(value=[label_string]))
    }))

    writer.write(example.SerializeToString())

# 关闭文件
writer.close()

return None

if name == “main”:

# 获取验证码文件当中的图片
image_batch = get_captcha_image()

# 获取验证码文件当中的标签数据
label = get_captcha_label()

print(image_batch, label)

with tf.Session() as sess:

    coord = tf.train.Coordinator()

    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    # [b'NZPP' b'WKHK' b'WPSJ' ..., b'FVQJ' b'BQYA' b'BCHR']
    label_str = sess.run(label)

    print(label_str)

    # 处理字符串标签到数字张量
    label_batch = dealwithlabel(label_str)

    print(label_batch)

    # 将图片数据和内容写入到tfrecords文件当中
    write_to_tfrecords(image_batch, label_batch)

    coord.request_stop()

    coord.join(threads)

1.4.2. 训练模型

import tensorflow as tf

FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_string("captcha_dir", "./tfrecords_data/captcha.tfrecords", "验证码数据的路径")
tf.app.flags.DEFINE_integer("batch_size", 100, "每批次训练的样本数")
tf.app.flags.DEFINE_integer("letter_num", 26, "每个目标值取的字母的可能性")
tf.app.flags.DEFINE_integer("label_num", 4, "每个样本的目标值数量")



def weight_variables(shape):
    """定义一个初始化权重的函数
    """
    w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))
    return w


def bias_variables(shape):
    """定义一个初始化偏置的函数
    """
    b = tf.Variable(tf.constant(0.0, shape=shape))
    return b


def read_and_decode():
    """读取验证码数据API, 返回image_batch, label_batch
    """
    # 1. 构建文件队列
    file_queue = tf.train.string_input_producer([FLAGS.captcha_dir])
    # 2. 构建读取阅读器读取文件内容,默认一个样本
    reader = tf.TFRecordReader()
    key, value = reader.read(file_queue)
    # 3. 解析example
    features = tf.parse_single_example(value, features={
        "image":tf.FixedLenFeature([], tf.string),
        "label":tf.FixedLenFeature([], tf.string),
    } )

    # 4.  解码内容, 如果存取的格式是string类型的就需要解码,如果是int64,float32不需要解码
    image = tf.decode_raw(features['image'], tf.uint8)
    label = tf.decode_raw(features['label'], tf.uint8)
    print(image, label)
    # 改变形状
    image_reshape = tf.reshape(image, [20, 80, 3])
    label_reshape = tf.reshape(label, [FLAGS.label_num])
    print(image_reshape, label_reshape)
    
    # 进行批处理, 每批次
    image_batch, label_batch = tf.train.batch([image_reshape, label_reshape], batch_size=FLAGS.batch_size, num_threads=1, capacity=FLAGS.batch_size)
    print(image_batch, label_batch)
    return image_batch, label_batch


def fc_model(image):
    """进行预测结果
    参数:image: 100张图片的特征值[100, 20, 80, 3]
    返回值:y_predict[100, 4*26]预测值
    """
    with tf.variable_scope("model"):
        # 将图片数据形状转换成二维的形状
        image_reshape = tf.reshape(image, [-1, 20*80*3])
        # 随机初始化权重
        # matrix [100, 20*80*3] * [20*80*3, 4*26] +[4*26] = [100, 4*26]
        weights = weight_variables([20*80*3, FLAGS.label_num * FLAGS.letter_num])
        bias = bias_variables([FLAGS.label_num * FLAGS.letter_num])
        
        # 进行全连接层计算
        y_predict = tf.matmul(tf.cast(image_reshape,tf.float32), weights) + bias

    return y_predict


def predict_to_onehot(label): 
    """将读取文件中的目标值转换成one_hot编码
    参数:[100, 4] -----> onehot编码
    返回:onehot编码
    """
    # 进行onehot编码转换,提供给交叉熵损失和准确率的计算
    label_onehot = tf.one_hot(label, depth=FLAGS.letter_num, on_value=1.0, axis=2)
    print(label_onehot)
    return label_onehot


def captcharec():
    """验证码识别
    """
    # 1. 读取验证码文件
    image_batch, label_batch = read_and_decode()
    # 2. 通过输入图片特征数据, 建立模型, 得出预测结果
    # 一层全连接神经网络进行预测
    # matrix [100, 20*80*3] * [20*80*3, 4*26] +[4*26] = [100, 4*26]
    y_predict = fc_model(image_batch)
    print(y_predict)
    
    # 3. 先把目标值转换成one_hot编码
    y_true = predict_to_onehot(label_batch)
    
    # 4. softmax计算,交叉熵损失计算
    with tf.variable_scope("soft_cross"):
        # 求平均交叉熵损失,y_true[100, 4,26] -----> [100, 4*26]
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=tf.reshape(y_true,[-1, FLAGS.label_num * FLAGS.letter_num]), logits=y_predict))
       
    # 5. 梯度下降,优化损失
    with tf.variable_scope("optimizer"):
        train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
    
    # 求出样本每批次预测的准确率
    with tf.variable_scope("acc"):
        # 比较预测值和目标值位置是否一样(每个样本4个位置) y_predict[100, 4*26] -----> [100, 4, 26]
        equal_list = tf.equal(tf.argmax(y_true, 2), tf.argmax(tf.reshape(y_predict,[FLAGS.batch_size, FLAGS.label_num , FLAGS.letter_num]), 2))
        # equal_list None个样本[1,0,1,0,1,1........]
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
        
    init_op = tf.global_variables_initializer()
    # 开启会话变量
    with tf.Session() as sess:
        sess.run(init_op)
        
        # 定义线程协调器和开启线程
        coord = tf.train.Coordinator()
        # 开启线程去运行读取文件操作
        threads = tf.train.start_queue_runners(sess, coord=coord)
        # 训练识别程序
        for i in range(5000):
            sess.run(train_op)
            print("第{}批次的准确率为:{}".format(i , accuracy.eval()))
        
        # 回收线程
        coord.request_stop()
        coord.join(threads)
        
        
if __name__ == "__main__":
    captcharec()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值