PyTorch 和 CNN 的验证码识别系统实现

在本篇文章中,我们将介绍如何使用 PyTorch 和 卷积神经网络(CNN) 来实现一个验证码识别系统。验证码(CAPTCHA)通常由随机生成的字符组成,旨在防止自动化程序(如爬虫)进行恶意行为。我们将通过搭建一个深度学习模型,自动识别这些验证码中的字符。本文将覆盖数据预处理、模型设计、训练及评估的整个过程。

  1. 环境设置
    在开始之前,我们需要安装必要的库。以下命令安装了 PyTorch 和其他需要的库:

bash
更多内容访问ttocr.com或联系1436423940
pip install torch torchvision numpy matplotlib opencv-python pillow
PyTorch:用于构建和训练深度学习模型。
torchvision:提供数据加载和图像处理的工具。
OpenCV:用于图像处理。
Pillow:图像预处理。
2. 数据准备与预处理
验证码图像数据集通常由多个图像组成,每个图像包含一个文本字符串(例如“AB12”)。我们需要对图像进行以下几种处理:

图像灰度化:将彩色图像转换为灰度图。
图像尺寸调整:调整图像尺寸,使得输入到网络中的图像大小一致。
归一化处理:将图像像素值缩放至 [0, 1]。
(1) 数据集加载和预处理
首先,我们将通过定义一个自定义的 CaptchaDataset 类来加载和处理数据。我们将图像转换为灰度图,调整其大小,并进行归一化。

python

import os
import cv2
import numpy as np
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms

class CaptchaDataset(Dataset):
def init(self, image_dir, char_set, transform=None):
self.image_dir = image_dir
self.image_paths = [os.path.join(image_dir, fname) for fname in os.listdir(image_dir)]
self.char_set = char_set
self.transform = transform

def __len__(self):
    return len(self.image_paths)

def __getitem__(self, idx):
    img_path = self.image_paths[idx]
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    label = os.path.basename(img_path).split('.')[0]  # 获取图像文件名作为标签

    # 将标签编码为数字
    label_encoded = [self.char_set.index(c) for c in label]

    # 应用预处理
    if self.transform:
        img = self.transform(img)

    return img, np.array(label_encoded)

图像预处理和数据增强

transform = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((64, 128)), # 调整图像大小
transforms.ToTensor(),
transforms.Normalize(mean=[0.5], std=[0.5]), # 灰度图像的归一化
])

定义字符集

char_set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" # 可识别的大写字母和数字
dataset = CaptchaDataset("captcha_images", char_set, transform=transform)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
(2) 标签编码
每个验证码标签都需要被编码为整数列表。例如,标签 "AB12" 会被编码为 [0, 1, 2, 3],其中每个字符对应 char_set 中的位置。

  1. 构建卷积神经网络(CNN)
    为了进行验证码识别,我们将构建一个简单的卷积神经网络(CNN)。CNN 模型擅长从图像中提取空间特征,特别适用于图像分类任务。

(1) CNN 模型设计
python

import torch
import torch.nn as nn
import torch.optim as optim

class CaptchaCNN(nn.Module):
def init(self, num_classes):
super(CaptchaCNN, self).init()

    # 卷积层1
    self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
    self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
    self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)

    # 池化层
    self.pool = nn.MaxPool2d(2, 2)
    
    # 全连接层
    self.fc1 = nn.Linear(128 * 8 * 16, 512)
    self.fc2 = nn.Linear(512, num_classes)

def forward(self, x):
    x = self.pool(torch.relu(self.conv1(x)))
    x = self.pool(torch.relu(self.conv2(x)))
    x = self.pool(torch.relu(self.conv3(x)))
    x = x.view(-1, 128 * 8 * 16)  # 扁平化
    x = torch.relu(self.fc1(x))
    x = self.fc2(x)
    return x

(2) 网络结构解释
卷积层(Conv2D):这些层负责提取图像的局部特征,如字符的边缘、角落和线条。
池化层(MaxPool2D):用于降低图像的尺寸,从而减少计算复杂度,同时保留最重要的特征。
全连接层(Fully Connected):将卷积层提取到的特征进行分类。
4. 模型训练
在构建完模型后,我们需要定义损失函数和优化器,并通过训练数据来训练模型。

(1) 定义损失函数与优化器
python

创建CNN模型

num_classes = len(char_set) # 分类数等于字符集的大小
model = CaptchaCNN(num_classes=num_classes)

定义损失函数:多分类交叉熵损失

criterion = nn.CrossEntropyLoss()

优化器:Adam优化器

optimizer = optim.Adam(model.parameters(), lr=0.001)
(2) 训练过程
python

训练模型

num_epochs = 10

for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for i, (inputs, labels) in enumerate(dataloader):
inputs = inputs.unsqueeze(1) # 增加通道维度
labels = torch.tensor(labels)

    optimizer.zero_grad()

    # 前向传播
    outputs = model(inputs)

    # 计算损失
    loss = criterion(outputs, labels)
    
    # 反向传播
    loss.backward()
    optimizer.step()

    running_loss += loss.item()

print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(dataloader):.4f}')
  1. 模型评估
    训练完成后,我们需要在测试集上评估模型的性能。下面的代码展示了如何计算模型的准确性。

(1) 模型评估
python

def evaluate_model(model, dataloader):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in dataloader:
inputs = inputs.unsqueeze(1) # 增加通道维度
labels = torch.tensor(labels)

        # 前向传播
        outputs = model(inputs)
        _, predicted = torch.max(outputs, 1)
        
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

accuracy = 100 * correct / total
print(f'Accuracy: {accuracy:.2f}%')

假设你有一个测试集 DataLoader

test_dataloader = DataLoader(dataset, batch_size=32, shuffle=False)
evaluate_model(model, test_dataloader)
6. 优化与改进
如果模型表现不理想,可以通过以下方法进行改进:

数据增强:可以通过旋转、平移、缩放、翻转等技术来增强训练数据集。
调整网络架构:增加更多的卷积层、池化层或全连接层,提升模型的学习能力。
调整超参数:如学习率、批次大小等,可以根据实际训练情况进行调节。

posted @   ttocr、com  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示