准备 - core:内置官方字符集(OLD/BETA)与 ModelMetadata::from_builtin_* 构造器 - ort:导出 Session、实现 Info、修正 cuda feature 接线、共享推理工具 - tract2:包名更名(原 ddddocr-tract 已被占用)并完成规范整改 - 集成测试按领域拆分(ocr / det / slide / common / api_surface) - 发布准备:Cargo.toml 元数据、workspace 版本 0.2.4、LICENSE/ NOTICE、README 模型下载说明
ddddocr-rs
带带弟弟 OCR(ddddocr) 的 Rust 移植版:提供验证码 OCR 识别、目标检测与滑块匹配能力。核心库与推理引擎解耦,同一套 API 可切换 Tract 或 ONNX Runtime 后端。
架构
项目为 Cargo workspace,包含三个 crate:
| crate | 说明 |
|---|---|
ddddocr-core |
引擎无关的核心库:OCR / 目标检测 / 滑块匹配、模型元数据与图像预处理 |
ddddocr-ort |
ONNX Runtime 推理后端(可选 cuda feature 启用 GPU 加速) |
ddddocr-tract2 |
Tract(纯 Rust)推理后端 |
ddddocr-core 通过 traits::InferenceEngine / OcrEngine / DetEngine 抽象推理能力,由 ddddocr-ort / ddddocr-tract2 实现,业务代码只依赖核心库接口即可。
快速开始
在 Cargo.toml 中添加:
[dependencies]
ddddocr-core = "0.2"
ddddocr-ort = "0.2" # 或 ddddocr-tract2 = "0.2"
核心库自带一个不依赖真实模型的演示示例(用假引擎演示完整调用链):
cargo run -p ddddocr-core --example quick_start
真实推理需要自行准备 ONNX 模型文件(crate 包内不包含模型)。以 ORT 后端为例:
use ddddocr_core::traits::{Info, Loader};
use ddddocr_core::{ModelMetadata, Normalization, Ocr, Resize};
// 1. 构建会话(等价写法:ddddocr_tract2::loader::ModelLoader)
let session = ddddocr_ort::loader::ModelLoader::default()
.build_for_path("models/common.onnx")?;
// 2. 组装 OCR 运行时
let metadata = ModelMetadata::from_static_slice(
&["a", "b"], // 字符集
false, // 非单字模型
Resize::DynamicWidth(64), // 高度固定 64、宽度等比缩放
1, // 灰度单通道
Normalization::MinusOneToOne,
);
let ocr = ddddocr_ort::OcrRuntime::new(session, metadata);
// 3. 识别图片
let result = Ocr::builder().build_with(&ocr).predict(&image)?;
println!("识别结果: {}", result);
目标检测与滑块匹配类似:Detector::new(&engine).predict(&image) 返回检测框列表;Slider::new().slide_match(target, background, simple_target) 返回匹配坐标与置信度。
模型下载
OCR / 目标检测需要 ONNX 模型文件。官方模型位于 ddddocr 仓库 ddddocr/ 目录,下载后放入仓库根目录的 models/ 文件夹:
| 文件 | 大小 | 用途 | 直链 |
|---|---|---|---|
common.onnx |
约 51.6 MB | 新版 OCR 模型(默认) | 下载 |
common_det.onnx |
约 19.2 MB | 目标检测模型 | 下载 |
common_old.onnx |
约 13 MB | 旧版 OCR 模型 | 下载 |
注意:
ddddocr-tract2不支持旧版模型common_old.onnx,请使用common.onnx。字符集配对:
common.onnx对应内置 Beta 字符集(Charset/ModelMetadata::from_builtin_beta,归一化MinusOneToOne);common_old.onnx对应旧版字符集(from_builtin_old,归一化ZeroToOne)。仓库测试使用的
common_sml2h3_f32.onnx、common_huashi666_i64.onnx为社区转换的 f32 / i64 变体模型(与common.onnx同源),不在上述官方目录中,需自行获取。
字符集与内置默认值
OCR 模型的字符集(token 列表)是模型的一部分:字符 i 对应模型输出 logits 的第 i 列,必须与模型训练时一致,否则识别结果会错位。
字符集有两种提供方式:
- 通过模型元数据 JSON 的
charset字段(Metadata::from_json_str/from_json_bytes自动解析); - 代码内显式指定:
ModelMetadata::from_static_slice(&["", "a", "b"], ...)或Charset::new(...)。
ddddocr-core 内置官方模型的默认字符集(旧版 CHARSET_OLD 与 Beta CHARSET_BETA),作为免配置的快速通道。字符集数据独立存放在 ddddocr-core/src/ocr/builtin.rs 私有模块中(与业务逻辑分离),通过 ModelMetadata 的公开构造方法使用:
use ddddocr_core::{ModelMetadata, Normalization, Resize};
// 官方旧版模型配套
let meta = ModelMetadata::from_builtin_old(
false,
Resize::DynamicWidth(64),
1,
Normalization::ZeroToOne,
);
// 官方 Beta 模型配套
let meta = ModelMetadata::from_builtin_beta(
false,
Resize::DynamicWidth(64),
1,
Normalization::MinusOneToOne,
);
数据内置于代码,不依赖外部文件。若使用自有模型,请仍以元数据 JSON 或 from_static_slice 指定匹配的字符集。
滑块匹配核心知识点
项目实现两种匹配模式,底层逻辑与 OpenCV 对齐:
| 模式 | 算法原理 | 适用场景 | 备注 |
|---|---|---|---|
| 边缘模式(Edge-based) | 基于 Canny 边缘检测提取轮廓后匹配 | 推荐方案,适用于绝大多数拼图滑块 | 天然免疫拼图周边透明/黑色留白干扰,坐标最精准 |
| 简单模式(Simple/Gray) | 基于灰度像素值做归一化互相关(NCC) | 无明显边缘、靠颜色差异识别的场景 | 对背景和透明边框敏感,可能存在重心偏移 |
关键点:
- 简单模式采用归一化互相关(NCC),与 OpenCV 的
TM_CCORR_NORMED完全一致。 - 若拼图原图四周带透明留白,本项目会将留白计入整张图片框中心;OpenCV 默认的 CCOEFF 会做均值中心化削弱留白影响。
- 图像预处理与 Python 链路保持一致:灰度权重采用 OpenCV 标准感光公式
0.299R + 0.587G + 0.114B;PNG 转 RGB 时透明区域填充为黑色;返回坐标为匹配区域的几何中心(x + w/2, y + h/2)。
若识别结果在 X 轴上有约 10px 固定误差,通常是滑块原图自带透明边距所致。此时请确保
simple_target = false,边缘模式会自动锁定拼图实体并忽略留白干扰。
致谢
- sml2h3 (ddddocr) - 模型权重与原始逻辑。
- Sonos (tract) - 纯 Rust ONNX 推理引擎。
- pyke.io (ort) - ONNX Runtime 的 Rust 绑定。
- Microsoft (ONNX Runtime) - ONNX 推理引擎。
License
MIT OR Apache-2.0,许可证文本见仓库根目录的 LICENSE-MIT 与 LICENSE-APACHE。