深度学习卷积神经网络识别光学字符验证码,及captcha使用简单案例

深度学习卷积神经网络识别验证码

文章目录

  • 深度学习卷积神经网络识别验证码
    • 一、引言
    • 二、导入必要的库
    • 三、防止 tensorflow 占用所有显存
    • 四、定义数据生成器并测试
    • 五、定义网络结构
    • 六、训练模型
    • 七、测试模型

一、引言

验证码识别,本身使用来判断访问网站的用户是不是一个真人,但是随着人工智能的发展,尤其是深度卷积神经网络的发展,使得验证码识别机器还是人的底线再被层层攻破,本文所使用的captcha 可以生成语音和图片验证码,验证码是由数字、大写字母、小写字母组成,可以自动生成验证码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E7jq6PxI-1693272688113)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230828213513905.png)]

最好掌握的预备知识:

  • 有python脚本编程基础;
  • 了解图像处理、计算机视觉理论基础;
  • 对Opencv有一定的认识;
  • 对图像处理有操作经验;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6EZ6HRR7-1693272688114)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230828213911621.png)]
目的:通过Python语言与其各种资源库如numpy,pillow,tensorflow,keras等来实现。将效果实现出来。了解如何使用catptcha自动生成验证码数据,同时使用tensorflow撰写网络,来完成验证码训练,将使用高级框架的keras作为手写字母的网络主体。

二、导入必要的库

我们需要导入一个叫 captcha 的库来生成验证码。

我们生成验证码的字符由数字和大写字母组成。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xBRQPC1-1693272688115)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230828185346056.png)]

导入成功后,我们使用jupyter notebook编写代码,使用py3.6.9,TensorFlow2.0+

from captcha.image import ImageCaptcha
import matplotlib.pyplot as plt
import numpy as np
import random
import tensorflow as tf

%matplotlib inline
%config InlineBackend.figure_format = 'retina'

#输出所有的ascii,用来生成验证码
import string
characters = string.digits + string.ascii_uppercase
print(characters)

#验证码的长、宽、字符数、类别数
width, height, n_len, n_class = 128, 64, 4, len(characters)

输出结果:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

三、防止 tensorflow 占用所有显存

#下面就是实现按需分配的代码
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    try:
        #设置仅在需要时申请显存空间
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)
        logical_gpus = tf.config.experimental.list_logical_devices('GPU')
        print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
    except RuntimeError as e:
        print(e)

四、定义数据生成器并测试

from tensorflow.keras.utils import Sequence

class CaptchaSequence(Sequence):
    #这里传入的参数与上面的导入模块常量相对应
    def __init__(self, characters, batch_size, steps, n_len=4, width=128, height=64):
        self.characters = characters
        self.batch_size = batch_size
        self.steps = steps
        self.n_len = n_len
        self.width = width
        self.height = height
        self.n_class = len(characters)
        self.generator = ImageCaptcha(width=width, height=height)
    
    def __len__(self):
        return self.steps

    def __getitem__(self, idx):
        X = np.zeros((self.batch_size, self.height, self.width, 3), dtype=np.float32)
        y = [np.zeros((self.batch_size, self.n_class), dtype=np.uint8) for i in range(self.n_len)]
        for i in range(self.batch_size):
            random_str = ''.join([random.choice(self.characters) for j in range(self.n_len)])
            X[i] = np.array(self.generator.generate_image(random_str)) / 255.0
            for j, ch in enumerate(random_str):
                y[j][i, :] = 0
                y[j][i, self.characters.find(ch)] = 1
        return X, y

测试代码:

def decode(y):
    y = np.argmax(np.array(y), axis=2)[:,0]
    return ''.join([characters[x] for x in y])
#注意每次运行输出结果可能不同,因为我们每次随机选择一个字符
data = CaptchaSequence(characters, batch_size=1, steps=1)  
X, y = data[0]
plt.imshow(X[0])
plt.title(decode(y))

结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lx2zPpf-1693272688115)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230828214749531.png)]

注意:生成的验证码中字可能会出现不清晰的情况

例如这样:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w3VvkFwm-1693272688116)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230828191026978.png)]

