ljl9090 发表于 2021-10-2 22:56

使用深度学习模型进行图片验证码识别

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

                import string
                letters = string.digits+string.ascii_letters
                list_labels =


      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 =
                        labels = []
                        x = np.zeros()
                        dict_labels = {}
                        for index,label in enumerate(list_labels):
                                        dict_labels = 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(".")
                                        label_split = 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*x_shape,x_shape).max(axis=1)
                                        # trian = x_train/255
                                        x = 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=)

                        #目标函数定义,需与输出层名字对应
                        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,,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 =
    num_dicts = {}
    for index,label in enumerate(list_labels):
      num_dicts = label

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

ljl9090 发表于 2021-10-2 23:03

上面模型结构为vgg 网络结构(训练结果不是很理想)
应该为先这个模型结构图

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

牛逼{:301_993:},都用到深度学习了,大佬{:301_995:}

chinavy 发表于 2021-10-3 22:28

厉害,感谢分享啊

风雨3137 发表于 2021-10-4 00:13

识别率怎么样?
页: [1] 2
查看完整版本: 使用深度学习模型进行图片验证码识别