基于深度学习的滑动验证码缺口识别教程

1. 简介

本教程将介绍如何使用深度学习模型(YOLOv3)来识别滑动验证码中的缺口位置。相比传统图像处理方法,深度学习能够更准确地定位验证码缺口,且具有更好的泛化能力。

2. 准备工作

2.1 克隆代码仓库

git clone https://github.com/Python3WebSpider/DeepLearningSlideCaptcha2.git
cd DeepLearningSlideCaptcha2

2.2 安装依赖

推荐使用 Python 3.8+ 和 PyTorch 1.8+:

pip install -r requirements.txt

3. 目标检测基础

滑动验证码缺口识别属于目标检测任务。当前主流的目标检测算法可分为两类:

  • Two-Stage 方法(如 R-CNN 系列):

    • 首先生成候选区域
    • 然后对候选区域进行分类和回归
    • 准确率高但速度较慢
  • One-Stage 方法(如 YOLO、SSD):

    • 直接将目标检测转化为回归问题
    • 速度快但准确率略低

本教程选用 YOLOv3 作为基础算法,因其在速度和准确率之间取得了良好平衡。

4. 数据准备

4.1 收集验证码图片

使用 collect.py 脚本自动收集验证码图片:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import os

COUNT = 100  # 收集数量
URL = 'https://captcha1.scrape.center/'
OUTPUT_DIR = 'data/captcha/images'

if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)

for i in range(COUNT):
    driver = webdriver.Chrome()
    try:
        driver.get(URL)
        wait = WebDriverWait(driver, 10)
        login_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-primary')))
        login_btn.click()
        captcha = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.geetest_slicebg')))
        time.sleep(2)  # 等待验证码完全加载
        captcha.screenshot(f'{OUTPUT_DIR}/captcha_{i}.png')
    finally:
        driver.quit()

4.2 数据标注

推荐使用 labelImg 工具进行标注:

pip install labelImg
labelImg

标注步骤:

  1. 打开 data/captcha/images 目录
  2. 使用 Create RectBox 工具框选缺口
  3. 将标注命名为 "target"
  4. 保存为 XML 格式

4.3 数据格式转换

将 XML 标注转换为 YOLO 格式:

import xmltodict
import os

def parse_xml(xml_path):
    with open(xml_path, 'r') as f:
        xml_str = f.read()
    data = xmltodict.parse(xml_str)
    
    # 获取图片尺寸
    width = int(data['annotation']['size']['width'])
    height = int(data['annotation']['size']['height'])
    
    # 获取标注框坐标
    xmin = int(data['annotation']['object']['bndbox']['xmin'])
    ymin = int(data['annotation']['object']['bndbox']['ymin'])
    xmax = int(data['annotation']['object']['bndbox']['xmax'])
    ymax = int(data['annotation']['object']['bndbox']['ymax'])
    
    # 转换为YOLO格式(中心点坐标和相对宽高)
    x_center = ((xmin + xmax) / 2) / width
    y_center = ((ymin + ymax) / 2) / height
    box_width = (xmax - xmin) / width
    box_height = (ymax - ymin) / height
    
    return [x_center, y_center, box_width, box_height]

# 转换所有XML文件
for xml_file in os.listdir('data/captcha/annotations'):
    if xml_file.endswith('.xml'):
        result = parse_xml(f'data/captcha/annotations/{xml_file}')
        with open(f'data/captcha/labels/{xml_file.replace(".xml", ".txt")}', 'w') as f:
            f.write(f'0 {" ".join(map(str, result))}')

5. 模型训练

5.1 下载预训练权重

bash scripts/download_pretrained.sh

5.2 开始训练

bash scripts/train.sh

5.3 监控训练过程

使用 TensorBoard 监控训练指标:

tensorboard --logdir=logs

访问 http://localhost:6006 查看训练曲线。

6. 模型测试

6.1 准备测试数据

将测试图片放入 data/captcha/test 目录。

6.2 运行测试

bash scripts/detect.sh

测试结果将保存在 data/captcha/result 目录。

7. 模型部署

将训练好的模型部署为 API 服务(使用 FastAPI):

from fastapi import FastAPI, UploadFile, File
from PIL import Image
import io
import torch
from models.yolo import Model
from utils.general import non_max_suppression, scale_coords

app = FastAPI()

# 加载模型
model = Model(cfg='models/yolov3.yaml')
model.load_state_dict(torch.load('checkpoints/best.pt')['model'])
model.eval()

@app.post("/predict")
async def predict(file: UploadFile = File(...)):
    # 读取图片
    image = Image.open(io.BytesIO(await file.read()))
    
    # 预处理
    img_tensor = preprocess(image)
    
    # 预测
    with torch.no_grad():
        pred = model(img_tensor)
        pred = non_max_suppression(pred, conf_thres=0.5, iou_thres=0.5)
    
    # 后处理
    if pred[0] is not None:
        pred = scale_coords(img_tensor.shape[2:], pred[0][:, :4], image.size)
        x1, y1, x2, y2 = pred[0].tolist()
        return {
            "x_offset": x1,
            "width": x2 - x1,
            "height": y2 - y1
        }
    return {"error": "No target detected"}

def preprocess(image):
    # 实现图片预处理逻辑
    pass

8. 优化建议

  1. 数据增强:增加更多样化的验证码数据,包括不同风格、不同背景的验证码
  2. 模型优化:尝试 YOLOv5 或 YOLOv8 等更新版本的模型
  3. 部署优化:使用 ONNX 或 TensorRT 加速推理
  4. 主动学习:将模型预测不确定的样本加入训练集重新训练

9. 总结

本教程详细介绍了使用 YOLOv3 识别滑动验证码缺口的方法,包括数据收集、标注、模型训练和测试的全流程。相比传统方法,深度学习方案具有更好的准确性和泛化能力。

完整代码:DeepLearningSlideCaptcha2