SimdPaddleOCR发布——一个纯 C# 的完整 OCR 推理库

今天正式发布 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.0netstandard2.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