Skip to content

3-Tokisaki-Kurumi/Resolve-ninegrid-Jigsaw-captcha

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🧩 九宫格拼图验证码求解器

基于边缘特征匹配的九宫格验证码自动还原工具

Language Python License


🌍 Language / 语言: English | 简体中文


📖 目录


✨ 功能特性

  • 🔍 智能边缘特征提取:自动提取每张图片四条边的灰度特征向量(默认20维)
  • 📐 高精度相似度计算:使用余弦相似度算法计算相邻图片边缘匹配度
  • 🎯 启发式搜索优化:采用贪心+回溯策略快速寻找最优3×3排列
  • 🔄 最少交换步骤生成:自动计算从初始状态到目标状态的最少交换次数
  • 🖼️ 可视化支持:生成网格排列对比图,直观展示求解结果
  • 💾 多格式支持:兼容 png, jpg, jpeg, webp, bmp, gif, tiff 等主流图片格式
  • 🛠️ 灵活的API接口:提供完整的Python API和命令行工具
  • 📝 详细日志输出:支持DEBUG/INFO/WARNING/ERROR多级日志

📁 项目结构

nine_grid_captcha_solver/
├── solver.py              # 核心算法:边缘提取、相似度计算、启发式搜索、交换序列生成
├── image_utils.py         # 图片处理:合并、保存、可视化、模拟交换
├── io_utils.py            # 文件IO:加载本地图片(支持9种格式)
├── cli.py                 # 命令行入口:参数解析、错误处理、退出码管理
└── __init__.py            # 模块初始化:导出公共API

example/
├── test_image/            # 测试图片目录(test1, test2, test3...)
│   ├── test1/             #   └─ 包含 0.webp ~ 8.webp(9张打乱的拼图块)
│   ├── test2/
│   └── test3/
├── test_results/          # 输出结果(自动生成)
│   ├── test1.jpg          #   └─ 求解后的完整拼图
│   ├── test2.jpg
│   └── test3.jpg
└── batch_solve_example_.py # 批量测试脚本

requirements.txt           # Python依赖列表
README.md                  # 本文档(简体中文版 - 默认显示)
README.en.md               # English version (英文版)

🔧 安装依赖

环境要求

  • Python版本: >= 3.6
  • 操作系统: Windows / macOS / Linux(跨平台)

安装步骤

# 1. 克隆或下载本项目
git clone https://github.com/3-Tokisaki-Kurumi/nine-grid-captcha-solver.git
cd nine-grid-captcha-solver

# 2. 安装依赖
pip install -r requirements.txt

依赖说明

依赖包 版本要求 用途 必需
pillow >= 8.0.0 PIL图像处理库,用于图片加载、转换、保存
numpy >= 1.19.0 数值计算库,用于数组运算、矩阵操作
matplotlib >= 3.3.0 绑图库,用于生成可视化图表(可选)
requests >= 2.25.0 HTTP请求库(预留扩展)
beautifulsoup4 >= 4.9.0 HTML解析库(预留扩展)

🚀 快速开始

最小化使用(3步搞定)

# 步骤1: 准备9张打乱的拼图图片到文件夹
mkdir my_captcha
# 将9张图片放入 my_captcha/ 文件夹,命名为 0.webp, 1.webp, ..., 8.webp

# 步骤2: 运行求解器
python -m nine_grid_captcha_solver.cli --local ./my_captcha

# 步骤3: 查看结果
# 控制台会输出:
#   - 交换步骤(如:交换0和6)
#   - 最终排列(3×3网格)

完整功能演示

python -m nine_grid_captcha_solver.cli \
  --local ./example/test_image/test1 \
  --visualize \
  --save-result \
  --save-original \
  --log-level DEBUG

预期输出:

加载图片: ./example/test_image/test1
保存图片: captcha_images/image_0.png
保存图片: captcha_images/image_1.png
...
保存图片: captcha_images/image_8.png
求解中...
正在提取边缘特征...
正在计算相似度矩阵...
正在搜索最优排列...
求解成功! 找到3个交换步骤
保存排列结果: result_images/result.jpg
可视化结果已保存: visualization.png

搞定! 需要3步交换

交换步骤:
  1. 交换0和6
  2. 交换1和3
  3. 交换5和7

最终排列:
  第1行: [6, 3, 2]
  第2行: [1, 4, 7]
  第3行: [0, 5, 8]

模拟过程:
初始顺序: [0, 1, 2, 3, 4, 5, 6, 7, 8]
交换 1: 位置 0 和 6 -> [6, 1, 2, 3, 4, 5, 0, 7, 8]
交换 2: 位置 1 和 3 -> [6, 3, 2, 1, 4, 5, 0, 7, 8]
交换 3: 位置 5 和 7 -> [6, 3, 2, 1, 4, 7, 0, 5, 8]
最终顺序: [6, 3, 2, 1, 4, 7, 0, 5, 8]

📋 命令行使用

基本语法

python -m nine_grid_captcha_solver.cli [选项]

完整参数列表

参数 类型 必填 默认值 说明
--local 字符串 - 图片文件夹路径(必须包含9张图片)
--visualize 布尔标志 False 生成 visualization.png 可视化对比图
--save-result 布尔标志 False 保存拼接结果到 result_images/result.jpg
--save-original 布尔标志 False 保存原始9张图片到 captcha_images/ 文件夹
--log-level 枚举字符串 INFO 日志级别:DEBUG / INFO / WARNING / ERROR

使用场景示例

场景1:仅求解,查看控制台输出

python -m nine_grid_captcha_solver.cli --local ./images

场景2:求解 + 保存结果图

python -m nine_grid_captcha_solver.cli \
  --local ./images \
  --save-result

输出文件: result_images/result.jpg

场景3:求解 + 可视化 + 保存

python -m nine_grid_captcha_solver.cli \
  --local ./images \
  --visualize \
  --save-result \
  --save-original

输出文件:

  • visualization.png (3×3网格对比图)
  • result_images/result.jpg (拼接后的完整图片)
  • captcha_images/image_0.png ~ image_8.png (原始图片备份)

场景4:调试模式(显示详细日志)

python -m nine_grid_captcha_solver.cli \
  --local ./images \
  --log-level DEBUG

场景5:批量处理多个验证码

