SimdPaddleOCR README

The project's README from github.com/sdcb/SimdPaddleOCR. As one markdown file: README.md.

Sdcb.SimdPaddleOCR test NuGet License: Apache-2.0 QQ

中文 | English

纯 C# PP-OCRv6 推理库:多平台 SIMD 优化、较低内存占用、高正确率。 自带托管 ONNX 解释器,不依赖 Paddle Inference、ONNX Runtime 或 OpenCV 原生库。

核心 API 只接收 BGR8 内存,不负责图片解码,因此不会强制引入 ImageSharp、SkiaSharp 或 OpenCvSharp。

快速开始

安装核心包和 tiny 模型(tiny 会传递引用 CLS 与 ModelProvider):

dotnet add package Sdcb.SimdPaddleOCR
dotnet add package Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny
dotnet add package SixLabors.ImageSharp --version 3.1.11

模型从程序集嵌入资源直接加载,不会解压或写入临时文件。输入为 8-bit BGR,stride = 0 表示紧密排列(width * 3)。

ImageSharp 3(推荐)

using Sdcb.SimdPaddleOCR;
using Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

using PaddleOcrAll ocr = await PaddleOcrAll.LoadAsync(ChineseV6TinyModels.Default);
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);

后续三个示例只演示如何解码到 BGR,加载与 Run 与上面相同。

SkiaSharp

using SkiaSharp;

SKBitmap bitmap = SKBitmap.Decode("sample.jpg")
    ?? throw new InvalidDataException("无法读取图片");
int stride = bitmap.Width * 3;
byte[] bgr = new byte[stride * bitmap.Height];
for (int y = 0; y < bitmap.Height; y++)
{
    for (int x = 0; x < bitmap.Width; x++)
    {
        SKColor color = bitmap.GetPixel(x, y);
        int offset = y * stride + x * 3;
        bgr[offset] = color.Blue;
        bgr[offset + 1] = color.Green;
        bgr[offset + 2] = color.Red;
    }
}

OpenCvSharp5

using System.Runtime.InteropServices;
using OpenCvSharp;

using Mat image = Cv2.ImRead("sample.jpg", ImreadModes.Color);
if (image.Empty()) throw new InvalidDataException("无法读取图片");
int rowBytes = image.Width * image.Channels();
byte[] bgr = new byte[rowBytes * image.Height];
for (int y = 0; y < image.Height; y++)
    Marshal.Copy(IntPtr.Add(image.Data, (int)(y * image.Step())), bgr, y * rowBytes, rowBytes);

Bitmap

using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

using Bitmap bitmap = new("sample.jpg");
int stride = bitmap.Width * 3;
byte[] bgr = new byte[stride * bitmap.Height];
Rectangle rectangle = new(0, 0, bitmap.Width, bitmap.Height);
BitmapData data = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
try
{
    for (int y = 0; y < bitmap.Height; y++)
        Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + y * (long)data.Stride), bgr, y * stride, stride);
}
finally
{
    bitmap.UnlockBits(data);
}

NuGet 包

NuGet 包 版本 说明
Sdcb.SimdPaddleOCR NuGet 纯托管推理核心(net10.0;netstandard2.0)
Sdcb.SimdPaddleOCR.ModelProvider NuGet 模型契约(IPaddleOcrModelProvider / PaddleOcrModelBundle),通常被传递引用
Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny NuGet PP-OCRv6 tiny DET+REC+字典;ChineseV6TinyModels.Default 含 CLS
Sdcb.SimdPaddleOCR.Models.ChineseV6Small NuGet PP-OCRv6 small;ChineseV6SmallModels.Default
Sdcb.SimdPaddleOCR.Models.ChineseV6Medium NuGet PP-OCRv6 medium;ChineseV6MediumModels.Default
Sdcb.SimdPaddleOCR.Models.TextLineOrientation NuGet PP-LCNet 文本行方向 CLS,被三个中文模型包传递引用

每个 IPaddleOcrModelProvider 提供 Name、Kind、Format、语言和版本元数据以及 OpenRead() / OpenReadAsync()。完整 OCR 组合由 PaddleOcrModelBundle 表达(DET、REC、字典和可选 CLS)。当前语言代码为 zh。单个模型也可被其他推理实现消费,例如 ChineseV6TinyModel.Detection.OpenReadAsync()。Model、PaddleOcrDetector、PaddleOcrClassifier、PaddleOcrRecognizer 和 PaddleOcrAll 均提供 Stream 加载入口;解析完成后不会继续保留完整的 ONNX 原始字节。

使用本地模型

