Ddddocr
ddddocr rust 版本,ocr_api_server rust 版本,二进制版本,验证码识别,不依赖 opencv 库,跨平台运行,AI MCP 支持,a simple OCR API server, very easy to deploy。
Install / Use
/learn @86maid/DdddocrREADME
简介
ddddocr rust 版本。
ocr_api_server rust 版本。
二进制版本,验证码识别,不依赖 opencv 库,跨平台运行。
a simple OCR API server, very easy to deploy。
<img alt="github" src="https://img.shields.io/badge/github-86maid/ddddocr- ?logo=github" height="20">
目录
环境支持
| 系统 | CPU | GPU | 备注 | | ---------------- | --- | --- | ---------------------------------------------------------------------------------------------------- | | Windows 64位 | √ | ? | 部分版本 Windows 需要安装 <a href="https://www.ghxi.com/yxkhj.html">vc 运行库</a> | | Windows 32位 | √ | ? | 不支持静态链接,部分版本 Windows 需要安装 <a href="https://www.ghxi.com/yxkhj.html">vc 运行库</a> | | Linux 64 / ARM64 | √ | ? | 可能需要升级 glibc 版本, <a href=https://www.cnblogs.com/fireinstone/p/18169273>升级 glibc 版本</a> | | Linux 64 / MUSL | √ | ? | 不需要 glibc,静态链接 | | Linux 32 | × | ? | | | Macos X64 | √ | ? | M1/M2/M3 ... 芯片参考<a href="https://github.com/sml2h3/ddddocr/issues/67"> #67 </a> |
安装步骤
lib.rs 实现了 ddddocr。
main.rs 实现了 ocr_api_server。
model 目录是模型与字符集。
依赖本库 ddddocr = {git = "https://github.com/86maid/ddddocr.git", branch = "master"}
开启 cuda 特性 ddddocr = { git = "https://github.com/86maid/ddddocr.git", branch = "master", features = ["cuda"] }
支持静态和动态链接,默认使用静态链接,构建时将会自动下载链接库,请设置好代理,cuda 特性不支持静态链接(会自己下载动态链接库)。
如有更多问题,请跳转至疑难杂症部分。
如果你不想从源代码构建,这里有编译好的二进制版本。
还可以使用配置好的 Github Action 进行构建。
使用文档
OCR 识别
内容识别
主要用于识别单行文字,即文字部分占据图片的主体部分,例如常见的英数验证码等,本项目可以对中文、英文(随机大小写or通过设置结果范围圈定大小写)、数字以及部分特殊字符。
let image = std::fs::read("target.png").unwrap();
let mut ocr = ddddocr::ddddocr_classification().unwrap();
let res = ocr.classification(image).unwrap();
println!("{:?}", res);
旧模型
let image = std::fs::read("target.png").unwrap();
let mut ocr = ddddocr::ddddocr_classification_old().unwrap();
let res = ocr.classification(image).unwrap();
println!("{:?}", res);
支持识别透明黑色 png 格式的图片,使用 png_fix 参数
classification_with_png_fix(image, true);
颜色过滤
支持以下预设颜色:red(红色)、blue(蓝色)、green(绿色)、yellow(黄色)、orange(橙色)、purple(紫色)、cyan(青色)、black(黑色)、white(白色)、gray(灰色)。
let ddddocr = ddddocr_classification().unwrap();
// 只保留绿色
println!(
"{}",
ddddocr
.classification_with_filter(include_bytes!("../image/4.png"), "green")
.unwrap()
);
// 只保留红色和绿色
println!(
"{}",
ddddocr
.classification_with_filter(include_bytes!("../image/4.png"), ["red", "green"])
.unwrap()
);
// HSV 范围,每个元素是一个 (min_hsv, max_hsv) 的元组。
println!(
"{}",
ddddocr
.classification_with_filter(
include_bytes!("../image/4.png"),
[((40, 50, 50), (80, 255, 255))]
)
.unwrap()
);
参考例图
<img src="https://cdn.wenanzhe.com/img/20210715211733855.png" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/78b7f57d-371d-4b65-afb2-d19608ae1892.png" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20211226142305.png" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20211226142325.png" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/2AMLyA_fd83e1f1800e829033417ae6dd0e0ae0.png" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/aabd_181ae81dd5526b8b89f987d1179266ce.jpg" alt="captcha" width="150"> <br /> <img src="https://cdn.wenanzhe.com/img/2bghz_b504e9f9de1ed7070102d21c6481e0cf.png" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/0000_z4ecc2p65rxc610x.jpg" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/2acd_0586b6b36858a4e8a9939db8a7ec07b7.jpg" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/2a8r_79074e311d573d31e1630978fe04b990.jpg" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/aftf_C2vHZlk8540y3qAmCM.bmp" alt="captcha" width="150"> <img src="https://cdn.wenanzhe.com/img/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20211226144057.png" alt="captcha" width="150">目标检测
let image = std::fs::read("target.png").unwrap();
let mut det = ddddocr::ddddocr_detection().unwrap();
let res = det.detection(image).unwrap();
println!("{:?}", res);
参考例图

