这篇是博客园今天(2026-09-21 08:50)最热门的文章,稳坐"最多推荐"榜首,由 .NET骚操作 发布。[citation:50.4][citation:50.11][citation:50.12]
---
Fable 5.1 操刀,内存腰斩,外星科技——SimdPaddleOCR 1.4 发布!
2026 年 9 月 21 日 | 作者:.NET骚操作
---
项目定位
SimdPaddleOCR 是一个纯 C# 实现的 PP-OCRv6 推理引擎。它不需要 Paddle Inference,不需要 ONNX Runtime,也不依赖 OpenCV 原生库——从模型加载到矩阵运算,全部用 C# + SIMD 手写。核心 API 只接收 8-bit BGR/RGB 内存数据,图像解码交给上层自由选择(ImageSharp、SkiaSharp、OpenCvSharp 皆可)。[citation:50.1][citation:50.13]
做这个项目只为回答一个问题:如果以我能达到的最高标准,打造出最强的 C# PaddleOCR 引擎,它能达到什么效果?1.4 版本就是我给出的答案!
---
性能与内存:碾压式的提升
1.4.2 vs 1.3 纵向对比
测试环境:Ryzen 7 5800X(AVX2,无 AVX-512),64GB 内存,.NET 10.0.11。[citation:50.13]
| 模型 | 1.3 耗时 | 1.4.2 耗时 | 耗时比 | CER 字符错误率 | 峰值内存 |
|:----:|:--------:|:----------:|:------:|:-------------:|:--------:|
| tiny net10 AVX2 | 86.0 ms | 63.1 ms | 0.73× | 2.78% → 2.37% | 804 → 515 MB |
| tiny ns2 | 203.1 ms | 96.5 ms | 0.48× | 同上 | 766 → 522 MB |
| small net10 | 222.1 ms | 200.0 ms | 0.90× | 0.60% → 0.41% | 1195 → 674 MB |
| small ns2 | 432.1 ms | 303.0 ms | 0.70× | 同上 | 1277 → 684 MB |
| medium net10 | 628 ms | 585 ms | 0.93× | 0.67% → 0.14% | 2489 → 1206 MB |
| medium ns2 | 1606 ms | 874 ms | 0.54× | 同上 | 2663 → 1218 MB |
亮点:
tiny 模型 ns2 路径耗时 腰斩(203→96 ms),内存从 766 MB 降至 522 MB
medium 峰值内存从 2.5 GB → 1.2 GB,直接腰斩
工作集增量(Δ WS)在 tiny 场景下从 389 MB → 113 MB
对比 C 语言引擎
拉来 C 版引擎(lw.PPOCR.C)同台对比:[citation:50.13]
| 模型 | SimdPaddleOCR 1.4.2 | C 引擎 | 优势 |
|:----:|:-------------------:|:------:|:----:|
| tiny 耗时 | 63.1 ms | 201.9 ms | 3.2× 吞吐量碾压 |
| medium CER | 0.14% | 0.24% | 准确率反超 C 引擎 |
| 峰值内存 (tiny) | 515 MB | 541 MB | 更低 |
纯 C# 写的 OCR 引擎,在吞吐量和准确率上双双反超纯 C 版——这在 .NET 生态里几乎是"不可能"的事。
对比 PaddleOCRSharp
| 模型 | SimdPaddleOCR | PaddleOCRSharp | 倍数 |
|:----:|:-------------:|:--------------:|:----:|
| tiny 耗时 | 66.5 ms | 270.6 ms | 4.07× |
| small 耗时 | 195.4 ms | 505.9 ms | 2.59× |
| medium 耗时 | 585.9 ms | 1284.0 ms | 2.19× |
| 峰值内存 (tiny) | 515 MB | 993 MB | 约一半 |
---
核心进化揭秘
内存管理大瘦身
三项关键改进:移除输入 LayoutConvert 阶段的第二份缓冲 → NHWC 工作集引入别名机制 → F32 常量池不再使用"原始字节 + 解码拷贝"的笨重模式。峰值内存直接腰斩。[citation:50.13]
CLS 正确率两连跳:从 98% 干到 100%
1.3 版本的分类型(CLS)预处理使用了 PaddleX 的拉伸逻辑(强行拉成 160×80,使用 ImageNet RGB),导致细长拉丁文字行被极度拉伸后频繁误判 0 度与 180 度。
1.4 先改回 PaddleOCR 原生的 ClsResizeImg——高度固定 80,宽度按比例拉伸(封顶 160),右侧用 -1 pad。这一步让 medium 的 CER 从 0.67% 降到 0.26%。
1.4.2 更精妙——对于长行,将原图宽度按高度的 4 倍裁剪,保留左侧部分再拉伸。不引入额外内存分配和性能开销,转换一气呵成。最终 CLS 正确率达到 1022/1022(100%)。[citation:50.13]
图级 NHWC 全路径制霸
1.3 只有 AVX2+FMA 吃到了图级 NHWC(通道最后布局)的红利。1.4 将这一优势扩充到了所有路径:[citation:50.13]
| 路径 | 改进 | 效果 |
|:----:|:----:|:----:|
| netstandard2.0 (Vector) | NCHW → NHWC | 性能大幅提升 |
| x64 scalar | 软件模拟 → 专用 NHWC 标量 tile | 改善 |
| net10 AdvSIMD (ARM) | NCHW → 手写 NHWC NEON tile | CI 上 tiny 241→180ms (0.75×) |
| avx512 | NCHW → 手写 NHWC AVX512 tile | 社区反馈性能提升 45% |
原生支持 RGB/RGBA,告别 BGR 转换
1.4 的 Run 方法可以直接接收 Rgb24、Bgra32、Rgba32 格式,通道交换在 resize 或 warp 时就地完成,不需要额外分配内存。不再需要先转 BGR 再传 OCR。[citation:50.13]
// ImageSharp + Rgba32 直接传入
using Image<Rgba32> image = await Image.LoadAsync<Rgba32>("sample.jpg");
image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> memory);
PaddleOcrResult result = ocr.Run(
MemoryMarshal.AsBytes(memory.Span),
image.Width, image.Height,
format: ImagePixelFormat.Rgba32 // 原生支持!
);
---
数据集开源,欢迎打擂
为了方便社区做引擎对比,作者将测试集开源:[citation:50.13]
HuggingFace: simdpaddleocr-dataset-v1
ModelScope: simdpaddleocr-dataset-v1
Apache-2.0 协议,100 张 JPEG,约 26456 个中英文混排字符,20% 竖排,25% 180 度倒转
三项官方指标:
Exact lines:预测与真值无序字符串全匹配
Exact CLS:DET 纠偏后的 0/180 分类正确率
CER:非 Exact 行取最小编辑距离除以总字符数
---
一句话总结
SimdPaddleOCR 1.4 用纯 C# 写出了一个让 C 语言引擎都汗颜的 OCR 引擎——吞吐量 3.2 倍于 C 版、峰值内存腰斩、CLS 正确率 100%。 作者借 Fable 5.1 之力重构了全链路的 SIMD 算子(NHWC 铺到所有 CPU 路径),配合精细到逐字节的内存管理和 CLS 预处理优化,硬生生在托管环境中榨出了 C 级乃至超越 C 的性能。GitHub 已开源,Apache-2.0 协议,NuGet 包名 Sdcb.SimdPaddleOCR[citation:50.13]。
0 评论