使用CNN进行验证码识别:深度学习与图像预处理教程

验证码(CAPTCHA)广泛用于区分人类和自动化程序(如机器人),通常由扭曲的字母、数字或符号组成。为了实现验证码的自动识别,深度学习尤其是卷积神经网络(CNN)非常有效。本文将带你一起使用CNN构建一个验证码识别模型,并应用图像预处理技术来优化训练数据。
在这里插入图片描述
在这里插入图片描述

1. 预处理验证码图像

在训练模型之前,我们需要对图像进行一些预处理操作,以便让CNN能够更好地学习图像特征。以下是常见的图像预处理步骤:

  • 自适应阈值化:根据图像周围的区域动态确定阈值,适合处理光照不均的图像。
  • 形态学操作:如膨胀(Dilation)和腐蚀(Erosion),可以帮助去除噪声和连接断裂的字符。
  • 高斯模糊:去除图像中的噪声,平滑图像。

1.1 自适应阈值化

自适应阈值化是通过计算图像中每个小区域的均值或加权均值来确定该区域的阈值。这使得我们能更好地处理亮度不均的图像。

import cv2
import matplotlib.pyplot as plt

path1 = './samples/23n88.png'
path2 = './samples/23mdg.png'

# 读取图像
img1 = cv2.imread(path1, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(path2, cv2.IMREAD_GRAYSCALE)

# 自适应阈值化
thresh_img1 = cv2.adaptiveThreshold(img1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 145, 0)
thresh_img2 = cv2.adaptiveThreshold(img2, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 145, 0)

# 显示阈值化结果
plt.figure(figsize=(20,5))
plt.subplot(1, 2, 1)
plt.imshow(thresh_img1, cmap='gray')
plt.subplot(1, 2, 2)
plt.imshow(thresh_img2, cmap='gray')
plt.show()

1.2 形态学操作(闭运算)

闭运算是先进行膨胀操作,然后进行腐蚀操作,主要用于去除小的噪点并填补字符中的小空洞。

# 形态学操作:闭运算
close_img1 = cv2.morphologyEx(thresh_img1, cv2.MORPH_CLOSE, np.ones((5,2), np.uint8))
close_img2 = cv2.morphologyEx(thresh_img2, cv2.MORPH_CLOSE, np.ones((5,2), np.uint8))

# 显示闭运算后的结果
plt.figure(figsize=(20,5))
plt.subplot(1, 2, 1)
plt.imshow(close_img1, cmap='gray')
plt.subplot(1, 2, 2)
plt.imshow(close_img2, cmap='gray')
plt.show()

1.3 膨胀操作

膨胀操作通过使用一个结构化元素对图像进行扫描,选择局部区域的最大值,通常用于扩展白色区域。

# 膨胀操作
dilate_img1 = cv2.dilate(close_img1, np.ones((2,2), np.uint8), iterations=1)
dilate_img2 = cv2.dilate(close_img2, np.ones((2,2), np.uint8), iterations=1)

# 显示膨胀后的结果
plt.figure(figsize=(20,5))
plt.subplot(1, 2, 1)
plt.imshow(dilate_img1, cmap='gray')
plt.subplot(1, 2, 2)
plt.imshow(dilate_img2, cmap='gray')
plt.show()

1.4 高斯模糊

高斯模糊有助于去除图像中的噪点,使图像更加平滑。

# 高斯模糊
gauss_img1 = cv2.GaussianBlur(dilate_img1, (1,1), 0)
gauss_img2 = cv2.GaussianBlur(dilate_img2, (1,1), 0)

# 显示模糊后的结果
plt.figure(figsize=(20,5))
plt.subplot(1, 2, 1)
plt.imshow(gauss_img1, cmap='gray')
plt.subplot(1, 2, 2)
plt.imshow(gauss_img2, cmap='gray')
plt.show()

1.5 将图像切割成小块

由于验证码通常包含多个字符,我们需要将每个字符切割出来作为模型的输入。这里,我们将图像分割成多个小块。

# 切割图像
image_list1 = [gauss_img1[10:50, 30:50], gauss_img1[10:50, 50:70], gauss_img1[10:50, 70:90], gauss_img1[10:50, 90:110], gauss_img1[10:50, 110:130]]
image_list2 = [gauss_img2[10:50, 30:50], gauss_img2[10:50, 50:70], gauss_img2[10:50, 70:90], gauss_img2[10:50, 90:110], gauss_img2[10:50, 110:130]]

# 显示切割结果
plt.figure(figsize=(20,5))
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(image_list1[i], cmap='gray')
plt.show()

2. 构建卷积神经网络(CNN)

接下来,我们将使用卷积神经网络(CNN)进行字符识别。CNN对于图像分类任务非常有效,因为它能够自动提取图像特征。

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, BatchNormalization, Dropout

def cnn_model(input_shape, num_classes):
    model = Sequential()
    model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=input_shape))
    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))

    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))

    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(num_classes, activation='softmax'))

    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
    return model

