m0_74244443 2024-01-30 20:26 采纳率: 66.7%
浏览 3
已结题

python字符验证码自动识别


import os
from PIL import Image
import numpy as np
import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
train_data_dir = r'D:\test\python\machinelearning\tensorFlow20\深度学习与TF-PPT和代码\深度学习与TensorFlow入门实战-源码和PPT\lesson32-Keras实战\验证码\train'
test_data_dir = r'D:\test\python\machinelearning\tensorFlow20\深度学习与TF-PPT和代码\深度学习与TensorFlow入门实战-源码和PPT\lesson32-Keras实战\验证码\test'
model_dir = r'D:\test\python\machinelearning\tensorFlow20\深度学习与TF-PPT和代码\深度学习与TensorFlow入门实战-源码和PPT\lesson32-Keras实战\验证码\model.h5'

def denoising(image):
    """
    处理图片,方便更好识别,学习
    :param image:图片对象
    :return: 处理之后的图片
    """

    threshold = 128  # 通过设置阈值,去除不必要的干扰物

    for i in range(image.width):
        for j in range(image.height):
            r,g,b = image.getpixel((i,j))
            if (r > threshold or g >threshold or b > threshold):
                r=255
                g=255
                b=255
                image.putpixel((i,j),(r,g,b))
            else:
                r = 0
                g = 0
                b = 0
                image.putpixel((i, j), (r, g, b))

    # 灰度图片
    image = image.convert('L')
    return image

def gen_train_data(filePath):
    '''
       生成数据集
       :param filePath: 存filePath文件夹获取全部图片处理
       :return: x_data:图片数据,shape=(num, 20, 80),y_data:标签信息, shape=(num, 4)
       '''

    #返回指定的文件夹包含的文件或文件夹的名字的列表。
    train_file_name_list = os.listdir(filePath)
    # 返回值
    x_data = []
    y_data = []

    # 对每个图片单独处理
    for selected_train_file_name in train_file_name_list:
        if selected_train_file_name.endswith('.png'):

            # 获取图片对象
            captcha_image = Image.open(os.path.join(filePath, selected_train_file_name))

            # 对图片去噪,后面对这个方法单独说明
            captcha_image = denoising(captcha_image)
            # captcha_image = captcha_image.convert('L') # 对于简单的不用去噪,灰度反而更有利
            captcha_image_np = np.array(captcha_image)

            # 下面这两个是tensorflow获取图片信息,这里我们还是以上面为例
            # img = tf.io.read_file(os.path.join(filePath, selected_train_file_name))
            # img_np = tf.image.decode_jpeg(img, channels=0)

            img_np = np.array(captcha_image_np)
            # 把每个处理后的数据,塞进x_data,y_data
            x_data.append(img_np)
            y_data.append(np.array(list(selected_train_file_name.split('.')[0])).astype(np.int))

    x_data = np.array(x_data).astype(np.float)
    y_data = np.array(y_data)
    return x_data,y_data

# 生成训练集
(x,y) = gen_train_data(train_data_dir)
# 生成测试集
(x_test,y_test) = gen_train_data(test_data_dir)
print(x.shape,y.shape) #(num个图片验证码, 20宽, 80高) (955个图片验证码, 4)


def preprocess(x,y):
    """
    对x,y进行数据处理,转成tensor张量,小范围缩小在-1~1之间
    """
    x = 2*tf.cast(x,dtype=tf.float32)/255.-1
    x = tf.expand_dims(x,-1)
    y = tf.cast(y,dtype=tf.int32)
    return x,y


batch_size = 10
train_db = tf.data.Dataset.from_tensor_slices((x,y))
train_db = train_db.map(preprocess).batch(batch_size)

test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test))
test_db = test_db.map(preprocess).batch(1)