总结原因可能有以下几点:

  1. 图片尺寸过小:在代码中,如果设置了验证码图片的宽度和高度为64和32,这可能导致生成的验证码图片较小,从而导致字体较小且不清晰。可以尝试增大图片尺寸,例如将宽度设置为128,高度设置为64。
  2. 图片缩放导致失真:在生成图片时,使用了np.array(self.generator.generate_image(random_str)) / 255.0 将图像转换为numpy数组并进行了归一化处理。如果在这个过程中对图像进行了缩放操作,可能会导致图像失真,从而影响字体的清晰度。可以尝试去除归一化处理,或者调整归一化的方式,确保图像不失真。
  3. 字体类型和大小:验证码生成器ImageCaptcha使用默认的字体类型和大小生成验证码。如果默认字体类型和大小不适合生成清晰的验证码,可以尝试更换字体类型并调整字体大小。可以参考ImageCaptcha的文档,了解如何更改字体类型和大小。
  4. 图像参数调整:除了上述因素外,还可以尝试调整一些图像生成的参数,例如干扰线的宽度、噪点的数量等,以提高验证码的清晰度。

五、定义网络结构

train_data = CaptchaSequence(characters, batch_size=512, steps=1000)
valid_data = CaptchaSequence(characters, batch_size=128, steps=100)
x_train, y_train = train_data[0]
x_val, y_val = valid_data[0]
from tensorflow.keras.models import *
from tensorflow.keras.layers import *

input_tensor = Input((height, width, 3))
x = input_tensor
for num_cnn,num_kernel in enumerate([32,16,8]):
    for j in range(num_cnn):
        x = Conv2D(num_kernel, kernel_size=(3,3), padding='same', kernel_initializer='he_uniform')(x)
        x = Conv2D(num_kernel, kernel_size=(3,3), padding='same')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = MaxPooling2D(pool_size=(2,2))(x)

x = Flatten()(x)
x = [Dense(n_class, activation='softmax',name='c%d'%(i+1))(x) for i in range(n_len)]
model = Model(inputs=input_tensor, outputs=x)
model.summary()

网络结构总结如下:

Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 64, 128, 3)] 0                                            
__________________________________________________________________________________________________
conv2d (Conv2D)                 (None, 64, 128, 16)  448         input_1[0][0]                    
__________________________________________________________________________________________________
conv2d_1 (Conv2D)               (None, 64, 128, 16)  2320        conv2d[0][0]                     
__________________________________________________________________________________________________
batch_normalization (BatchNorma (None, 64, 128, 16)  64          conv2d_1[0][0]                   
__________________________________________________________________________________________________
activation (Activation)         (None, 64, 128, 16)  0           batch_normalization[0][0]        
__________________________________________________________________________________________________
max_pooling2d (MaxPooling2D)    (None, 32, 64, 16)   0           activation[0][0]                 
__________________________________________________________________________________________________
conv2d_2 (Conv2D)               (None, 32, 64, 8)    1160        max_pooling2d[0][0]              
__________________________________________________________________________________________________
conv2d_3 (Conv2D)               (None, 32, 64, 8)    584         conv2d_2[0][0]                   
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 32, 64, 8)    32          conv2d_3[0][0]                   
__________________________________________________________________________________________________
activation_1 (Activation)       (None, 32, 64, 8)    0           batch_normalization_1[0][0]      
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D)  (None, 16, 32, 8)    0           activation_1[0][0]               
__________________________________________________________________________________________________
conv2d_4 (Conv2D)               (None, 16, 32, 8)    584         max_pooling2d_1[0][0]            
__________________________________________________________________________________________________
conv2d_5 (Conv2D)               (None, 16, 32, 8)    584         conv2d_4[0][0]                   
__________________________________________________________________________________________________
batch_normalization_2 (BatchNor (None, 16, 32, 8)    32          conv2d_5[0][0]                   
__________________________________________________________________________________________________
activation_2 (Activation)       (None, 16, 32, 8)    0           batch_normalization_2[0][0]      
__________________________________________________________________________________________________
max_pooling2d_2 (MaxPooling2D)  (None, 8, 16, 8)     0           activation_2[0][0]               
__________________________________________________________________________________________________
flatten (Flatten)               (None, 1024)         0           max_pooling2d_2[0][0]            
__________________________________________________________________________________________________
c1 (Dense)                      (None, 36)           36900       flatten[0][0]                    
__________________________________________________________________________________________________
c2 (Dense)                      (None, 36)           36900       flatten[0][0]                    
__________________________________________________________________________________________________
c3 (Dense)                      (None, 36)           36900       flatten[0][0]                    
__________________________________________________________________________________________________
c4 (Dense)                      (None, 36)           36900       flatten[0][0]                    
==================================================================================================
Total params: 153,408
Trainable params: 153,344
Non-trainable params: 64

六、训练模型

开始训练

from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.optimizers import Adam

callbacks = [EarlyStopping(patience=3), ModelCheckpoint('cnn_best.h5', save_best_only=True)]

model.compile(loss='categorical_crossentropy',
              optimizer=Adam(1e-3), 
              metrics=['accuracy'])
history = model.fit(x_train, y_train, epochs=100, validation_data=(x_val,y_val),callbacks=callbacks, verbose=1)

载入最好的模型继续训练一会

model.load_weights('cnn_best.h5')

callbacks = [EarlyStopping(patience=3),ModelCheckpoint('cnn_best.h5', save_best_only=True)]
#学习率降低,
model.compile(loss='categorical_crossentropy',
              optimizer=Adam(1e-4), 
              metrics=['accuracy'])
model.fit(x_train, y_train, epochs=100, validation_data=(x_val,y_val),callbacks=callbacks, verbose=1)

保存最好的模型

model.save('../cnn_best.h5')

七、测试模型

X, y = data[0]
y_pred = model.predict(X)
plt.title('real: %s pred:%s'%(decode(y), decode(y_pred)))
plt.imshow(X[0], cmap='gray')
plt.axis('off')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q0NnLMwd-1693272688117)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230828215633050.png)]