# 创建模型
model = cnn_model((40, 20, 1), 19)  # 假设有19个类
model.summary()

3. 数据增强与过采样

3.1 SMOTE

SMOTE(合成少数类过采样技术)可以帮助我们增加少数类的样本量,以解决类别不平衡的问题。

from imblearn.over_sampling import SMOTE

# 假设 X_train 和 y_train 是训练集和标签
X_train = np.reshape(X_train, (4160, 40*20*1))  # 扁平化图像
X_train, y_train = SMOTE(sampling_strategy='auto', random_state=1).fit_resample(X_train, y_train)

X_train = np.reshape(X_train, (8037, 40, 20, 1))  # 恢复图像形状

3.2 使用 ImageDataGenerator 进行图像数据增强

数据增强可以生成更多样化的训练数据,从而帮助模型泛化能力的提升。

from keras.preprocessing.image import ImageDataGenerator

# 定义数据增强
traingen = ImageDataGenerator(rotation_range=5, width_shift_range=[-2, 2])
traingen.fit(X_train)

# 使用生成器
train_set = traingen.flow(X_train, y_train)

4. 模型训练与评估

我们可以使用Keras的ModelCheckpointReduceLROnPlateau回调来保存最佳模型,并在训练过程中调整学习率。

from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau

checkp = ModelCheckpoint('./captcha_model.h5', monitor='val_loss', save_best_only=True)
reduce = ReduceLROnPlateau(monitor='val_loss', patience=20, verbose=1)

history = model.fit(traingen.flow(X_train, y_train, batch_size=32

), validation_data=(X_test, y_test), epochs=10, callbacks=[checkp, reduce])

5. 测试与预测

训练完成后,我们可以用测试集进行评估,并通过model.predict()进行预测。

# 加载最佳模型
model = load_model('./captcha_model.h5')

# 预测
pred = model.predict(X_test)
pred = np.argmax(pred, axis=1)

# 打印准确率和分类报告
from sklearn.metrics import accuracy_score, classification_report
print('Accuracy:', accuracy_score(y_test, pred))
print(classification_report(y_test, pred))

6. 测试样本

我们还可以使用训练好的模型对一些新的验证码样本进行预测。

def get_demo(img_path):
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    img = t_img(img)
    img = c_img(img)
    img = d_img(img)
    img = b_img(img)
    
    image_list = [img[10:50, 30:50], img[10:50, 50:70], img[10:50, 70:90], img[10:50, 90:110], img[10:50, 110:130]]
    Xdemo = np.array([img_to_array(Image.fromarray(img)) for img in image_list]) / 255.0
    
    ydemo = model.predict(Xdemo)
    ydemo = np.argmax(ydemo, axis=1)
    
    for res in ydemo:
        print(info[res])
    print(img_path[-9:])

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

总结

通过图像预处理技术、数据增强、以及卷积神经网络的结合,我们可以构建一个高效的验证码识别系统。在实际应用中,可以根据具体的验证码类型调整预处理和模型参数,以提高准确性和泛化能力。

需要数据集的添加

在这里插入图片描述

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

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

相关文章

基于 Python Django 的二手房间可视化系统分析

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

探索 Sentinel 服务容错

Sentinel 是阿里巴巴开源的一款高可用防护组件,主要用于分布式系统中的流量控制、熔断降级和系统负载保护。它在 Java 微服务架构中扮演着重要的角色,帮助开发者确保系统的稳定性和可靠性。 以下是 Sentinel 的一些关键特性: 流量控制(Flow Control):通过对请求进行限流…

DBeaver 连接 OceanBase Oracle 租户

DBeaver 是一款通用的数据库工具软件,支持任何具有JDBC驱动程序的数据库。DBeaver 需要 Java 运行环境的支持。截稿时 DBeaver 24.0.0 版本默认提供的 OceanBase 驱动是连接 MySQL 的,想连接 Oracle 租户需要新建一个驱动器使用。 下载数据库驱动包 1、…

Dubbo 3.x源码(24)—Dubbo服务引用源码(7)接口级服务发现订阅refreshInterfaceInvoker

基于Dubbo 3.1,详细介绍了Dubbo服务的发布与引用的源码。 此前我们学习了Dubbo3.1版本的MigrationRuleHandler这个处理器,它用于通过动态更改规则来控制迁移行为。MigrationRuleListener的onrefer方法是Dubbo2.x 接口级服务发现与Dubbo3.x应用级服务发现…

企业如何提高招聘能力?

企业如何提高招聘能力? 许多企业在进行招聘工作时,常常会遇到各种问题和挑战。尽管付出了大量的时间和精力,但结果却并不总是如人意。例如,企业可能会经历一次又一次的面试,却仍然找不到一个能够适应岗位要求的合适人…

JAVA:探索 EasyExcel 的技术指南

