为实现高效、快速的验证码自动识别,本文提出一种结合轻量卷积网络MobileNetV3与测试时增强(TTA)策略的验证码识别系统。该系统在保持识别精度的同时显著降低了模型体积与计算开销,适用于资源受限设备的部署需求。
一、引言
验证码作为防止机器攻击的重要手段,其识别问题一直是计算机视觉研究的重点。传统CNN模型虽然准确率高,但计算资源消耗大。MobileNetV3 作为轻量神经网络架构的代表,具有结构紧凑、速度快、性能优的优势。本文通过集成TTA策略,进一步提高模型在复杂环境下的稳定性与泛化能力。
二、系统流程概述
数据自动生成(模拟真实验证码)
更多内容访问ttocr.com或联系1436423940
图像预处理与增强
MobileNetV3 模型训练
测试时增强(TTA)推理
解码输出与结果评估
三、验证码数据生成
from captcha.image import ImageCaptcha
import os, random, string
def generate_captcha(path, count=1000):
os.makedirs(path, exist_ok=True)
generator = ImageCaptcha(width=160, height=60)
chars = string.digits + string.ascii_uppercase
for _ in range(count):
text = ''.join(random.choices(chars, k=5))
img = generator.generate_image(text)
img.save(os.path.join(path, f"{text}.png"))
generate_captcha('data/train', 5000)
generate_captcha('data/test', 1000)
四、数据加载与增强
使用 torchvision.transforms 实现训练增强和测试增强(TTA)。
import torchvision.transforms as T
train_transform = T.Compose([
T.Grayscale(),
T.RandomRotation(10),
T.ColorJitter(brightness=0.3),
T.ToTensor()
])
tta_transforms = [
T.Compose([
T.Grayscale(),
T.RandomAffine(0, translate=(0.05, 0.05)),
T.ToTensor()
])
for _ in range(4)
]
五、模型设计:MobileNetV3 + 多头输出
将 MobileNetV3 作为主干网络,每个字符位输出一个分支,适用于定长验证码。
from torchvision.models import mobilenet_v3_small
import torch.nn as nn
class CaptchaModel(nn.Module):
def init(self, num_classes, num_chars=5):
super().init()
base = mobilenet_v3_small(pretrained=True)
self.features = base.features
self.classifiers = nn.ModuleList([
nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(576, num_classes)
) for _ in range(num_chars)
])
def forward(self, x):x = self.features(x)return [head(x) for head in self.classifiers]
六、训练模型
def train_one_epoch(model, loader, optimizer, loss_fn, device):
model.train()
for imgs, labels in loader:
imgs = imgs.to(device)
labels = labels.to(device)
outputs = model(imgs)
loss = sum(loss_fn(o, labels[:, i]) for i, o in enumerate(outputs))
optimizer.zero_grad()
loss.backward()
optimizer.step()
七、TTA推理策略
def predict_tta(model, img, transforms, device):
model.eval()
results = []
with torch.no_grad():
for t in transforms:
t_img = t(img).unsqueeze(0).to(device)
output = model(t_img)
pred = [o.argmax(1).item() for o in output]
results.append(pred)
# 使用投票融合
import numpy as np
return np.array(results).mean(axis=0).round().astype(int)