核心不下载模型。使用本地 DET、CLS、REC 和字典文件时:

using Sdcb.SimdPaddleOCR;

using PaddleOcrAll ocr = await PaddleOcrAll.LoadAsync(
    detectionPath: "models/det.onnx",
    classificationPath: "models/cls.onnx",
    recognitionPath: "models/rec.onnx",
    dictionaryPath: "models/ppocr_keys.txt");

PaddleOcrOptions 里两套并行不要混用:DetIntraOpThreads 是检测图内的卷积线程 (一份 session,默认最多 8);LineWorkerCount 是一行一组的 CLS/REC worker 路数 (每路一个 session,上限,实际 min(请求, ProcessorCount);0 为 min(ProcessorCount, 4))。检测阈值、边界长度、方向分类、 动态识别宽度和 Session 缓存上限等也在同一组 options 里。

示例

四个示例共用 examples/sample.jpg,图片由示例负责解码并转换为 BGR:

dotnet run --project examples/ImageSharp.AspNetCore
dotnet run --project examples/OpenCvSharp5.Wpf -- path/to/image.jpg
dotnet run --project examples/SkiaSharp.Avalonia -- path/to/image.jpg
dotnet run --project examples/SystemDrawing.WinForms --framework net10.0-windows

Web 示例打开站点即可上传;API 为 POST /api/ocr(multipart/form-data 字段 file、model),文档在 /scalar。

常见问题

为什么调试时 OCR 识别特别慢?

调试器可能会在模块加载时取消 JIT 优化,使 OCR 的计算密集型代码无法获得应有的运行时优化,从而导致识别明显变慢。

请关闭该选项,然后重新启动调试会话:

支持范围

说明
目标框架 核心 net10.0;netstandard2.0;ModelProvider 与全部模型包为 netstandard2.0
推荐运行时 .NET 10:完整 x86 SIMD 与 NativeAOT(IsAotCompatible)
兼容运行时 netstandard2.0 可在 .NET Framework 4.8 等环境使用;编译时去掉 AVX / AVX-512 / VNNI 源,走 System.Numerics.Vector / 标量
CI 架构 Windows x64 / x86 / ARM64,Linux x64 / ARM64,macOS x64 / ARM64
SIMD .NET 10 运行时探测 AVX → AVX2 → AVX-512 / VNNI;无对应指令集或 ARM 时用 Vector/标量
输入 8-bit BGR 内存;无图片路径、文件或图片库 API
设备 CPU only,无 GPU
NativeAOT 裁剪发布时请保留核心程序集和所用模型程序集

许可证与第三方组件

本仓库中由本项目编写的源代码和文档采用 Apache License 2.0 发布。 Apache-2.0 提供明确的专利授权条款,更适合公开发布的库和 NuGet 包。

模型资源和第三方代码不因本项目许可证而被重新授权:

完整的第三方归属和分发说明见 THIRD-PARTY-NOTICES.md。PaddleOCR、PP-OCR 及相关名称归其 各自权利人所有,本项目不代表官方,也不构成官方背书。

性能

GitHub-hosted runner、PP-OCRv6 tiny、去掉首张 warmup 后的中位墙钟(2026-09,4 次 CI 合计):

平台 CPU ISA 中位 ms/图 工作集峰值 简评
win-x64 AMD EPYC 7763(4 vCPU) AVX2 238 ~790 MB 默认路径;正确率跨 ISA 不变
win-x64 netstandard2.0 同上 AVX2(Vector) 373 ~785 MB 约为 net10 AVX2 的 1.56×
linux-arm64 Neoverse N2 AdvSimd 273 ~847 MB replica 间几乎一条直线

同机引擎对比(win-x64 / EPYC 7763,tiny 4 worker;与上表不是同一批 VM,只看相对关系):

引擎 中位 ms/图 工作集峰值 行精确 CER
本库 224 ~790 MB 757/1022 3.53%
lw.PPOCR.C 281 ~586 MB 759/1022 4.18%
OpenVINO.NET 214 ~2600 MB 698/1022 3.63%

lw.PPOCR.C 用的是 2026 年 8 月底的一份构建,不代表该项目最新版本。

简评:墙钟接近 OpenVINO.NET、比这份 lw.PPOCR.C 快约 26%;工作集约 OpenVINO.NET 的 1/3,比 C 高一截。正确率跨 Windows / Linux / macOS 与 scalar 都是 757/1022、CER 3.53%;CER 好于该份 C,行精确高于 OpenVINO.NET。

完整环境、ISA 阶梯和读数规则见 docs/perf.md。

性能复现

