SimdPaddleOCR
A complete OCR inference engine written entirely in C#. No Paddle Inference, no ONNX Runtime, no native OpenCV.
dotnet add package Sdcb.SimdPaddleOCR
dotnet add package Sdcb.SimdPaddleOCR.Models.ChineseV6TinyWhy
A clean-slate successor to PaddleSharp and OpenVINO.NET
PaddleSharp and OpenVINO.NET brought OCR to a lot of .NET apps — but both drag along tens to hundreds of MB of native runtime. New platform or CPU architecture? New native packages, painful deployment and debugging.
SimdPaddleOCR takes a different route: models are loaded by a bundled managed ONNX interpreter; convolution, GEMM and friends are hand-written with C# hardware intrinsics, dispatching at runtime to AVX-512, AVX2, NEON or portable Vector code. One NuGet package runs everywhere — including NativeAOT and .NET Framework 4.8.
The core API just takes pixel memory (BGR24 / RGB24 / BGRA32 / RGBA32) and never forces an imaging library on you — use ImageSharp, SkiaSharp, OpenCvSharp or System.Drawing.
Teal: GPU backends, new in 2.0, net10.0 only.
Quick start
Bring your own imaging library
using System.Runtime.InteropServices;
using Sdcb.SimdPaddleOCR;
using Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using PaddleOcrAll ocr = await PaddleOcrAll.LoadAsync(ChineseV6TinyModels.Default);
// Clone Default:改 Configuration.Default 会丢掉 PNG/JPEG 解码器
Configuration cfg = Configuration.Default.Clone();
cfg.PreferContiguousImageBuffers = true;
using Image<Rgba32> image = await Image.LoadAsync<Rgba32>(
new DecoderOptions { Configuration = cfg }, "sample.jpg");
if (!image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> memory))
{
Rgba32[] copy = new Rgba32[image.Width * image.Height];
image.CopyPixelDataTo(copy);
memory = copy;
}
PaddleOcrResult result = ocr.Run(MemoryMarshal.AsBytes(memory.Span),
image.Width, image.Height, format: ImagePixelFormat.Rgba32);
Console.WriteLine(result.Text);using SkiaSharp;
using SKBitmap bitmap = SKBitmap.Decode("sample.jpg").Copy(SKColorType.Bgra8888);
unsafe
{
PaddleOcrResult result = ocr.Run(
new ReadOnlySpan<byte>((byte*)bitmap.GetPixels(), bitmap.RowBytes * bitmap.Height),
bitmap.Width, bitmap.Height, bitmap.RowBytes, ImagePixelFormat.Bgra32);
}using OpenCvSharp;
using Mat image = Cv2.ImRead("sample.jpg", ImreadModes.Color);
int stride = (int)image.Step();
unsafe
{
PaddleOcrResult result = ocr.Run(
new ReadOnlySpan<byte>((byte*)image.Data, stride * image.Height),
image.Width, image.Height, stride, ImagePixelFormat.Bgr24);
}using System.Drawing;
using System.Drawing.Imaging;
using Bitmap bitmap = new("sample.jpg");
BitmapData data = bitmap.LockBits(new(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
try
{
unsafe
{
PaddleOcrResult result = ocr.Run(
new ReadOnlySpan<byte>((byte*)data.Scan0, data.Stride * bitmap.Height),
bitmap.Width, bitmap.Height, data.Stride, ImagePixelFormat.Bgra32);
}
}
finally { bitmap.UnlockBits(data); }using PaddleOcrAll ocr = await PaddleOcrAll.LoadAsync(ChineseV6TinyModels.Default,
new PaddleOcrOptions
{
Detector = new PaddleOcrDetectorOptions { Backend = OcrBackend.Vulkan },
Recognizer = new PaddleOcrRecognizerOptions { Backend = OcrBackend.Vulkan },
Classifier = new PaddleOcrClassifierOptions { Backend = OcrBackend.Vulkan },
});
// 默认 OcrBackend.Auto:有满足条件的 GPU 就用,否则留在 CPU。
// macOS arm64 上把 Vulkan 换成 OcrBackend.Metal。Performance
Faster and leaner, every release
Numbers from the per-device reports under docs/ (median wall-clock, warm-up excluded; same-machine CPU vs Vulkan / Metal GPU). CPU numbers are re-measured by CI on Windows / Linux / macOS for every change.
RTX 3080 Ti · end-to-end per image
Ryzen 7 5800X CPU vs Vulkan · 100 images · 2.0
Intel Arc B580 · end-to-end per image
CPU vs Vulkan · 三轮中位 · 2.0
Peak working set
tiny · 4 workers
Local CER: tiny 2.78% → 2.37%, small 0.60% → 0.41%, medium 0.67% → 0.14%.
Platforms
One package, everywhere
- Targets net10.0 and netstandard2.0 (incl. .NET Framework 4.8)
- NativeAOT compatible (IsAotCompatible)
- Models load straight from embedded resources — no extraction, no temp files
- Measured on Snapdragon 8 Gen 3, CPU and Vulkan
| OS | CPU | GPU (2.0) |
|---|---|---|
| Windows | x64x86ARM64 | Vulkan |
| Linux | x64ARM64 | Vulkan |
| macOS | x64ARM64 | Metal |
| Android | ARM64 | Vulkan |
NuGet
Packages & models
Total downloads 5.3k
Releases
Release history
The series
Dev diary, 0 → 2.0
SimdPaddleOCR 2.0:再快15倍!见证纯C#驱动的GPU性能核弹
大家好,SimdPaddleOCR 今天发布 2.0。这是项目第一次升大版本号,原因很简单:1.x 一直在折腾 CPU 上的 SIMD,2.0 加上了 GPU 后端,Windows / Linux / 安卓走 Vulkan,macOS 走 Metal。在我的 RTX 3080 Ti 上,medium
Fable 5.1操刀,内存腰斩,外星科技——SimdPaddleOCR 1.4 发布!
大家好,我非常自豪地宣布纯 C# 写的 SimdPaddleOCR 今天发布 1.4 版本,这个版本有许多重大改进,其中有一些甚至说得上是“外星科技”! 对于刚认识这个项目的朋友,先交代一下我们的硬核定位:这是一个纯 C# 实现的 PP-OCRv6 引擎。它不需要 Paddle Inference,
AVX性能暴涨135%,吊打OpenVINO.NET——SimdPaddleOCR 1.3发布!
先看性能跑分,机器是我自己的主力开发机 Ryzen 7 5800X(16 逻辑核,AVX2),Windows 11,PP-OCRv6,4 个行级 worker,仓库里会生成 100 张合成图,去掉第一张预热,统计 99 张,长这个样子: 耗时是每张图的平均毫秒。C 引擎换成了较新的 lw.PPOCR
ARM64端到端再提速40%:SimdPaddleOCR 1.2 发布!
前两天连载了 SimdPaddleOCR 的发布 和 C# 手写向量化的底层逻辑。1.1 版本在 win-x64 上已经基本站稳了脚跟,但短板也很明显:ARM64 环境下虽然能跑,但速度明显慢了一截。 现在 ARM64 早就不是小众平台了——MacBook、手机、Windows on ARM 以及越
C# 手写向量化能追上 C 吗?
昨天发布了 SimdPaddleOCR,评论区和群里最多的一类问题是:纯 C# 写的推理,凭什么比纯 C 还快? 有人觉得肯定是偷偷调了 ONNX Runtime,有人觉得是 C 那边写得太烂,还有人直接说"C# 就不该谈性能"。 这篇不谈 OCR,谈一个更朴素的问题:C# 到底有没有能力写出和 C
SimdPaddleOCR发布——一个纯 C# 的完整 OCR 推理库
今天正式发布 SimdPaddleOCR(NuGet: Sdcb.SimdPaddleOCR)。这是一个完全用 C# 编写的完整 OCR 推理引擎。它不依赖 Paddle Inference,不依赖 ONNX Runtime,也不需要附带 OpenCV 的原生动态链接库。 如果你现在去翻这个 Git

C#/.NET Computer Vision community
Scan to join the WeChat group. The QR code rotates weekly — if it has expired, join QQ group 579060605 instead.