model = Sequential([
    # 第一个卷积层
    layers.Conv2D(32, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
    # layers.Dropout(0.25),
    # 第二个卷积层
    layers.Conv2D(64, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
    # layers.Dropout(0.25),
    layers.Flatten(),

    # 全连接
    layers.Dense(128),
    layers.Dense(40), # 因为这里我们4个数字,所以也就4*10可能性
    layers.Reshape([4,10])
])

model.build(input_shape=[None, 20, 80, 1])
model.summary()
# 设置学习率
optimizer = optimizers.Adam(lr=1e-3)


def train():
    global model
    # 如果存在模型,就拿以前的继续训练,不用再从头开始
    if os.path.exists(model_dir):
        model = tf.keras.models.load_model('model.h5', compile=False)

    # 进行20次重复训练
    for epoch in range(20):
        for step, (x, y) in enumerate(train_db):
            # 有的时候验证码不是这种格式,就没处理所以就不是的直接过滤
            if x.shape == (10, 20, 80, 1):
                with tf.GradientTape() as tape:
                    # logits
                    logits = model(x)
                    # 真实值就行one_hot编码来对比
                    y_onehot = tf.one_hot(y, depth=10)
                    # 设置loss
                    loss_ce = tf.losses.MSE(y_onehot, logits)
                    loss_ce = tf.reduce_mean(loss_ce)
                # 不断更新梯度
                grads = tape.gradient(loss_ce, model.trainable_variables)
                optimizer.apply_gradients(zip(grads, model.trainable_variables))

                if step % 10 == 0:
                    print(epoch, step, 'loss:', float(loss_ce))
    # 因为一次就已经很高了,所以直接保存模型
    model.save('model.h5')

def test():
    model = tf.keras.models.load_model('model.h5', compile=False)
    for step, (x, y) in enumerate(test_db):
        if x.shape == (1, 20, 80, 1):
            logits = model(x)
            logits = tf.nn.softmax(logits)
            pred = tf.cast(tf.argmax(logits,axis=2),dtype=tf.int32)
            print('预测值:',pred[0].numpy(),'真实值:',y[0].numpy(),'是否相同:',int(tf.reduce_sum(tf.cast(tf.equal(pred,y),dtype=tf.int32)))==4)

if __name__ == '__main__':

    #判断是否存在模型文件,没有则训练生成
    choice_flag = 1 # 0训练 1测试
    if os.path.exists(model_dir) and choice_flag==1:
        test()
    else:
        train()


以上是我参照的一个python字符验证码识别的源代码。能不能帮我看看我报错的这一步应该怎么写,⚽️⚽️了。

img

  • 写回答

2条回答 默认 最新

  • 专家-郭老师 Java领域新星创作者 2024-01-30 20:27
    关注

    参考通义千问和郭老师的小迷弟雅思莫了-编写提供,主要是为了帮助您快速解决问题,如下回答,您可以参考下,如有问题,评论区留言。

    在提供的代码中,您没有提及具体的错误信息。不过,我注意到一处可能存在问题的地方:在test()函数中,对预测值和真实值进行比较的逻辑可以稍作调整。请尝试将以下部分:

    pred = tf.cast(tf.argmax(logits,axis=2),dtype=tf.int32)
    print('预测值:',pred[0].numpy(),'真实值:',y[0].numpy(),'是否相同:',int(tf.reduce_sum(tf.cast(tf.equal(pred,y),dtype=tf.int32)))==4)
    

    修改为:

    pred = tf.cast(tf.argmax(logits, axis=1), dtype=tf.int32)  # 将axis从2改为1,因为我们需要针对每个字符(每列)找到最大概率
    correct_prediction = tf.equal(pred, y)
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, dtype=tf.float32))  # 计算准确率
    
    print('预测值:', pred.numpy()[0], '真实值:', y.numpy()[0], '是否正确:', int(accuracy * 4) == 4)  # 判断4个字符是否都预测正确
    

    同时,请确保y数据在生成测试集时已经被适当地转化为one-hot编码格式,因为在训练过程中模型是基于one-hot编码进行学习的。如果y_test不是one-hot编码,这里需要做相应处理。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 2月7日
  • 已采纳回答 1月30日
  • 创建了问题 1月30日

悬赏问题

  • ¥15 flink-sql-connector-rabbitmq使用
  • ¥15 zynq7015,PCIE读写延时偏大
  • ¥15 使用spss做psm(倾向性评分匹配)遇到问题
  • ¥20 vue+UEditor附件上传问题
  • ¥15 想做个WPS的自动化代码,不知道能做的起不。
  • ¥15 uniApp,生成安卓安卓包后,黑暗主题中间内容不生效,底部导航正常
  • ¥15 斯坦福自动漂移非线性模型反解
  • ¥15 学习Python如何找兼职
  • ¥15 python结合Matlab仿真忆阻器
  • ¥35 有人会注册whatsaop协议号吗?