用户可通过浏览器或 API 上传数独图片自动识别并求解,也可手动输入题目获取答案。项目融合 PyTorch CNN 图像识别与高性能 C++ 求解器,提供 Web GUI、REST API 和详细文档,支持模型训练与性能优化。【此简介由AI生成】
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 2 个月前 | ||
| 4 年前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 4 年前 |
Sudoku Solver + Image Recognition
数独求解与图像识别系统,支持通过 API 上传数独图片自动识别并求解。
功能
- Web GUI:浏览器访问即可使用,上传图片 → 编辑识别结果 → 一键求解
- 图像识别:上传数独图片,自动提取网格并识别数字(基于 PyTorch CNN)
- 数独求解:高性能 C++ 求解器(位运算回溯 / DLX / SIMD 加速)
- REST API:基于 FastAPI 提供 HTTP 接口
详细文档
每个子模块有独立的 README 深入介绍:
| 文档 | 内容 |
|---|---|
| src/README.md | C++ 求解器:算法原理、编译系统、PGO 优化、性能数据 |
| tests/README.md | 测试体系:精度验证、性能基准、PGO 训练、添加新测试 |
| sudoku/README.md | 图像识别:透视校正→数字提取→CNN 分类的完整流水线 |
| training/README.md | CNN 训练:MNIST 预训练 + 自定义数据微调,如何添加样本 |
目录结构
sudoku-py/
├── main.py # FastAPI 入口
├── CMakeLists.txt # C++ 构建系统
├── build_pgo.sh # PGO 一键构建脚本
├── pyproject.toml # Python 项目配置与依赖(PEP 621)
├── Dockerfile # 容器化部署
├── sudoku/ # Python 图像识别模块
│ ├── README.md # 详细文档:识别流水线说明
│ ├── pipeline.py # 图像识别主流程
│ ├── classifier.py # CNN 模型定义
│ ├── correction.py # 透视变换校正
│ ├── extraction.py # 数字提取(连通域分析)
│ ├── binary_classifier.py # 二分类 CNN(空格/数字判别)
│ └── __init__.py
├── training/ # CNN 模型训练
│ ├── README.md # 详细文档:训练流程说明
│ ├── train.py # 训练脚本
│ ├── samples.npy # 自定义训练数据
│ └── label.npy # 训练标签
├── models/ # 训练好的模型权重
│ ├── sudoku_cnn.pth
│ └── cell_binary.pth
├── src/ # C++ 求解器源码
│ ├── README.md # 详细文档:求解器算法与编译
│ ├── solver_bitmask.hpp # 位运算回溯求解器头文件
│ ├── solver_bitmask.cpp # 位运算回溯求解器实现(主力)
│ ├── solver_dpll_triad_simd.cc # Tdoku SIMD 求解器
│ ├── solver_dpll_triad_scc.cc # Tdoku SCC 求解器
│ ├── solver_basic.cc # Tdoku 基础求解器
│ ├── solver_backtrack.cpp # 实验性回溯求解器
│ ├── solver_dlx.cpp # 实验性 Dancing Links 求解器
│ ├── solver_dfs.cpp # 实验性 DFS 求解器
│ ├── tables.hpp # 位掩码查找表
│ └── ... # 其他辅助文件
├── lib/ # 编译产物(.so)
├── tests/ # 测试与基准
│ ├── README.md # 详细文档:测试体系说明
│ ├── test_solver.py # 统一求解器性能测试(bitmask + tdoku)
│ ├── test_solver_tdoku.py # Tdoku 兼容入口
│ ├── verify.cpp # 求解精度验证
│ ├── bench_single.cpp # 纯 C 性能基准
│ ├── bench_multi.cpp # 多轮基准(perf 采样)
│ ├── test_e2e.py # curl 端到端测试(功能+压测)
│ ├── tools/ # PGO 训练程序
│ ├── images/ # 测试用数独图片
│ ├── ir_bench/ # 图像识别基准测试(对比/诊断/参数扫描)
│ └── ground_truth/ # 用户标注的基准真相(启用反馈模式后生成,不纳入版本控制)
├── data/ # 测试题库(9 个数据集, 3.8M+ 谜题)+ MNIST(自动下载)
├── templates/ # Web GUI 页面模板
│ └── index.html
├── static/ # 前端静态资源
│ ├── style.css
│ └── app.js
运行时性能
Web 服务层面的优化:
- ORJSON:使用 orjson 替代 stdlib json,序列化快 2-5x
- LRU 缓存:最近 128 次求解结果自动缓存,重复提交零开销
- uvloop + httptools:高性能事件循环和 HTTP 解析器
- 输入校验:Pydantic v2 校验 81 元素长度和 0-9 值域,非法输入在到达 C++ 求解器前被拦截
- 日志:结构化 logging 替代 print,记录每次请求耗时
图像识别流水线优化:
- 圆形遮罩预计算为模块级常量,消除 81×1600 次 Python 循环
- NumPy 高级索引替代显式 for 循环
torch.inference_mode()替代torch.no_grad()
C++ 求解器:
- 统一 C ABI 接口:
SudokuBitmaskSolver(const char *puzzle, size_t limit, uint32_t flags, char *solution, size_t *num_guesses)— 81 字符输入(1-9/.),返回找到的解的数量,Web 服务默认使用此接口 - 切换求解器:在
main.py中修改两行即可切换:将lib/solver_bitmask.so改为lib/solver_tdoku.so,SudokuBitmaskSolver改为TdokuSolverDpllTriadSimd(Tdoku 需 AVX512 指令集) - 循环展开 (
-funroll-loops) 提升紧凑循环性能 - 深度溢出不再调用
exit(0),改为返回错误码
环境要求
| 依赖 | 版本 | 说明 |
|---|---|---|
| Python | 3.10+ | |
| g++ | 支持 C++17 | tdoku 求解器需 AVX512 指令集 |
| CMake | 3.16+ |
Linux
Debian / Ubuntu (apt)
sudo apt-get install -y build-essential cmake
RHEL / CentOS / Fedora (yum / dnf)
# RHEL 7 / CentOS 7
sudo yum install -y gcc-c++ make cmake
# RHEL 8+ / Fedora
sudo dnf install -y gcc-c++ make cmake
# CPU 版 torch(避免拉下数 GB 的 NVIDIA 包)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
# Python 依赖
pip install -e .
# 解压谜题数据集
unzip data.zip
# PGO 编译 C++ 求解器(推荐,性能提升约 17%)
bash build_pgo.sh
macOS
# 系统依赖(Xcode CLI 自带 g++,cmake 通过 Homebrew 安装)
brew install cmake
# CPU 版 torch
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
# Python 依赖
pip install -e .
# 解压谜题数据集
unzip data.zip
# PGO 编译 C++ 求解器(推荐,性能提升约 17%)
bash build_pgo.sh
Windows
# 系统依赖:安装 Visual Studio Build Tools(含 C++ 工具链)和 CMake
# CPU 版 torch
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
# Python 依赖
pip install -e .
# 解压谜题数据集
unzip data.zip
# 常规编译(PGO 需 g++,Windows 不适用)
mkdir build && cd build && cmake .. && cmake --build .
Windows 注意:
uvloop仅支持 Linux/macOS。启动前需将main.py中的loop="uvloop"改为loop="asyncio",或安装时跳过高性能组件:pip install uvicorn(不带[standard]extra),需手动补装httptools(Windows 兼容的 C 扩展)。
安装
# 1. 先装 CPU 版 torch(避免 PyPI 拉下数 GB 的 NVIDIA 包)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
# 2. 安装其余 Python 依赖(torch 已就位,跳过)
pip install -e .
# 开发/测试额外依赖:
# pip install -e ".[dev]"
# 3. 解压谜题数据集(PGO 训练和测试需要)
unzip data.zip
# 4. 编译 C++ 求解器(PGO 推荐,性能提升约 17%)
bash build_pgo.sh
# 5. 启动服务
cd .. && python3 main.py
# 浏览器打开 http://localhost:8000,上传数独图片即可使用
CNN 模型(
models/sudoku_cnn.pth、models/cell_binary.pth)已纳入版本控制,安装后可直接使用图像识别。如需用自己的数据重新训练或微调,见下方 训练 CNN 模型。
清理构建产物(仅清理
lib/*.so、build/、__pycache__/,不影响模型文件):cmake --build build --target clean_artifacts
编译 C++ 求解器
推荐使用 PGO (Profile-Guided Optimization) 构建,可额外获得约 17% 的性能提升:
# 一键 PGO 构建(默认生成 lib/solver_bitmask.so)
bash build_pgo.sh
# 自定义训练数据集(多文件)
PUZZLE_FILES="data/puzzles2_17_clue data/puzzles6_forum_hardest_1106" bash build_pgo.sh
PGO 构建流程:
- 插桩编译 (
-fprofile-generate):生成带计数器插桩的 .so - 训练运行:逐题求解训练集谜题,收集 profile 数据(默认用 49,162 个 17-clue 谜题)
- 优化编译 (
-fprofile-use):基于 profile 数据重新编译,优化分支预测、内联决策和代码布局
环境要求:g++(需支持 -fprofile-generate/-fprofile-use)。
常规编译(无 g++ 或快速构建时使用):
mkdir build && cd build && cmake .. && cmake --build .
编译产物输出到 lib/ 目录:
lib/solver_bitmask.so— 位运算回溯求解器(SudokuBitmaskSolver接口,81 字符输入)lib/solver_tdoku.so— Tdoku SIMD 求解器(需 AVX512VL/BITALG)
训练 CNN 模型
cd training
python3 train.py # 数字分类 CNN(识别 1-9)
python3 train_binary.py # 二分类 CNN(判别空格 / 有数字)
数字分类训练流程:
- MNIST 数据集预训练(数字 1-9,5 个 epoch)
- 自定义数据微调(30 个 epoch)
- GT 数据微调(15 个 epoch,从 ground truth 图片提取)
- 最优模型保存至
models/sudoku_cnn.pth
二分类训练保存至 models/cell_binary.pth。
启动 API 服务
python3 main.py --help # 查看所有选项
python3 main.py # 默认:8 workers, warning 日志
python3 main.py --workers 1 # 单 worker
python3 main.py --port 9000 # 指定端口
python3 main.py --log-level info # INFO 级别日志(每请求可见)
| 参数 | 默认值 | 说明 |
|---|---|---|
--host |
0.0.0.0 |
绑定地址 |
--port, -p |
8000 |
绑定端口 |
--workers, -w |
cpu_count() // 2 |
Worker 进程数 |
--log-level |
warning |
日志级别:debug/info/warning/error/critical |
--enable-feedback |
关闭 | 启用图像识别反馈功能(保存更正结果 + 原图) |
API 接口
POST / — 求解数独
请求体:
{"asks": [8,0,0,0,0,0,0,0,0, 0,0,3,6,0,0,0,0,0, ...]}
81 个整数的一维数组,0 表示空格。校验:必须恰好 81 个元素,每格 0-9,否则返回 422。
POST /uploadfile/ — 图片识别
上传数独图片(multipart form-data),返回识别出的 9×9 矩阵。
GET / — Web GUI
启动服务后浏览器打开 http://localhost:8000,提供完整的可视化操作界面:
┌─────────────────────────────────────────────────────┐
│ [上传区域] 点击或拖拽数独图片 │
│ ┌──────────────────────────────────────────────┐ │
│ │ 📋 图片预览 │ │
│ └──────────────────────────────────────────────┘ │
│ [上传并识别] [求解] [清空] │
│ │
│ ┌─────── 题目(可编辑) ──────┐ ┌─── 解答 ───────┐ │
│ │ 8 · · │ · · · │ · · · │ │ 8 1 2 │ 7 … │ │
│ │ · · 3 │ 6 · · │ · · · │ │ 9 4 3 │ 6 … │ │
│ │ · 7 · │ · 9 · │ 2 · · │ │ 5 7 6 │ 1 … │ │
│ │ ────────┼─────────┼──────── │ │ ────────┼───── │ │
│ │ · 5 · │ · · 7 │ · · · │ │ 1 5 4 │ 3 … │ │
│ │ … │ │ │ │ … │ │ │
│ └──────────────────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────┘
交互流程:
- 上传图片:点击、拖拽数独照片到上传区域,或 Ctrl+V 粘贴剪贴板中的图片
- 识别:点击「上传并识别」,CNN 自动提取数字填入左侧网格(蓝色)
- 编辑修正:点击格子直接修改识别错误的数字(绿色),方向键导航
- 求解:点击「求解」,C++ 求解器计算结果,右侧展示解答(紫色=求解器填入)
启用反馈模式 (--enable-feedback) 后,额外提供:
- 更正识别结果:手动修正后的题目可保存为基准真相(Ground Truth),附带原图
- 自动对比:再次上传同一张图时,自动加载已保存的更正结果,标出与 AI 识别的差异(橙色虚线=不同,绿色=一致)
- 切换视图:双击「题目」标题可在更正结果和 AI 识别结果之间切换
测试
求解器性能
cd tests && python3 test_solver.py # bitmask(默认)
cd tests && python3 test_solver.py --solver tdoku # tdoku
cd tests && python3 test_solver.py --list # 列出可用数据集
求解精度验证
验证 49,162 个 17-clue 谜题的行/列/宫完整性及线索保留:
cd build && cmake --build . --target verify -j$(nproc) && ./verify
# 预期: Verified 49162 puzzles: 49162 passed, 0 failed
C++ 性能基准
绕过 Python ctypes 开销,测量纯 C++ 求解时间:
cd build && g++ -O2 -std=c++17 -o ../tests/bench_single ../tests/bench_single.cpp -ldl
cd tests && ./bench_single
E2E 测试
通过 HTTP 请求测试 main.py 的可用性和性能(自动启动/关闭服务):
python3 tests/test_e2e.py # 功能测试
python3 tests/test_e2e.py --mode stress --requests 100 # 压测
python3 tests/test_e2e.py --mode stress-curl --requests 100 # 仅 curl 压测
python3 tests/test_e2e.py --mode stress-curl --requests 200 --concurrency 30
python3 tests/test_e2e.py --mode stress-ir --requests 100 # 仅图像识别压测
图像识别
python3 -m sudoku.pipeline --image path/to/image.jpg
更多测试细节(PGO 训练、perf 采样、添加新测试等)见 tests/README.md。
Docker 部署
docker build -t sudoku-api .
docker run -p 80:80 sudoku-api
产物说明
项目中各目录下的文件按性质分为源码(git 追踪)和产物(通过脚本/构建生成,gitignore 排除)。以下是全部产物的来源与清理方式。
| 产物 | 来源 | git 追踪? | 清理方式 |
|---|---|---|---|
lib/*.so |
cmake --build build |
否 | cmake --build build --target clean_artifacts |
build/ |
cmake 构建 | 否 | cmake --build build --target clean_artifacts(或 rm -rf build/) |
*.gcno |
PGO 插桩编译(随 .o 生成于 build/) |
否 | 随 build/ 一起清理 |
data/MNIST/ |
train.py 自动下载(torchvision) |
否 | rm -rf data/MNIST/ |
data/puzzles* |
解压 data.zip 得到(未纳入版本控制) |
否 | 手动删除 |
data.zip |
谜题数据集压缩包(纳入版本控制) | 是 | 勿删 — unzip data.zip 解压 |
models/sudoku_cnn.pth |
python3 training/train.py |
是 | rm models/sudoku_cnn.pth(需重新训练) |
models/cell_binary.pth |
python3 training/train_binary.py |
是 | rm models/cell_binary.pth(需重新训练) |
models/*_phase*.pth |
train.py 中间 checkpoint |
否 | rm models/*_phase*.pth |
training/samples.npy |
手动标注(450 张 20×20 印刷体数字) | 是 | 勿删 — Phase 2 微调的训练数据 |
training/label.npy |
手动标注(对应数字标签 1-9) | 是 | 勿删 — 配套 samples.npy |
training/gt_*.npy |
python3 training/extract_gt_samples.py |
否 | rm training/gt_*.npy |
__pycache__/, *.pyc |
Python 运行时 | 否 | find . -type d -name __pycache__ -exec rm -rf {} + |
tests/ground_truth/ |
Web GUI 反馈模式 (--enable-feedback) |
是 | 勿删 — 图像识别基准真相标注 |
perf.data* |
perf record |
否 | rm -f perf.data* |
tests/bench_*, tests/verify, tests/tools/pgo_train |
手动编译的 C 测试程序 | 否 | rm tests/bench_* tests/verify tests/tools/pgo_train |