可见测试模型效果并不理想,因为我们的训练迭代次数少,网络结构简单,不过我们可以增加网络层数,调节网络参数然后重新训练一个更好的模型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/101551.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Linux]套接字通信

摘于https://subingwen.cn,作者:苏丙榅 侵删 文章目录 1. 套接字-socket1.1 概念1.2 网络协议1.3 socket编程1.3.1 字节序1.3.2 IP地址转换1.3.3 sockaddr 数据结构1.3.4 套接字函数 1.4 TCP通信流程1.4.1 服务器端通信流程1.4.2 客户端的通信流程 1.5 扩展阅读1.5.1 初始化套…

Ceph IO流程及数据分布

1. Ceph IO流程及数据分布 1.1 正常IO流程图 步骤: client 创建cluster handler。client 读取配置文件。client 连接上monitor,获取集群map信息。client 读写io 根据crshmap 算法请求对应的主osd数据节点。主osd数据节点同时写入另外两个副本节点数据。…

ModaHub魔搭社区:自动化机器学习神器Auto-Sklearn

Auto-Sklearn Auto-Sklearn是一个开源库,用于在 Python 中执行 AutoML。它利用流行的 Scikit-Learn 机器学习库进行数据转换和机器学习算法。 它是由Matthias Feurer等人开发的。并在他们 2015 年题为“efficient and robust automated machine learning 高效且稳健的自动…

CSS Flex布局

前言 Flex布局(弹性盒子布局) 是一种用于在容器中进行灵活和自适应布局的CSS布局模型。通过使用Flex布局,可以更方便地实现各种不同尺寸和比例的布局,使元素在容器内自动调整空间分配。 目录 容器属性 🍁display属性 &…

内网隧道代理技术(二十)之 CS使用HTTP代理上线不出网机器

CS使用HTTP代理上线不出网机器 CS工具自带上线不出网机器 如图A区域存在一台中转机器,这台机器可以出网,这种是最常见的情况。我们在渗透测试的过程中经常是拿下一台边缘机器,其有多块网卡,边缘机器可以访问内网机器,内网机器都不出网。这种情况下拿这个边缘机器做中转,…

从零开始的Hadoop学习(六)| HDFS读写流程、NN和2NN工作机制、DataNode工作机制

1. HDFS的读写流程(面试重点) 1.1 HDFS写数据流程 1.1.1 剖析文件写入 (1)客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。 &#x…

vscode远程调试php

