于Python和CNN的图像验证码识别系统设计与实现
随着Web安全防护机制的不断强化,图像验证码在防止自动化脚本攻击中被广泛使用。本文利用Python语言构建了一个完整的图像验证码识别系统,核心识别模型采用卷积神经网络(CNN)。系统涵盖数据集生成、模型设计、训练优化与结果测试等模块,并在模拟验证码环境下取得了良好的识别效果。
一、研究背景
验证码(CAPTCHA)通过扭曲、干扰等方式区分人类和机器,识别难度较高。人工识别验证码效率低下,而基于深度学习的自动识别方法已成为主流方向。Python作为深度学习领域的主要开发语言,具备丰富的图像处理和建模工具。
二、数据集生成
使用 captcha 库生成模拟验证码图像,字符集为数字 + 大写字母。
from captcha.image import ImageCaptcha
import random, string, os
from PIL import Image
def generate_dataset(save_dir, num_samples):
os.makedirs(save_dir, exist_ok=True)
chars = string.ascii_uppercase + string.digits
image = ImageCaptcha(width=160, height=60)
for _ in range(num_samples):
text = ''.join(random.choices(chars, k=5))
img = image.generate_image(text)
img.save(os.path.join(save_dir, f"{text}.png"))
generate_dataset("captcha_images/train", 5000)
generate_dataset("captcha_images/test", 500)
三、模型设计
采用PyTorch构建CNN模型,对验证码中每个字符进行逐位分类。
import torch.nn as nn
class CaptchaCNN(nn.Module):
def init(self, num_classes=36, captcha_len=5):
super().init()
self.conv = nn.Sequential(
nn.Conv2d(1, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
)
self.fc = nn.Sequential(
nn.Linear(64 * 40 * 15, 512), nn.ReLU(),
nn.Linear(512, captcha_len * num_classes)
)
def forward(self, x):
x = self.conv(x)
x = x.view(x.size(0), -1)
out = self.fc(x)
return out.view(-1, 5, 36) # [batch, length, classes]
四、训练流程
训练过程中对每位字符分别监督,采用 CrossEntropyLoss。
import torch, torch.nn.functional as F
def train(model, dataloader, optimizer, device):
model.train()
total_loss = 0
for imgs, labels in dataloader:
imgs, labels = imgs.to(device), labels.to(device)
outputs = model(imgs)
loss = sum(F.cross_entropy(outputs[:, i, :], labels[:, i]) for i in range(5))
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
return total_loss / len(dataloader)
五、测试与评估
对每个验证码图像进行预测,并与标签对比统计准确率。
def evaluate(model, dataloader, device):
model.eval()
correct = total = 0
with torch.no_grad():
for imgs, labels in dataloader:
imgs = imgs.to(device)
outputs = model(imgs)
preds = outputs.argmax(dim=2)
correct += (preds.cpu() == labels).all(dim=1).sum().item()
total += imgs.size(0)
return correct / total
浙公网安备 33010602011771号