1、简述 在 Java 开发中,Excel 文件的读写操作是一项常见的需求。阿里巴巴开源的 EasyExcel 提供了一种高效、简洁的解决方案,特别是在处理大规模数据时表现尤为突出。本文将详细介绍 EasyExcel 的优缺点、应用场景,并通过实例展示其基本用法…

AI制作ppt

1,kimi: 实际上也是AiPPT.cn这个网站(但是有实际次数限制) 2,其余专业AI ppt生成网站: (1)gamma:https://gamma.app/ 大概能制作7~10页左右 free的ppt,其余要…

穿越数据迷宫:C++哈希表的奇幻旅程

文章目录 前言📔一、unordered系列关联式容器📕1.1 unordered 容器概述📕1.2 哈希表在 unordered 容器中的实现原理📕1.3 unordered 容器的特点 📔二、unordered_set 和 unordered_map 的基本操作📕2.1 un…

数据结构 -二叉搜索树

一.什么是二叉搜索树 树插入删除方便比线性数组 二.二叉搜索树的查找操作 尾递归可以用循环递归 三.二叉树的插入操作 35要挂在33上面必须记住33的位置 解决方法,要求递归函数返回一个 结点插到33的右子树 四.二叉搜索树的删除 要是删除的是叶子节点之间删除 只有一…

计算机三级 数据库技术

第一章 数据库应用系统开发方法 1.1 数据库应用系统生命周期 软件工程:软件工程的思想,即用工程的概念、原理、技术和方法对软件生产、开发的全过程进行跟踪和管理 软件开发方法:瀑布模型、快速原型模型、螺旋模型 DBAS生命周期模型 1.2 规划与分析 系统规划与定…

使用 AMD GPU 推理 Mixtral 8x22B

Inferencing with Mixtral 8x22B on AMD GPUs — ROCm Blogs 2024年5月1日,由 Clint Greene撰写。 简介 自从Mistral AI’s AI发布了Mixtral 8x7B以来,专家混合(MoE)在AI社区重新获得了关注。受此发展启发,多个AI公…

前后端、网关、协议方面补充

这里写目录标题 前后端接口文档简介前后端视角对于前端对于后端代码注册路由路由处理函数 关于httpGET/POST底层网络关于前端的获取 路由器网关路由器的IP简介公网IP(WAN IP)私网IP(LAN IP)无线网络IP(WIFI IP)查询路由器私网IP路由器公网IP LAN口与WIFI简介基本原理 手动配置电…

leetcode104:二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3示例 2: 输入:root [1,null,2] 输出…

大语言模型理论基础

文章目录 前言大语言模型必需知识概述大语言模型目标模型上下文神经网络的神经元常见激活函数SigmoidTanhRelusoftmax 通用近似定理多层感知机(MLP)拟合最后 前言 你好,我是醉墨居士,我们接下来对大语言模型一探究竟,…

关于VUE NPM安装失败的问题

最近使用 npm install --registryhttps://registry.npmmirror.com 安装一个新项目的依赖,各种失败。 最后发现是package-lock里面有老的淘宝的域名,整体替换掉就行了

【数据结构】宜宾大学-计院-实验七

实验七 二叉树 一、实验目的:二、实验内容:三、实验结果:1,2;3,4,5;6.数组顺序存储的优缺点二叉链表存储的优缺点 一、实验目的: 掌握二叉树的顺序存储结构 掌握二叉树的链式存储结构 二、实验内容: 1&am…

游戏如何应对内存修改

据观察,近年来游戏黑灰产攻击角度多样化趋势显著,主要面临工作室、定制注入挂、模拟点击挂、内存修改挂、破解版等多方面安全问题。 据FairGuard数据统计,在游戏面临的众多安全风险中,「内存修改」攻击占比约为13%,主…

git重置的四种类型(Git Reset)

git区域概念 1.工作区:IDEA中红色显示文件为工作区中的文件 (还未使用git add命令加入暂存区) 2.暂存区:IDEA中绿色(本次还未提交的新增的文件显示为绿色)或者蓝色(本次修改的之前版本提交的文件但本次还未提交的文件显示为蓝色)显示的文件为暂存区中的文件(使用了…

Clickhouse集群新建用户、授权以及remote权限问题

新建用户 create user if not exists user on cluster 集群名称 IDENTIFIED WITH plaintext_password BY 密码;给用户授查询、建表、删表的权限 GRANT create table,select,drop table ON 数据库实例.* TO user on cluster 集群名称 ;再其他节点下用户建本地表成功&#…

Exploring Defeasible Reasoning in Large Language Models: A Chain-of-Thought A

文章目录 题目摘要简介准备工作数据集生成方法实验结论 题目 探索大型语言模型中的可废止推理:思路链 论文地址:http://collegepublications.co.uk/downloads/LNGAI00004.pdf#page136 摘要 许多大型语言模型 (LLM) 经过大量高质量数据语料库的训练&…