使用vscode远程调试php的方法 1.安装remote ssh插件 2.连接服务器 可以点击左下角的绿色按钮,或者ctrlshiftp打开命令框输入remote ssh应该也有。 3.在服务器端vscode安装php debug插件 4.安装xdebug xdebug是用来调试php的软件,原本和vscode没什么关…

webrtc-m79-msvc编译H264

0 写在前面 本文主要参考:webrtc 4577版本vs编译_tusong86的博客-CSDN博客 4577也就是m93,由于源码版本的不同,可能存在一定的出入,可根据实际情况进行修改; 感谢作者的付出; 1 编译参数 powershell运…

【docker】运行redis

拉取redis镜像 有多种选择: redis(基础版)redis/redis-stack(包含redis stack server和RedisInsight)redis/redis-stack-server(仅包含redis stack server) docker pull redis docker pull r…

C语言——指针基本语法

概述 内存地址 在计算机内存中,每个存储单元都有一个唯一的地址(内存编号)。 通俗理解,内存就是房间,地址就是门牌号 指针和指针变量 指针(Pointer)是一种特殊的变量类型,它用于存储内存地址。 指针的实…

【混合时变参数系统参数估计算法】使用范数总和正则化和期望最大化的混合时变参数系统参数估计算法(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

图像处理简介

目录 基本术语 1 .图像(image) 1.1 像素(Pixel) 1.2 颜色深度(Color Depth) 1.3 分辨率(Resolution) 1.4 像素宽高比(Pixel Aspect Ratio) 1.5 帧率(FPS) 1.6 码率(BR) 1. …

Vue中如何为Echarts统计图设置数据

在前端界面接收后端数据后,将数据赋值给ECharts中的data时出现了,数据读取失败的问题(可能是由于数据渲染的前后顺序问题)。后通过如下方式进行了解决: 1、接下来将介绍UserController中的countUsers方法,…

Liunx系统编程:信号量

一. 信号量概述 1.1 信号量的概念 在多线程场景下,我们经常会提到临界区和临界资源的概念,如果临界区资源同时有多个执行流进入,那么在多线程下就容易引发线程安全问题。 为了保证线程安全,互斥被引入,互斥可以保证…

redis面试题二

redis如何处理已过期的元素 常见的过期策略 定时删除:给每个键值设置一个定时删除的事件,比如有一个key值今天5点过期,那么设置一个事件5点钟去执行,把它数据给删除掉(优点:可以及时利用内存及时清除无效数…

华为Mate60低调发布,你所不知道的高调真相?

华为Mate60 pro 这两天的劲爆新闻想必各位早已知晓,那就是华为Mate60真的来了!!!并且此款手机搭载了最新国产麒麟9000s芯片,该芯片重新定义了手机性能的巅峰。不仅在Geekbench测试中表现出色,还在实际应用…

CTFhub-SSRF-内网访问

CTFHub 环境实例 | 提示信息 http://challenge-8bf41c5c86a8c5f4.sandbox.ctfhub.com:10800/?url_ 根据提示,在url 后门添加 127.0.0.1/flag.php http://challenge-8bf41c5c86a8c5f4.sandbox.ctfhub.com:10800/?url127.0.0.1/flag.php ctfhub{a6bb51530c8f6be0…

基于深度学习的三维重建从入门实战教程 原理讲解 源码解析 实操教程课件下载

传统的重建方法是使用光度一致性等来计算稠密的三维信息。虽然这些方法在理想的Lambertian场景下,精度已经很高。 但传统的局限性,例如弱纹理,高反光和重复纹理等,使得重建困难或重建的结果不完整。 基于学习的方法可以引入比如镜面先验和反射先验等全局语义信息,使匹配…

elementui tree 层级过多时,高亮状态无法选满整行

问题: 如上图所示,官方的tree组件,在层级很多时 elementui -tree 的高亮状态并没有选中整行。 (衍生库 vue-easy-tree 也会出现此问题) 原因: (没有查看源码,只是根据dom简单定位…

Echart笔记

Echart笔记 柱状图带背景色的柱状图将X与Y轴交换制作为进度条 柱状图 带背景色的柱状图 将X与Y轴交换制作为进度条 //将X与Y轴交换制作为进度条 option { xAxis: {type: value,min:0,max:100,show:false,//隐藏x轴},yAxis: {type: category,data:[进度条],show:false,//隐…