GitHub Actions test 工作流 会跑单元测试,并在 Windows / Linux / macOS 多架构上对 tiny / small / medium 做 bench (含关闭 AVX-512 / AVX2 / AVX / 全部硬件加速,以及 netstandard2.0 库)。汇总报告写入 job summary 与 perf-report artifact。

微信群

如果微信群二维码过期了,请加入 QQ 群 C#/.NET计算机视觉技术交流 579060605。

SimdPaddleOCR (sdcb/SimdPaddleOCR)

Searching Database…

Что это такое?Чисто C#-библиотека OCR для моделей PP-OCRv6: она находит и распознаёт текст на изображениях с помощью собственных SIMD-оптимизированных ядер, написанных вручную, и содержит собственный управляемый интерпретатор ONNX — без нативных зависимостей от Paddle Inference, ONNX Runtime или OpenCV.
Это библиотека, которую я подключаю к своему .NET-коду, или готовое приложение?Это библиотека — вы подключаете NuGet-пакеты Sdcb.SimdPaddleOCR к своему .NET-приложению. В репозитории также есть готовые примеры для запуска: веб-демо на ASP.NET Core с API-эндпоинтом POST /api/ocr, а также примеры приложений на Avalonia, WPF и WinForms.
Как добавить её в .NET-проект?Установите основной пакет плюс пакет моделей, например Sdcb.SimdPaddleOCR.Models.ChineseV6Tiny (он транзитивно подтягивает CLS-классификатор и ModelProvider). Веса моделей загружаются из встроенных ресурсов сборки — никакие скачивания или временные файлы не нужны, — а API принимает буферы пикселей в 8-битном формате BGR.
Нужно ли разворачивать вместе с ней какие-то нативные библиотеки?Нет. Интерпретатор ONNX полностью управляемый, на C#, поэтому никаких нативных бинарников Paddle Inference, ONNX Runtime или OpenCV не требуется. Единственное, что нужно добавить самому, — декодер изображений (ImageSharp 3, SkiaSharp, OpenCvSharp или System.Drawing), чтобы получить буферы BGR8.
Какие сейчас главные ограничения?Работает только на CPU (без GPU) и пока поддерживает только китайский (модели zh). API принимает сырую память в 8-битном формате BGR — ни путей к файлам, ни хелперов из библиотек для работы с изображениями — а маленькая модель потребляет до ~790 МБ оперативной памяти и обрабатывает изображение примерно за 238 мс на серверном CPU с 4 виртуальными ядрами.
Какие платформы и рантаймы .NET она поддерживает?Windows x64/x86/ARM64, Linux x64/ARM64 и macOS x64/ARM64 проверяются в CI. Для полной поддержки SIMD (AVX/AVX-512/VNNI) и NativeAOT ориентируйтесь на net10.0, а для старых рантаймов вроде .NET Framework 4.8 — на netstandard2.0, где используется запасной вариант на Vector/скалярных операциях.
Можно ли настроить, сколько потоков она использует?Да, через PaddleOcrOptions: DetIntraOpThreads ограничивает число потоков свёртки внутри графа детекции (одна сессия, по умолчанию максимум 8), а LineWorkerCount задаёт количество параллельных воркеров CLS/REC для каждой строки (по одной сессии на воркера, не больше min(request, ProcessorCount); 0 означает min(ProcessorCount, 4)).
Почему OCR так медленно работает под отладчиком?Отладчики могут отключать JIT-оптимизации при загрузке модуля, что сильно замедляет требовательный к вычислениям SIMD-код. Отключите это и перезапустите отладку — в Visual Studio снимите галочку в Tools > Options > Debugging > General; в Rider — в настройках JIT отладчика; в VS Code установите csharp.debug.suppressJITOptimizations в false.
Можно ли загрузить свои локальные файлы моделей вместо NuGet-пакетов с моделями?Да. Сама библиотека никогда не скачивает модели — вы можете передать локальные файлы DET, CLS, REC и словарь через провайдер моделей, а пороги детекции, ограничения длины строк и лимиты кэша сессий настроить там же, в PaddleOcrOptions.
Всё ли в репозитории распространяется под Apache-2.0?Собственный код и документация проекта — под Apache-2.0, лицензия выбрана из-за явной передачи прав на патенты. Ресурсы моделей сохраняют условия исходных проектов (они из экосистемы PaddleOCR), ImageSharp 3.x использует Six Labors Split License, а сам проект неофициальный — не связан с PaddleOCR и ею не одобрен.
Creator
sdcb
Size
128.9 MB
Stars
488
Age
1mo
Commits · 90 Days