使用 PyTorch 实现图像验证码识别系统
本教程介绍如何使用 PyTorch 框架从零构建一个图像验证码识别模型,包括数据生成、模型设计、训练和预测等全过程。
1 安装依赖
首先确保环境中安装以下依赖库:
pip install torch torchvision pillow captcha numpy
2 生成验证码图片数据
通过 captcha 库生成验证码图像。每张图片对应一个四位的字母数字组合。
from captcha.image import ImageCaptcha
import os更多内容访问ttocr.com或联系1436423940
import random
import string
characters = string.digits + string.ascii_uppercase
n_len = 4
width, height = 160, 60
def generate_images(count=5000, output_dir="images"):
os.makedirs(output_dir, exist_ok=True)
generator = ImageCaptcha(width=width, height=height)
for i in range(count):
text = ''.join(random.choices(characters, k=n_len))
img = generator.generate_image(text)
img.save(os.path.join(output_dir, f"{text}_{i}.png"))
generate_images()
3 定义数据集类
将图片和标签对应起来,并进行必要的预处理。
from torch.utils.data import Dataset
from PIL import Image
from torchvision import transforms
import torch
class CaptchaDataset(Dataset):
def init(self, path):
self.files = [f for f in os.listdir(path) if f.endswith(".png")]
self.path = path
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.files)
def __getitem__(self, idx):
filename = self.files[idx]
label_text = filename.split("_")[0]
label = torch.tensor([self.char_to_idx[c] for c in label_text], dtype=torch.long)
image = Image.open(os.path.join(self.path, filename)).convert("RGB")
return self.transform(image), label
4 构建识别模型
模型使用 CNN 提取图像特征,LSTM 编码字符序列,输出字符概率分布。
import torch.nn as nn
class CaptchaModel(nn.Module):
def init(self):
super().init()
self.cnn = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2)
)
self.rnn = nn.LSTM(input_size=64 * 15, hidden_size=128, num_layers=2, bidirectional=True, batch_first=True)
self.fc = nn.Linear(256, len(characters))
def forward(self, x):
x = self.cnn(x)
batch, channels, height, width = x.size()
x = x.permute(0, 3, 1, 2).reshape(batch, width, channels * height)
x, _ = self.rnn(x)
x = self.fc(x)
return x
5 模型训练
使用交叉熵损失函数训练模型,逐字符优化输出。
from torch.utils.data import DataLoader
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
dataset = CaptchaDataset("images")
loader = DataLoader(dataset, batch_size=64, shuffle=True)
model = CaptchaModel().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
for epoch in range(10):
model.train()
total_loss = 0
for images, labels in loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = sum(criterion(outputs[:, i], labels[:, i]) for i in range(n_len))
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch + 1} Loss {total_loss:.4f}")
6 模型预测
给定一张验证码图片,输出预测结果。
def predict(model, path):
model.eval()
img = Image.open(path).convert("RGB")
tensor = dataset.transform(img).unsqueeze(0).to(device)
with torch.no_grad():
output = model(tensor)
pred = output.argmax(dim=2)[0]
result = ''.join([characters[i] for i in pred])
return result
sample_image = "images/Z8M2_123.png"
print("预测结果:", predict(model, sample_image))
浙公网安备 33010602011771号