吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4750|回复: 17
收起左侧

[Python 转载] 使用深度学习模型进行图片验证码识别

[复制链接]
ljl9090 发表于 2021-10-2 22:56
[md]基于深度学习模型进行图片验证码识别(keras)目的:在登录网站,尤其使用爬虫工具时通常会遇到验证码,大多数时候都是使用第三方付费的接口识别验证码结果,
学习了深度学习后可以尝试自己训练一个验证码识别的模型。
过程:
# 1.构造数据集(这里通过python工具自行生成图片验证码)
### (1) 生成验证码训练、测试图片

                import string
                letters = string.digits+string.ascii_letters
                list_labels = [s for s in letters]


        def create_image_labels(path,num_img=100):
   
    width = 160
    height = 60
    for i in range(num_img):
        chars = ""
        for __ in range(4):
            chars += random.choice(list_labels)
        image = ImageCaptcha().generate_image(chars)
        img = image.convert('L')   #转化为灰度图
        resized_image = img.resize((width, height), Image.ANTIALIAS) #压缩图片

        files = path+str(i)+"_" +chars+".png"
        resized_image.save(files)
    print("bulid success")
                #create_image_labels("./image/",num_img=40000)
                #create_image_labels("./test/",num_img=100)

### (2)numpy整理图片数据
                def get_train_Dataset(file_name):
                        weight = 160
                        height = 60
                        files =os.listdir(file_name)
                        fileList = [file_name+"/"+f for f in files]
                        labels = []
                        x = np.zeros([len(fileList),height*weight])
                        dict_labels = {}
                        for index,label in enumerate(list_labels):
                                        dict_labels[label] = index

                        threshold = 195  #阈值
                        table = []
                        for i in range(256):
                                        if i < threshold:
                                                        table.append(0)
                                        else:
                                                        table.append(1)
                        for index,f_img in enumerate(fileList):
                                        #处理label
                                        label = f_img.split("_")[-1].split(".")[0]
                                        label_split = [dict_labels[la] for la in label]
                                        labels.append(label_split)
                                        #处理图片转换为为数组
                                        img = cv2.imread(f_img,cv2.IMREAD_GRAYSCALE)
                                        median = cv2.medianBlur(img, 5)
                                        image = Image.fromarray(cv2.cvtColor(median,cv2.COLOR_BGR2RGB))
                                        img= image.convert("L")  #灰度
                                        img = img.point(table, '1')  #二值化

                                        x_train = np.array(img).reshape(-1,height*weight)
                                        # x_shape = x_train.shape
                                        # x_train = x_train.reshape(x_shape[0]*x_shape[1],x_shape[2]).max(axis=1)
                                        # trian = x_train/255
                                        x[index,:] = x_train
### (3)可保存整理后的数据npz
        train_x,train_y = get_train_Dataset("./image")
        test_x,test_y = get_train_Dataset("./test")
        #保存为npz 文件(占用存储空间)
        np.savez('./image_train_and_test06.npz',train_x=train_x,train_y=train_y,test_x=test_x,test_y=test_y)


# 2.构造模型训练及保存模型参数
### (1)模块导入
        from keras.models import load_model
        import numpy as np
        from PIL import Image
        from keras.models import Model
        from keras.layers import Input,Dense,Convolution2D,MaxPooling2D,Flatten,Dropout
        from keras.optimizers import Adam
        from keras.utils import np_utils
        from keras.utils import plot_model
        #数据准备
        CLASS_NUM = 62
        weight = 160
        height = 60

        data = np.load("./image_train_and_test06.npz")
        X_train, X_test,y_train, y_test =data["train_x"],data["test_x"],data["train_y"],data["test_y"]
        
### (2)构建模型