# 创建批量脚本或使用循环
for dir in ./captcha_folder/*/; do
  python -m nine_grid_captcha_solver.cli --local "$dir" --save-result
done

错误处理与退出码

退出码 含义 触发条件 示例输出
0 ✅ 成功 正常完成求解 搞定! 需要3步交换
1 ❌ 错误 参数错误/文件不存在/图片不足/求解失败 文件夹不存在: ./xxx加载失败,需要9张图片求解失败
130 ⚠️ 用户中断 按 Ctrl+C 取消 已取消

错误情况详解:

  1. 文件夹不存在
    文件夹不存在: ./nonexistent_folder
    
  2. 图片数量不足(<9张)
    加载图片: ./incomplete_folder
    加载失败,需要9张图片
    需要9张图片,只找到5张
    
  3. 搜索失败(无法找到有效排列)
    正在搜索最优排列...
    搜索失败,无法找到有效排列
    求解失败
    
  4. 未预期的异常(仅在DEBUG模式显示堆栈)
    出错了: division by zero
    # (DEBUG模式下会打印完整traceback)
    

💻 Python API 调用

导入模块

from nine_grid_captcha_solver import (
    CaptchaSolver,        # 核心求解器类
    load_local_images,    # 图片加载函数
    merge_grid,           # 网格合并函数
    save_result_grid,     # 结果保存函数
    visualize_grid,       # 可视化函数
    save_images,          # 批量保存函数
    simulate_swaps        # 交换模拟函数
)

完整使用示例

from nine_grid_captcha_solver import CaptchaSolver, load_local_images, merge_grid

# 初始化求解器
solver = CaptchaSolver()

# 步骤1: 加载图片(从本地文件夹)
print("步骤1: 加载图片...")
images = load_local_images("./my_captcha_images")
if not images:
    print("❌ 图片加载失败")
    exit(1)

print(f"✅ 成功加载 {len(images)} 张图片")

# 步骤2: 执行求解
print("\n步骤2: 执行求解...")
swaps, grid = solver.solve(images)

if not swaps:
    print("❌ 求解失败")
    exit(1)

print(f"✅ 求解成功! 需要 {len(swaps)} 步交换")

# 步骤3: 输出结果
print("\n===== 求解结果 =====")
print(f"交换步骤: {swaps}")
print(f"最终排列:")
for i, row in enumerate(grid):
    print(f"  第{i+1}行: {row}")

# 步骤4: 合并并保存结果图
print("\n步骤4: 保存结果...")
result_image = merge_grid(images, grid)
result_image.save("solved_puzzle.jpg", quality=95)
print("✅ 结果已保存到 solved_puzzle.jpg")

# ===== 高级用法 =====

# 用法1: 提取单张图片的边缘特征(用于自定义分析)
edge_features = solver.extract_edges(images[0], edge_size=20)
left_edge, right_edge, top_edge, bottom_edge = edge_features
print(f"\n左边缘特征向量长度: {len(left_edge)}")

# 用法2: 计算相似度矩阵(用于调试或研究)
all_features = [solver.extract_edges(img) for img in images]
H_matrix, V_matrix = solver.precompute_similarities(all_features)
print(f"水平相似度矩阵形状: {H_matrix.shape}")  # (9, 9)
print(f"垂直相似度矩阵形状: {V_matrix.shape}")  # (9, 9)

# 用法3: 可视化结果
from nine_grid_captcha_solver import visualize_grid
visualize_grid(
    images,
    grid,
    title="我的验证码求解结果",
    save_path="my_visualization.png"
)

# 用法4: 模拟交换过程
from nine_grid_captcha_solver import simulate_swaps
final_arrangement = simulate_swaps(swaps)
print(f"\n模拟后的最终顺序: {final_arrangement}")

API 参考文档

CaptchaSolver 类 (solver.py)

核心求解器类,封装了所有算法逻辑。

方法名 签名 参数 返回值 详细说明
__init__ () 实例 初始化求解器(当前无配置项)
extract_edges (img, edge_size=20) img: PIL Image对象edge_size: 特征向量维度(默认20) tuple(4) 提取图片四边(左、右、上、下)的灰度特征向量• 将每条边压缩为指定长度的向量• 使用均值池化进行降采样• 返回 (left, right, top, bottom) 四个列表
precompute_similarities (edge_features) edge_features: list of tuples(9个元素的列表) (H, V) 计算所有图片对之间的相似度矩阵• H: 水平相似度矩阵 (9×9),表示右边-左边匹配度• V: 垂直相似度矩阵 (9×9),表示底边-顶边匹配度• 使用余弦相似度公式:  cos(A,B) = (A·B) / (‖A‖ × ‖B‖)• 对角线设为 -10(避免自己和自己匹配)
optimized_search (H, V) H: 水平相似度矩阵V: 垂直相似度矩阵 list[list[int]]None 启发式搜索最优3×3排列• 尝试每个图片作为左上角起点• 贪心选择水平/垂直相似度最高的邻居• 相似度阈值 > 0.1 才认为有效匹配• 返回得分最高的有效排列(3×3二维列表)• 如果找不到有效排列则返回 None
evaluate_grid (grid, H, V) grid: 3×3排列H, V: 相似度矩阵 float 评估给定排列的总得分• 累加所有相邻边的相似度分数• 包括2个水平邻接 × 3行 = 6个水平分数• 包括2个垂直邻接 × 3列 = 6个垂直分数• 总分范围通常在 -12 到 +12 之间
generate_swap_sequence (initial, correct) initial: 初始排列(list)correct: 目标排列(list) list[tuple] 生成交换步骤序列• 从初始状态逐步变换到目标状态• 每次交换将正确位置的元素归位• 返回交换索引对的列表,如 [(0,6), (1,3), (5,7)]• 保证交换次数最少
solve (images) images: list of 9 PIL Images (swaps, grid)(None, None) 完整的求解流程入口1. 验证图片数量 == 92. 调用 extract_edges() 提取所有图片的特征3. 调用 precompute_similarities() 计算相似度矩阵4. 调用 optimized_search() 搜索最优排列5. 调用 generate_swap_sequence() 生成交换步骤6. 返回 (交换步骤列表, 3×3网格)

image_utils 模块 (image_utils.py)

提供图片处理和可视化功能的工具函数集合。

函数名 签名 参数 返回值 详细说明
merge_grid (images, grid) images: 9张PIL Imagegrid: 3×3排列列表 PIL Image 根据3×3网格排列合并9张图片为一张大图• 自动检测第一张图片的尺寸 (w × h)• 创建新的 RGB 图像 (3w × 3h)• 按照 grid 指定的位置粘贴每张图片• 所有图片统一转换为RGB模式
save_result_grid (images, grid, folder="result_images") 同上 + folder: 输出文件夹 str (文件路径) 保存排列后的结果图片• 自动创建输出文件夹(如不存在)• 调用 merge_grid() 生成合并图• 以JPEG格式保存为 folder/result.jpg• 返回保存的完整文件路径
visualize_grid (images, grid, title="结果排列", save_path=None) images, grid: 同上title: 图表标题save_path: 保存路径(可选) None 生成3×3网格可视化图表• 使用 matplotlib 创建 10×10 英寸图形• 每个子图显示一张图片及其位置信息• 格式:位置(row,col)\n原图idx• 如果提供 save_path 则保存为文件• 否则调用 plt.show() 显示窗口• 支持中文标题(SimHei/Microsoft YaHei字体)
save_images (images, folder="captcha_images") images: 图片列表folder: 保存文件夹 None 批量保存图片到指定文件夹• 自动创建文件夹• 按顺序保存为 image_0.png ~ image_8.png• PNG无损格式,保留原始质量
simulate_swaps (swap_sequence) swap_sequence: 交换步骤列表 list 在控制台模拟交换过程• 初始状态: [0, 1, 2, 3, 4, 5, 6, 7, 8]• 逐步执行每次交换并打印中间状态• 格式:交换 i: 位置 a 和 b -> [新序列]• 最后打印最终顺序• 返回最终的排列列表

io_utils 模块 (io_utils.py)

负责文件I/O操作的底层工具。

函数名 签名 参数 返回值 详细说明
load_local_images (folder_path) folder_path: 文件夹路径字符串 list[PIL Image]None 从本地文件夹加载9张验证码图片• 支持的格式(按优先级扫描):  .png, .jpg, .jpeg, .webp, .bmp, .gif, .tiff, .tif排序规则:按文件名字符串升序排列• 数量限制:只取前9张图片• 错误处理:跳过无法打开的图片并打印警告• 成功返回9个PIL Image对象的列表• 失败返回 None 并打印原因

📊 输入输出规范

输入要求

属性 要求 说明 示例
数量 必须9张 不多不少,正好9张 0.webp, 1.webp, ..., 8.webp
命名规则 数字前缀 文件名以数字开头,按字符串排序后应为0-8的顺序 0.webp, 1.jpg, 10.png(注意:10会在2前面)❌ pic_a.webp, pic_b.webp
文件格式 支持多种 优先级:png > jpg > jpeg > webp > bmp > gif > tiff > tif 推荐 webp(体积小)或 png(无损)
图片尺寸 建议一致 9张图片尺寸最好相同(算法可容忍小幅差异) 推荐 100×100, 150×150 等
内容类型 拼图碎片 每张图片应是完整图片的1/9部分 打乱顺序的九宫格拼图块
存储路径 本地文件夹 所有9张图片必须在同一文件夹内 ./my_captchas/test1/

⚠️ 重要注意事项

  1. 命名陷阱:如果使用 0.png, 1.png, ..., 10.png,字符串排序会导致 10.png 排在 2.png 前面!
    • 解决方案:使用 0.png, 1.png, ..., 8.png 或补零 00.png, 01.png, ..., 08.png
  2. 图片质量
    • 推荐:清晰边缘、明显纹理(如风景照、建筑)
    • ⚠️ 一般:纯色块、渐变色(可能降低准确率)
    • 困难:重复图案、周期性纹理(可能导致误匹配)
  3. 特殊字符:文件路径和文件名建议只使用英文、数字、下划线

输出说明

命令行输出

成功时:

✅ 标准输出信息流:
  1. 加载提示:"加载图片: <路径>"
  2. 进度提示:"正在提取边缘特征..." / "正在计算相似度矩阵..." / "正在搜索最优排列..."
  3. 成功提示:"求解成功! 找到N个交换步骤"
  4. 结果摘要:"搞定! 需要N步交换"
  5. 交换详情(逐行列出)
  6. 最终排列(3行×3列网格)

❌ 错误输出到 stderr(如果启用 --log-level DEBUG 会附带堆栈跟踪)

生成的文件

文件/文件夹 触发条件 格式 内容说明
visualization.png --visualize PNG (10×10英寸) 3×3网格对比图,标注位置和原图编号
result_images/result.jpg --save-result JPEG (quality=95) 拼接后的完整图片
captcha_images/image_0.png ~ image_8.png --save-original PNG 原始9张图片的副本

Python API 返回值

# 成功时
swaps = [(0, 6), (1, 3), (5, 7)]  # list of tuples
grid = [[6, 3, 2], [1, 4, 7], [0, 5, 8]]  # 3×3 nested list

# 失败时
swaps = None
grid = None

🧪 测试与示例

内置测试数据

项目提供了3组真实测试案例:

测试集 路径 说明 预期行为
test1 example/test_image/test1/ 9张 .webp 拼图块 应能成功求解
test2 example/test_image/test2/ 9张 .webp 拼图块 应能成功求解
test3 example/test_image/test3/ 9张 .webp 拼图块 应能成功求解

批量测试运行

cd example
python batch_solve_example_.py

预期输出

[OK] test1 完成
[OK] test2 完成
[OK] test3 完成

结果保存至: example/test_results/

输出文件

  • example/test_results/test1.jpg - 第1组的求解结果
  • example/test_results/test2.jpg - 第2组的求解结果
  • example/test_results/test3.jpg - 第3组的求解结果

单独测试某个案例

# 测试 test1
python -m nine_grid_captcha_solver.cli \
  --local ./example/test_image/test1 \
  --visualize \
  --save-result

# 测试 test2
python -m nine_grid_captcha_solver.cli \
  --local ./example/test_image/test2 \
  --save-result

自定义测试数据

如果你想用自己的图片测试:

# 1. 创建文件夹
mkdir my_test

# 2. 放入9张图片(确保命名正确)
#    推荐命名:0.webp, 1.webp, 2.webp, ..., 8.webp

# 3. 运行求解
python -m nine_grid_captcha_solver.cli \
  --local ./my_test \
  --visualize \
  --save-result \
  --log-level DEBUG

# 4. 检查输出
ls -la visualization.png result_images/

❓ 常见问题

Q1: 求解失败怎么办?

A: 可能的原因及解决方案:

  1. 图片质量问题
    • 检查图片是否清晰、是否有明显的边缘纹理
    • 避免使用纯色或渐变色的图片
    • 尝试提高图片分辨率
  2. 命名顺序错误
    • 确保文件名按数字顺序排列:0, 1, 2, ..., 8
    • 注意字符串排序问题(见"输入要求"章节)
  3. 图片数量不足
    • 必须恰好9张图片,不能多也不能少
    • 检查文件夹中是否混入了其他文件
  4. 调试技巧
    python -m nine_grid_captcha_solver.cli \
      --local ./your_images \
      --log-level DEBUG
    查看详细日志了解具体失败环节

Q2: 可以处理非3×3的拼图吗?

A: 当前版本仅支持 3×3 九宫格拼图。如果要支持其他规格(如 4×4、2×3),需要修改以下部分:

Q3: 准确率如何?哪些情况下会出错?

A: 基于边缘特征的算法在大多数情况下表现良好,但在以下情况可能出现问题:

高准确率场景 ✅ (>95%):

  • 自然风景照片(树木、建筑、天空交界线)
  • 有明确边缘的物体照片
  • 高分辨率、低噪声的图片

中等准确率场景 ⚠️ (70-90%):

  • 包含大面积纯色区域的图片
  • 重复图案(如砖墙、格子布)
  • 光照不均匀的图片

低准确率场景 ❌ (<70%):

  • 抽象艺术画或无规律的纹理
  • 周期性很强的图案
  • 经过重度压缩或有损处理的图片

Q4: 如何提高求解速度?

A: 当前算法已经很快(<1秒),但如果需要进一步优化:

  1. 减少 edge_size(默认20→10):加快特征提取速度,但可能略微降低准确率
  2. 限制搜索起点:不尝试全部9个起点,而是随机抽样3-5个
  3. 使用更快的相似度度量:如欧氏距离替代余弦相似度
  4. 并行化:多进程同时尝试不同起点

Q5: 如何集成到我自己的项目中?

A: 提供两种方式:

方式1:命令行调用(适合脚本自动化)

import subprocess

result = subprocess.run([
    'python', '-m', 'nine_grid_captcha_solver.cli',
    '--local', './images',
    '--save-result'
], capture_output=True, text=True)

print(result.stdout)
print(result.returncode)  # 0=成功, 1=失败

方式2:Python API调用(适合深度集成)

from nine_grid_captcha_solver import CaptchaSolver, load_local_images, merge_grid

solver = CaptchaSolver()
images = load_local_images("./images")
swaps, grid = solver.solve(images)

if swaps:
    result = merge_grid(images, grid)
    result.save("output.jpg")

Q6: 支持哪些Python版本?

A:

  • 最低版本: Python 3.6+
  • 推荐版本: Python 3.8+
  • 测试环境: Python 3.6, 3.7, 3.8, 3.9, 3.10, 3.11

主要使用了类型注解语法(Python 3.6+)和 f-string(Python 3.6+)。

Q7: 生成的可视化图片太大怎么办?

A: 可以修改代码或使用外部工具压缩:

方法1:修改 matplotlib 参数

# 在调用 visualize_grid 前
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 100  # 降低DPI(默认100)
plt.rcParams['figure.figsize'] = (6, 6)  # 缩小尺寸(默认10×10)

方法2:后处理压缩

# 使用ImageMagick或其他工具
convert visualization.png -resize 50% -quality 85 visualization_small.jpg

📄 许可证

本项目采用 MIT License 开源协议。

MIT License

Copyright (c) 2025 3-Tokisaki-Kurumi and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


⭐ 如果这个项目对你有帮助,请给一个 Star!⭐

🤝 欢迎 Issue 和 Pull Request!

About

Nine-grid jigsaw captcha solver based on image similarity matching. No ML training required, uses traditional computer vision algorithms for high-accuracy puzzle captcha recognition.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages