用PyTorch实现图像验证码识别

本篇文章将从数据生成、模型搭建到模型训练与测试,完整实现一个基于PyTorch的图像验证码识别项目。

  1. 安装依赖
    首先安装必要的Python库:
    pip install torch torchvision pillow captcha numpy2. 生成验证码数据
    我们使用​​captcha​​库生成训练数据,字符集包括数字和大写字母。
    from captcha.image import ImageCaptcha
    import os
    import random
    import string
    更多内容访问ttocr.com或联系1436423940
    characters = string.digits + string.ascii_uppercase
    captcha_length = 4
    width, height = 160, 60

def generate_captchas(num_images=10000, save_dir="captchas"):
os.makedirs(save_dir, exist_ok=True)
generator = ImageCaptcha(width=width, height=height)
for i in range(num_images):
label = ''.join(random.choices(characters, k=captcha_length))
img = generator.generate_image(label)
img.save(os.path.join(save_dir, f"{label}_{i}.png"))

generate_captchas()3. 定义数据集类
创建一个自定义的PyTorch数据集类,用于读取和处理图像与标签。
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import torch

class CaptchaDataset(Dataset):
def init(self, root_dir):
self.root_dir = root_dir
self.image_files = os.listdir(root_dir)
self.transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
self.char_to_idx = {ch: idx for idx, ch in enumerate(characters)}

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

def __getitem__(self, idx):
    img_name = self.image_files[idx]
    label_str = img_name.split('_')[0]
    img_path = os.path.join(self.root_dir, img_name)
    image = Image.open(img_path).convert('RGB')
    image = self.transform(image)
    label = torch.tensor([self.char_to_idx[c] for c in label_str], dtype=torch.long)
    return image, label

dataset = CaptchaDataset("captchas")
data_loader = DataLoader(dataset, batch_size=64, shuffle=True)4. 构建识别模型
模型使用卷积神经网络提取特征,再用LSTM处理字符序列。
import torch.nn as nn

class CaptchaRecognizer(nn.Module):
def init(self):
super(CaptchaRecognizer, self).init()
self.cnn = nn.Sequential(
nn.Conv2d(3, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(64, 128, 3, padding=1), nn.ReLU(),
nn.MaxPool2d((2,1))
)
self.rnn = nn.LSTM(128 * 7, 128, num_layers=2, bidirectional=True, batch_first=True)
self.fc = nn.Linear(256, len(characters))

def forward(self, x):
    x = self.cnn(x)
    x = x.permute(0, 3, 1, 2)  # B, W, C, H
    B, W, C, H = x.size()
    x = x.view(B, W, C*H)
    x, _ = self.rnn(x)
    x = self.fc(x)
    return x5. 模型训练

定义损失函数和优化器,开始训练。
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = CaptchaRecognizer().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

for epoch in range(20):
model.train()
total_loss = 0
for images, labels in data_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = sum(criterion(outputs[:, i, :], labels[:, i]) for i in range(captcha_length))
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {total_loss:.4f}")6. 测试识别效果
编写预测函数,对单张验证码进行识别。
def predict(model, image_path):
model.eval()
image = Image.open(image_path).convert('RGB')
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
image = transform(image).unsqueeze(0).to(device)
with torch.no_grad():
output = model(image)
pred = output.argmax(dim=2)
pred_text = ''.join([characters[i] for i in pred[0]])
return pred_text

测试

test_image = "captchas/9G2K_0.png"
print("Predicted:", predict(model, test_image))7. 后续优化建议
• 添加更多数据增强操作,比如旋转、仿射变换、噪声
• 使用更深的卷积网络提升特征提取能力
• 引入CTC Loss处理长度可变的验证码
• 尝试Transformer结构进行序列建模

posted @ 2025-04-28 13:30  ttocr、com  阅读(25)  评论(0)    收藏  举报