#搭建网络模型,
        def main(X_train,y_train,epochs=50):
                        # 输入层
                        inputs = Input(shape=(height,weight,1))
                        x = inputs
                        x=Convolution2D(32,(3,3),activation='relu')(x)
                        x=Convolution2D(32,(3,3),activation='relu')(x)
                        x=MaxPooling2D((2,2))(x)
                        x=Dropout(0.5)(x)
                        x=Convolution2D(64,(3,3),activation='relu')(x)
                        x=Convolution2D(64,(3,3),activation='relu')(x)
                        x=MaxPooling2D((2,2))(x)
                        x=Dropout(0.5)(x)
                        x=Convolution2D(128,(3,3),activation='relu')(x)
                        x=MaxPooling2D((2,2))(x)

                        x=Flatten()(x)
                        x=Dropout(0.5)(x)
                        #卷积层及全连接层等相关层
                        x = Dense(1024, activation="relu")(x)

                        #多输出,定义两个输出,指定名字标识
                        fc_a=Dense(name='fc_a',units=CLASS_NUM,activation="softmax")(x)
                        fc_b=Dense(name='fc_b',units=CLASS_NUM,activation="softmax")(x)
                        fc_c=Dense(name='fc_c',units=CLASS_NUM,activation="softmax")(x)
                        fc_d=Dense(name='fc_d',units=CLASS_NUM,activation="softmax")(x)
                        #单输入多输出
                        model = Model(inputs=inputs, outputs=[fc_a, fc_b,fc_c,fc_d])

                        #目标函数定义,需与输出层名字对应
                        losses = {'fc_a': 'categorical_crossentropy',
                                                        'fc_b': 'categorical_crossentropy',
                                                        'fc_c': 'categorical_crossentropy',
                                                        'fc_d': 'categorical_crossentropy'}

                        model.compile(optimizer=Adam(0.00001,decay=1e-6,clipnorm=1.),
                                                                                        loss=losses,
                                                                                        metrics=['accuracy'])   
                        X_train = X_train.reshape(-1,height,weight,1)/255
                        y_train1 = np_utils.to_categorical(y_train[:,0],num_classes=CLASS_NUM)
                        y_train2 = np_utils.to_categorical(y_train[:,1],num_classes=CLASS_NUM)
                        y_train3 = np_utils.to_categorical(y_train[:,2],num_classes=CLASS_NUM)
                        y_train4 = np_utils.to_categorical(y_train[:,3],num_classes=CLASS_NUM)

                        model.fit(X_train,[y_train1,y_train2,y_train3,y_train4],epochs=epochs,batch_size=64,shuffle=True)
                        return model
### (3)保存,加载模型
        model = main(X_train,y_train,epochs=800)
        #画结构图
        #import os
        #os.environ["PATH"] += os.pathsep + 'D:/software/graph/bin/'
        #plot_model(model, to_file='./model4.png', show_shapes=True)
        #保存模型
         model.save("./my_morestring62_160_model04.h5")
        #加载模型
        #model = load_model("./my_morestring62_160_model04.h5")
![模型结构图](D:\study\jupyter_notebook\vgg.png)

# 3.预测
        import cv2
        def prep_image(path):
                #加载模型
                model = load_model("./my_morestring62_160_model04.h5")
    #img = Image.open(path)
    #img = img.resize((weight,height))
   
    threshold = 215  #阈值
    table = []
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    img = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
    median = cv2.medianBlur(result, 5)
    image = Image.fromarray(cv2.cvtColor(median,cv2.COLOR_BGR2RGB))
    img= image.convert("L")  #灰度
    img = img.point(table, '1')  #二值化
    img = img.resize((weight,height))
    X_test = np.array(img).reshape(-1,height*weight)
    X_test = X_test.reshape(-1,height,weight,1)/255
    prep1,prep2,prep3,prep4 = model.predict(X_test)
    prep = np.hstack((np.argmax(prep1,axis=1).reshape(-1,1),np.argmax(prep2,axis=1).reshape(-1,1),\
        np.argmax(prep3,axis=1).reshape(-1,1),np.argmax(prep4,axis=1).reshape(-1,1))).reshape(-1,4)
    import string
    letters = string.digits+string.ascii_letters
    list_labels = [s for s in letters]
    num_dicts = {}
    for index,label in enumerate(list_labels):
        num_dicts[index] = label

    new_labels = []
    for i in range(prep.shape[0]):
        labels = []
        for j in range(prep.shape[1]):
            labels.append(num_dicts[prep[i,j]])
        new_labels.append("".join(labels))
    return new_labels[0]
#result = prep_image("./vaild/0_t76j.png")
print(result)

模型结构图

模型结构图

免费评分

参与人数 4吾爱币 +4 热心值 +3 收起 理由
ma4907758 + 1 谢谢@Thanks!
chinawolf2000 + 1 + 1 热心回复!
lendone + 1 + 1 用心讨论,共获提升!
为之奈何? + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| ljl9090 发表于 2021-10-2 23:03
上面模型结构为vgg 网络结构(训练结果不是很理想)
应该为先这个模型结构图
model4.png
 楼主| ljl9090 发表于 2021-10-3 00:58
m58758788 发表于 2021-10-3 00:55
厉害了 可惜现在好多都是滑块 点选

现在很多第三方平台也支持点选的(使用 “图鉴“ 点选*06车票都不错;超级鹰也可以,不过要差一点),滑块可以模拟操作,或者逆向解析js,不过难度较大。
m58758788 发表于 2021-10-3 00:55
maqiao144 发表于 2021-10-3 08:08
第三方不知道行不行
chinasmu 发表于 2021-10-3 08:25
滑块点选的识别问题不大,难的是如何通过人机检测吧
 楼主| ljl9090 发表于 2021-10-3 11:33
chinasmu 发表于 2021-10-3 08:25
滑块点选的识别问题不大,难的是如何通过人机检测吧

对的,比如某宝的滑块很容易模拟,但是账号识别为不同等级就比较狠了
霸气侧漏m2 发表于 2021-10-3 16:15
牛逼,都用到深度学习了,大佬
chinavy 发表于 2021-10-3 22:28
厉害,感谢分享啊
风雨3137 发表于 2021-10-4 00:13
识别率怎么样?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 22:07

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表