今天正式发布 SimdPaddleOCR (NuGet: Sdcb.SimdPaddleOCR)。这是一个完全用 C# 编写的完整 OCR 推理引擎。它不依赖 Paddle Inference,不依赖 ONNX Runtime,也不需要附带 OpenCV 的原生动态链接库。

如果你现在去翻这个 GitHub 仓库的侧边栏,会看到语言统计条是纯紫色的------100% C#。在托管环境里从头跑到尾,没有第二种语言。
维护 PaddleSharp 和 OpenVINO.NET 这些年,我见过太多项目在生产环境里遇到五花八门的报错。C++ 引擎本身很强,P/Invoke 写起来也不难,真正的痛点永远在部署和分发 :Windows x64 跑通了,换到 Linux ARM 就报错;开发机没问题,客户机缺 .so、缺 VC++ 运行时、或者 CPU 指令集不匹配。你以为你只是在调用一个 OCR,实际上你被迫维护了一套跨平台的原生发行矩阵。
SimdPaddleOCR 的核心目的,就是把 OCR 推理这件脏活累活,彻底拉回我们熟悉的托管世界。没有 native 依赖,就没有"换个环境就跑不起来"的破事。
它能做什么?
官方的 PaddleOCR 是一个庞大的文档 AI 生态,而这个库的定位非常聚焦:场景 OCR 的端到端推理。它完整实现了 PP-OCRv6 的 DET(检测) + CLS(方向分类) + REC(识别) 链路。
为了做到 100% 托管,库里自带了一个轻量级的 C# ONNX 解释器。模型直接打包进程序集资源里,加载时不需要往磁盘解压临时文件。
还有一点很关键:它的核心 API 只接收纯粹的 8-bit BGR 内存数据。
以前做 PaddleSharp 时,为了示例好写,我把图像解码强行绑定在了 OpenCvSharp 上。结果就是,调用方哪怕只是想传个图,也得被迫引入一套 OpenCV 的原生 runtime。
这一次,选择权完全交还给你。无论你的项目里用的是 ImageSharp、SkiaSharp、OpenCvSharp 还是最古老的 System.Drawing,只要把图像转成 BGR 字节数组塞给它,推理就能跑。不越俎代庖去处理文件 IO,也不强绑任何图像库。
性能表现
大家最关心的肯定是:纯 C# 写的推理,速度会不会很拉垮?
在这个项目初期,我参考了 lw.PPOCR.C(一份非常优秀的纯 C PP-OCRv6 tiny 推理引擎)。经过对 C# 内存布局和 SIMD 指令的深度重构,现在的结论是:在同等模型下,C# 版本的端到端速度比纯 C 版本更快(当然,代价是托管内存的上涨,这点原生的 C 依然更具优势)。
GitHub Actions,win-x64,tiny 模型,同一份 99 张测试图(不含 warmup),端到端均值:
| workers | C# | C | C 相对 C# |
|---|---|---|---|
| 1 | 296.6 ms | 485.7 ms | 慢 1.64× |
| 4 | 168.4 ms | 393.3 ms | 慢 2.34× |
具体它是如何利用 .NET 的 Vector<T>、甚至在 Zen 5 上榨取 AVX-512 性能的,我会在周三的连载里放详细的对照表。
在目标框架上,它同时支持 net10.0 和 netstandard2.0。
- 如果你用最新的 .NET 10,能吃满完整的硬件 SIMD 加速,且完美支持 NativeAOT。
- 如果你在维护老旧的 .NET Framework 4.8 遗留系统,它一样能跑。
(注:当前版本仅支持 CPU 推理,暂无 GPU 计划)
十分钟跑起来
在你的项目里装上核心包和 tiny 中文模型(装 tiny 会自动传递引用方向分类包 TextLineOrientation):
powershell
dotnet add package Sdcb.SimdPaddleOCR
dotnet add package Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny
# 这里以 ImageSharp 为例,你也可以换成自己喜欢的解码库
dotnet add package SixLabors.ImageSharp --version 3.1.11
一段最基础的 ImageSharp 3 解析图片并进行 OCR 的完整代码:
csharp
using Sdcb.SimdPaddleOCR;
using Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
// 加载模型(模型在程序集内,直接读取)
using PaddleOcrAll ocr = await PaddleOcrAll.LoadAsync(ChineseV6TinyModels.Default);
// 用第三方库读图并提取 BGR 像素
using Image<Bgr24> image = await Image.LoadAsync<Bgr24>("sample.jpg");
byte[] bgr = new byte[image.Width * image.Height * 3];
image.CopyPixelDataTo(bgr);
// 核心推理
PaddleOcrResult result = ocr.Run(bgr, image.Width, image.Height);
Console.WriteLine(result.Text);
(仓库 README 里也提供了 SkiaSharp、OpenCvSharp5 和 WinForms LockBits 的跑法代码。)
包与模型选择
| NuGet 包 | 作用说明 |
|---|---|
Sdcb.SimdPaddleOCR |
纯托管推理核心库(支持 net10.0;netstandard2.0) |
Sdcb.SimdPaddleOCR.ModelProvider |
模型契约(通常被自动传递引用) |
Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny |
PP-OCRv6 tiny 模型包 |
Sdcb.SimdPaddleOCR.Models.ChineseV6Small |
PP-OCRv6 small 模型包 |
Sdcb.SimdPaddleOCR.Models.ChineseV6Medium |
PP-OCRv6 medium 模型包 |
Sdcb.SimdPaddleOCR.Models.TextLineOrientation |
文本行方向 CLS 模型包 |

建议日常使用无脑选 Tiny,体积小速度快。如果有更高的字准要求,再往 Small 或 Medium 提。
当然,如果你本地已经有了自己的 ONNX 文件和字典,核心库也支持直接从本地路径加载,不强求使用模型包。许可证方面为 Apache-2.0,模型来源细节请参考仓库内的 THIRD-PARTY-NOTICES.md。
如果你的 .NET 项目以前因为原生依赖的部署灾难而对 OCR 敬而远之,现在可以试试这个纯托管的解法。
开源仓库: https://github.com/sdcb/SimdPaddleOCR
NuGet 搜索: Sdcb.SimdPaddleOCR
喜欢的朋友可以点个 Star,或者在 Issues 里提建议和问题。
也可以加入 SimdPaddleOCR 微信群:
如果微信过期,请加入 C# / .NET 计算机视觉交流 QQ 群:579060605。