""" 全局配置 - 验证码识别多模型系统 (CaptchaBreaker) 定义字符集、图片尺寸、路径、训练超参等所有全局常量。 """ import os from pathlib import Path # ============================================================ # 项目根目录 # ============================================================ PROJECT_ROOT = Path(__file__).resolve().parent # ============================================================ # 数据目录 # ============================================================ DATA_DIR = PROJECT_ROOT / "data" SYNTHETIC_DIR = DATA_DIR / "synthetic" REAL_DIR = DATA_DIR / "real" CLASSIFIER_DIR = DATA_DIR / "classifier" SERVER_TASKS_DIR = DATA_DIR / "server_tasks" # 合成数据子目录 SYNTHETIC_NORMAL_DIR = SYNTHETIC_DIR / "normal" SYNTHETIC_MATH_DIR = SYNTHETIC_DIR / "math" SYNTHETIC_3D_TEXT_DIR = SYNTHETIC_DIR / "3d_text" SYNTHETIC_3D_ROTATE_DIR = SYNTHETIC_DIR / "3d_rotate" SYNTHETIC_3D_SLIDER_DIR = SYNTHETIC_DIR / "3d_slider" # 真实数据子目录 REAL_NORMAL_DIR = REAL_DIR / "normal" REAL_MATH_DIR = REAL_DIR / "math" REAL_3D_TEXT_DIR = REAL_DIR / "3d_text" REAL_3D_ROTATE_DIR = REAL_DIR / "3d_rotate" REAL_3D_SLIDER_DIR = REAL_DIR / "3d_slider" REAL_FUN_CAPTCHA_DIR = REAL_DIR / "funcaptcha" REAL_FUN_CAPTCHA_ROLLBALL_DIR = REAL_FUN_CAPTCHA_DIR / "4_3d_rollball_animals" # Solver 数据目录 SOLVER_DATA_DIR = DATA_DIR / "solver" SLIDE_DATA_DIR = SOLVER_DATA_DIR / "slide" ROTATE_SOLVER_DATA_DIR = SOLVER_DATA_DIR / "rotate" # ============================================================ # 模型输出目录 # ============================================================ CHECKPOINTS_DIR = PROJECT_ROOT / "checkpoints" ONNX_DIR = PROJECT_ROOT / "onnx_models" # 确保关键目录存在 for _dir in [ SYNTHETIC_NORMAL_DIR, SYNTHETIC_MATH_DIR, SYNTHETIC_3D_TEXT_DIR, SYNTHETIC_3D_ROTATE_DIR, SYNTHETIC_3D_SLIDER_DIR, REAL_NORMAL_DIR, REAL_MATH_DIR, REAL_3D_TEXT_DIR, REAL_3D_ROTATE_DIR, REAL_3D_SLIDER_DIR, REAL_FUN_CAPTCHA_DIR, REAL_FUN_CAPTCHA_ROLLBALL_DIR, CLASSIFIER_DIR, CHECKPOINTS_DIR, ONNX_DIR, SLIDE_DATA_DIR, ROTATE_SOLVER_DATA_DIR, SERVER_TASKS_DIR, ]: _dir.mkdir(parents=True, exist_ok=True) # ============================================================ # 字符集定义 # ============================================================ # 普通字符验证码: 按当前本地配置保留易混淆字符,覆盖完整数字 + 大写字母 NORMAL_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 算式验证码: 数字 + 运算符 MATH_CHARS = "0123456789+-×÷=?" # 3D 验证码: 继续使用去掉易混淆字符的精简字符集 THREED_CHARS = "23456789ABCDEFGHJKMNPQRSTUVWXYZ" # 验证码类型列表 (调度分类器输出) CAPTCHA_TYPES = ["normal", "math", "3d_text", "3d_rotate", "3d_slider"] NUM_CAPTCHA_TYPES = len(CAPTCHA_TYPES) # ============================================================ # 图片尺寸配置 (H, W) # ============================================================ IMAGE_SIZE = { "classifier": (64, 128), # 调度分类器输入 "normal": (40, 120), # 普通字符识别 "math": (40, 160), # 算式识别 (更宽) "3d_text": (60, 160), # 3D 立体文字识别 "3d_rotate": (80, 80), # 3D 旋转角度回归 (正方形) "3d_slider": (80, 240), # 3D 滑块偏移回归 "funcaptcha_rollball_animals": (48, 48), # FunCaptcha 专项 Siamese 输入 } # ============================================================ # 验证码生成参数 # ============================================================ GENERATE_CONFIG = { "normal": { "char_count_range": (4, 5), # 字符数量: 4-5 个 "bg_color_range": (230, 255), # 浅色背景 RGB 各通道 "rotation_range": (-15, 15), # 字符旋转角度 "noise_line_range": (2, 5), # 干扰线数量 "noise_point_num": 100, # 噪点数量 "blur_radius": 0.8, # 高斯模糊半径 "image_size": (120, 40), # 生成图片尺寸 (W, H) }, "math": { "operand_range": (1, 30), # 操作数范围 "operators": ["+", "-", "×", "÷"], # 支持的运算符 (除法只生成能整除的) "image_size": (160, 40), # 生成图片尺寸 (W, H) "bg_color_range": (230, 255), "rotation_range": (-10, 10), "noise_line_range": (2, 4), }, "3d_text": { "char_count_range": (4, 5), "image_size": (160, 60), # 生成图片尺寸 (W, H) "shadow_offset": (3, 3), # 阴影偏移 "perspective_intensity": 0.3, # 透视变换强度 "rotation_range": (-20, 20), # 字符旋转角度 }, "3d_rotate": { "image_size": (80, 80), # 生成图片尺寸 (W, H) "disc_radius": 35, # 圆盘半径 "marker_size": 8, # 方向标记大小 "bg_color_range": (200, 240), # 背景色范围 }, "3d_slider": { "image_size": (240, 80), # 生成图片尺寸 (W, H) "puzzle_size": (40, 40), # 拼图块大小 (W, H) "gap_x_range": (50, 200), # 缺口 x 坐标范围 "piece_left_margin": 5, # 拼图块左侧留白 "bg_noise_intensity": 30, # 背景纹理噪声强度 }, } # ============================================================ # 训练配置 # ============================================================ TRAIN_CONFIG = { "classifier": { "epochs": 30, "batch_size": 128, "lr": 1e-3, "scheduler": "cosine", "synthetic_samples": 50000, # 每类 10000 × 5 类 "val_split": 0.1, # 验证集比例 }, "normal": { "epochs": 50, "batch_size": 128, "lr": 1e-3, "scheduler": "cosine", "synthetic_samples": 60000, "loss": "CTCLoss", "val_split": 0.1, }, "math": { "epochs": 50, "batch_size": 128, "lr": 1e-3, "scheduler": "cosine", "synthetic_samples": 60000, "loss": "CTCLoss", "val_split": 0.1, }, "3d_text": { "epochs": 80, "batch_size": 64, "lr": 5e-4, "scheduler": "cosine", "synthetic_samples": 80000, "loss": "CTCLoss", "val_split": 0.1, }, "3d_rotate": { "epochs": 60, "batch_size": 128, "lr": 1e-3, "scheduler": "cosine", "synthetic_samples": 60000, "loss": "SmoothL1", "val_split": 0.1, }, "3d_slider": { "epochs": 60, "batch_size": 128, "lr": 1e-3, "scheduler": "cosine", "synthetic_samples": 60000, "loss": "SmoothL1", "val_split": 0.1, }, "funcaptcha_rollball_animals": { "epochs": 30, "batch_size": 64, "lr": 1e-3, "scheduler": "cosine", "loss": "BCEWithLogits", "val_split": 0.1, }, } # ============================================================ # 数据增强参数 (训练时使用) # ============================================================ AUGMENT_CONFIG = { "degrees": 8, # RandomAffine 旋转范围 "translate": (0.05, 0.05), # 平移范围 "scale": (0.95, 1.05), # 缩放范围 "brightness": 0.3, # ColorJitter 亮度 "contrast": 0.3, # ColorJitter 对比度 "blur_kernel": 3, # GaussianBlur 核大小 "blur_sigma": (0.1, 0.5), # GaussianBlur sigma "erasing_prob": 0.15, # RandomErasing 概率 "erasing_scale": (0.01, 0.05), # RandomErasing 面积比 } # ============================================================ # ONNX 导出配置 # ============================================================ ONNX_CONFIG = { "opset_version": 18, "dynamic_batch": True, # 支持动态 batch size } # ============================================================ # 回归模型标签范围 # ============================================================ REGRESSION_RANGE = { "3d_rotate": (0, 360), # 旋转角度 0-359° "3d_slider": (10, 200), # 滑块 x 偏移 (像素) } # ============================================================ # 推理配置 # ============================================================ INFERENCE_CONFIG = { "default_models_dir": str(ONNX_DIR), "normalize_mean": 0.5, "normalize_std": 0.5, } # ============================================================ # FunCaptcha 专项任务配置 # ============================================================ FUN_CAPTCHA_TASKS = { "4_3d_rollball_animals": { "artifact_name": "funcaptcha_rollball_animals", "checkpoint_name": "funcaptcha_rollball_animals", "data_dir": REAL_FUN_CAPTCHA_ROLLBALL_DIR, "input_size": IMAGE_SIZE["funcaptcha_rollball_animals"], # (H, W) "tile_size": (200, 200), # (W, H) "reference_box": (0, 200, 200, 400), # (x1, y1, x2, y2) "num_candidates": 4, "answer_index_base": 0, "channels": 3, }, } # ============================================================ # 随机种子 (保证数据生成可复现) # ============================================================ RANDOM_SEED = 42 # ============================================================ # 设备配置 (优先 GPU,回退 CPU) # 延迟导入 torch,避免仅使用生成器时必须安装 torch # ============================================================ def get_device(): """返回可用的 torch 设备,优先 GPU。""" import torch return torch.device("cuda" if torch.cuda.is_available() else "cpu") # ============================================================ # 服务配置 (可选 HTTP 服务) # ============================================================ SERVER_CONFIG = { "host": "0.0.0.0", "port": 8080, "task_ttl_seconds": 600, "task_workers": 2, "tasks_dir": str(SERVER_TASKS_DIR), "callback_timeout_seconds": 10, "callback_max_retries": 2, "callback_retry_delay_seconds": 1.0, "callback_retry_backoff": 2.0, "callback_signing_secret": os.getenv("CALLBACK_SIGNING_SECRET") or os.getenv("CAPTCHA_CALLBACK_SIGNING_SECRET"), "balance": 999999.0, "task_cost": 0.0, "client_key": os.getenv("CLIENT_KEY") or os.getenv("CAPTCHA_CLIENT_KEY"), } # ============================================================ # Solver 配置 (交互式验证码求解) # ============================================================ SOLVER_CONFIG = { "slide": { "canny_low": 50, "canny_high": 150, "cnn_input_size": (128, 256), # H, W }, "rotate": { "input_size": (128, 128), # H, W "channels": 3, # RGB }, } SOLVER_TRAIN_CONFIG = { "slide_cnn": { "epochs": 50, "batch_size": 64, "lr": 1e-3, "synthetic_samples": 30000, "val_split": 0.1, }, "rotate": { "epochs": 80, "batch_size": 64, "lr": 5e-4, "synthetic_samples": 50000, "val_split": 0.1, }, } SOLVER_REGRESSION_RANGE = { # 在 solver 输入宽度空间内预测缺口中心 x 坐标,再通过 sigmoid 归一化到 [0, 1] "slide": (0, SOLVER_CONFIG["slide"]["cnn_input_size"][1]), "rotate": (0, 360), # 角度 }