以上只是目前我能找到的点选验证码图片,做了一个简单的测试。
滑块匹配
算法非深度神经网络实现。
算法1
小滑块为单独的png图片,背景是透明图,如下图:

然后背景为带小滑块坑位的,如下图:

let target_bytes = std::fs::read("target.png").unwrap();
let background_bytes = std::fs::read("background.png").unwrap();
let res = ddddocr::slide_match(target_bytes, background_bytes).unwrap();
println!("{:?}", res);
如果小图无过多背景部分,则可以使用 simple_slide_match,通常为 jpg 或者 bmp 格式的图片
let target_bytes = std::fs::read("target.png").unwrap();
let background_bytes = std::fs::read("background.png").unwrap();
let res = ddddocr::simple_slide_match(target_bytes, background_bytes).unwrap();
println!("{:?}", res);
算法2
一张图为带坑位的原图,如下图:

一张图为原图,如下图:

let target_bytes = std::fs::read("target.png").unwrap();
let background_bytes = std::fs::read("background.png").unwrap();
let res = ddddocr::slide_comparison(target_bytes, background_bytes).unwrap();
println!("{:?}", res);
OCR 概率输出
为了提供更灵活的 ocr 结果控制与范围限定,项目支持对ocr结果进行范围限定。
可以通过在调用 classification_probability 返回全字符表的概率。
当然也可以通过 set_ranges 设置输出字符范围来限定返回的结果。
| 参数值 | 意义 | | ------ | ------------------------------------------------ | | 0 | 纯整数 0-9 | | 1 | 纯小写字母 a-z | | 2 | 纯大写字母 A-Z | | 3 | 小写字母 a-z + 大写字母 A-Z | | 4 | 小写字母 a-z + 整数 0-9 | | 5 | 大写字母 A-Z + 整数 0-9 | | 6 | 小写字母 a-z + 大写字母A-Z + 整数0-9 | | 7 | 默认字符库 - 小写字母a-z - 大写字母A-Z - 整数0-9 |
如果值为 string 类型,请传入一段不包含空格的文本,其中的每个字符均为一个待选词,例如:"0123456789+-x/="
let image = std::fs::read("image.png").unwrap();
let mut ocr = ddddocr::ddddocr_classification().unwrap();
// 数字 3 对应枚举 CharsetRange::LowercaseUppercase,不用写枚举
// ocr.set_ranges(3);
// 设置全局字符集
ocr.set_ranges("0123456789+-x/=");
// 或者,单次识别的字符集
// ocr.classification_probability_with_ranges(image, "0123456789+-x/=");
let result = ocr.classification_probability(image).unwrap();
println!("识别结果: {}", result.get_text());
println!("识别可信度: {}", result.get_confidence());
// 哦呀,看来数据有点儿太多了,小心卡死哦!
println!("概率: {}", result.json());
自定义 OCR 训练模型导入
支持导入 dddd_trainer 训练后的自定义模型。
use ddddocr::*;
let mut ocr = Ddddocr::with_model_charset(
"myproject_0.984375_139_13000_2022-02-26-15-34-13.onnx",
"charsets.json",
)
.unwrap();
let image_bytes = std::fs::read("888e28774f815b01e871d474e5c84ff2.jpg").unwrap();
let res = ocr.classification(&image_bytes).unwrap();
println!("{:?}", res);
ocr_api_server 例子
运行方式
Usage: ddddocr.exe [OPTIONS]
Options:
--address <ADDRESS>
监听地址。 [default: 0.0.0.0:8000]
--mcp
mcp 协议支持,与 only_mcp 互斥。
--only-mcp
仅开启 mcp 协议,不开启普通路由,与 mcp 互斥。
--ocr
开启内容识别,与 old 互斥。
--old
开启旧版模型内容识别,与 ocr 互斥。
--det
开启目标检测。
--slide
开启滑块和坑位识别。
--ocr-charset-range <OCR_CHARSET_RANGE>
全局默认字符集,用于概率识别, 如果 API 未提供字符集,则
Related Skills
himalaya
352.9kCLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
taskflow
352.9kname: taskflow description: Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layer
tmux
352.9kRemote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
Hook Development
111.5kThis skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.
