文章目录
- 前言
- 1. 为什么放着 Python 不用,非要自讨苦吃
- 2. 纯 C 到底有多纯
- 2.1 整条链路握在自己手里
- 2.2 SIMD:从 x86 卷到龙芯
- 3. v0.2.0 最大变化:Tiny、Small、Medium 三兄弟集合
- 3.1 为什么不在 API 里加"型号枚举"
- 4. 三套独立模型包,各回各家
- 5. 一个 HTML,就是一个完整 OCR
- 6. 不是"HTML 能生成",而是真跑了 OCR
- 7. 除了 C,Java、Android、Node 也全接上了
- 8. Release 本身也做成了"测试"
- 9. 为什么还叫 Preview
- 10. 谁适合来试试这个项目
- 11. 接下来打算干啥
- 12. 最后说两句
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看, 传送门https://blog.csdn.net/HHX_01
前言
兄弟们,最近我干了一件在别人眼里多少有点"倒反天罡"的事:放着 Python + PaddleOCR 这种"人人都说好"的路线不走,非要拿纯 C 去硬啃 PP-OCR。
先别急着笑,听我把话说完。不是我不识好歹,实在是在工程现场被教育太多次了:客户要的从来不是"算法牛不牛",而是"你这玩意儿到底好不好接"。
1. 为什么放着 Python 不用,非要自讨苦吃
现在做 OCR 部署,成熟方案一抓一大把:Python + PaddleOCR,方便到像是白送的;ONNX Runtime,通用性拉满;OpenVINO、TensorRT,性能顶得一批。
但真正落到工程项目里,你会碰到另一类更扎心的问题。
比如客户给你一台工控机,需求就一句话:“拷几个 DLL 进去就能跑。”
说这话的时候,客户眼里闪着光,像极了当年发誓要减肥的我。
再比如,你要把 OCR 部署到一台配置比较克制的 Linux ARM64 设备上,或者集成进自己的 C++、C#、Java 软件里。
这时候你会痛苦地发现:真正麻烦的往往不是 OCR 模型本身,而是模型身后那一整个"运行时生态"。
Python 环境、动态库、第三方依赖、版本兼容、模型格式、部署目录、安装包体积……一个 OCR 功能,能给你带进来一大堆东西。不知道的还以为你在部署一个操作系统。
所以做 lw.PPOCR.C 的时候,我一开始就立了个 flag:
它不是一个通用 ONNX Runtime,而是一个专门针对 PP-OCR 模型优化的轻量级纯 C Runtime。
翻译成人话:我主动放弃"什么模型都能跑",换来了更小、更简单、更容易集成、也更容易控制。
2. 纯 C 到底有多纯
核心用 C11 开发。跑 PP-OCR 的时候,Python、OpenCV、ONNX Runtime、OpenVINO、TensorRT、protobuf —— 全都不需要。
这串名字念完嘴都酸了,可见以前要带的东西有多少。
2.1 整条链路握在自己手里
因为 Runtime 足够小,整个 OCR 执行链你就能真正说了算:
PP-OCR ONNX ↓ 模型转换 ↓ LWM ↓ lw.PPOCR.C ↓ DET ↓ CLS ↓ REC ↓ 完整 OCR 结果模型加载、Shape 推导、Workspace 管理、算子实现、SIMD 优化、OCR 后处理,全部握在自己手里。
2.2 SIMD:从 x86 卷到龙芯
目前 CPU SIMD 已经覆盖:
Scalar SSE2 AVX2 AArch64 NEON LoongArch LSX看到没,连龙芯的 LoongArch 都安排上了。这已经不是"给普通 Windows x64 PC 写的 Demo",而是奔着跨平台部署 Runtime 去的。
3. v0.2.0 最大变化:Tiny、Small、Medium 三兄弟集合
以前项目主要围着 PP-OCRv6 Tiny 转。
Tiny 的最大优势就一个字:小。小到手机、普通桌面软件、边缘设备、浏览器都能塞进去,属于"哪里需要往哪搬"的模范打工人。
但实际项目里大家自然会问:能不能用 Small?能不能跑 Medium?
于是 v0.2.0-preview.1 干了一件大事:让三套模型用同一套 Runtime。
PP-OCRv6 Tiny PP-OCRv6 Small PP-OCRv6 Medium3.1 为什么不在 API 里加"型号枚举"
这里有个设计细节我很得意:我故意没有在 C API 里加 LW_MODEL_TINY、LW_MODEL_SMALL、LW_MODEL_MEDIUM 这种枚举。
LW_MODEL_TINY LW_MODEL_SMALL LW_MODEL_MEDIUM因为在我的设计里,Tiny / Small / Medium 是模型包的事,不该变成 Runtime ABI 的事。
原生程序只需要换模型目录,Runtime 根本不需要知道"你现在跑的是 Tiny 还是 Medium"。
这个边界划清楚之后,以后再加新模型,公共 C API 就不用跟着改来改去。省下来的头发,还能多熬两年夜。
4. 三套独立模型包,各回各家
这次 Release 直接给了三套模型包:
PP-OCRv6 Tiny Runtime Pack PP-OCRv6 Small Runtime Pack PP-OCRv6 Medium Runtime Pack实际发布大小大约为:
Tiny 7.2 MB Small 32.1 MB Medium 139.6 MB7.2MB 和 139.6MB 站在一起,像极了健身房里的我和旁边那个练了八年的哥们。
每个模型包都自带模型、字典、manifest 和 SHA256 信息,还用了独立命名空间,避免解压后互相覆盖。
于是原生程序目录可以长这样:
models/ ├── ppocrv6-tiny/ ├── ppocrv6-small/ └── ppocrv6-medium/选哪个目录,就跑哪个模型。比在 Runtime 里堆一堆"模型类型判断"干净得多。
5. 一个 HTML,就是一个完整 OCR
这个功能我愿称之为"本场最佳"。
一个 HTML 文件里,直接打包了 Runtime + WASM + 模型 + OCR 页面。
不用启动服务器、不用装 Python、不用 npm install,连模型目录都不用单独准备。下载完,双击打开,就能 OCR。
这次不是做一个 HTML 让你在三个模型里挑,而是分别给了三个独立文件:
Tiny HTML Small HTML Medium HTML每个文件本身就是个完整、确定的 OCR 产品。
发布大小也很有意思:
Tiny HTML ≈ 13.7 MB Small HTML ≈ 46.9 MB Medium HTML ≈ 190.3 MB这三个数字基本就是它们的定位:
- Tiny:手机和普通使用,轻装上阵;
- Small:我认为是最值得试的增强版,体积还扛得住;
- Medium:桌面优先的重量级方案。
Medium 虽然也能做成单文件 HTML,但我不打算把它吹成移动端首选。190MB 的"轻量"页面,打开的时候估计比我的开机速度还感人。
6. 不是"HTML 能生成",而是真跑了 OCR
做 WebAssembly 项目最怕什么?最怕"编译成功 = 支持浏览器"这种自欺欺人。
这次不一样。Tiny、Small、Medium 的浏览器版本,都真的通过 Chromium 执行过 OCR。
Small 和 Medium 还额外跑了这么一套:
创建 OCR Runtime ↓ 执行真实 OCR ↓ 校验行数 ↓ 校验完整识别文本 SHA256 ↓ 再次 OCR ↓ destroy ↓ 重新 create ↓ 再次 OCR看到没,OCR 完还要校验 SHA256,然后再来一遍。不知道的还以为在做期末考试。
Standalone HTML 也在浏览器里真正加载图片、执行 OCR、读取结果。
而且这些测试最后又在正式 Release Workflow 里重新跑了一遍,全部通过。
所以这次说"Small / Medium 浏览器支持",不是"理论上应该可以",而是已经作为 Release Gate 真刀真枪验过货了。
7. 除了 C,Java、Android、Node 也全接上了
核心坚持纯 C,但 Runtime 总得被各种业务程序调用。
目前这个 Preview 已经提供了一套相当完整的分发方式:
- Windows x64 原生开发包、Linux x86_64 原生开发包;
- Android ARM64 AAR 和 Demo APK;
- Java/JNI:Windows x64、Linux x64、macOS ARM64;
- Node.js 18 / 20 / 22 WASM;
- Tiny / Small / Medium 浏览器 SDK;
- Tiny / Small / Medium 单文件离线 HTML;
- Tiny / Small / Medium Runtime Model Pack。
这矩阵列出来,不知道的还以为我在做平台全家桶促销。
其中 macOS ARM64 的 Java/JNI 这次也真正跑通了完整链路:
构建 → 打包 → 校验 → Java 示例编译 → macOS 上实际 OCR → Release一条不少,比我当年写毕业设计的流程图还全。
8. Release 本身也做成了"测试"
这个变化不太能从页面上直接看出来,但我觉得比多加点接口重要多了。
以前很多项目的发布流程是:
编译 ↓ 压缩 ↓ 上传随着平台越来越多,这种流程特别容易发错文件。
于是 lw.PPOCR.C 把 Release Asset 本身定义成了一个 Contract:每一个该发布的文件——
Windows Linux Web Java Android Node Runtime Model Pack Checksum——都会进 Release Manifest。
正式发布前,CI 会检查:
文件是否缺失 文件名是否正确 版本号是否正确 是否出现多余文件 SHA256 是否正确 checksum 是否覆盖正确全部通过才允许执行 GitHub Release。
文件多一个、少一个都过不了。这哪是发布,这是机场安检。
v0.2.0-preview.1 是第一次完整跑通这条真实发布链。
对我来说,这意味着项目开始从"代码仓库"变成"可以重复构建和发布的软件产品"。
9. 为什么还叫 Preview
功能挺全了,但我还是坚持标 v0.2.0-preview.1,而不是直接发 v0.2.0。
原因很简单:想再观察几个问题。
首先是 Small 和 Medium 在真实项目里的价值。尤其是 Medium,浏览器单文件已经接近 190MB,技术上跑得动,不代表每个场景都值得用。我更想看的是:Small 是不是已经站在了性能、效果、体积之间的平衡点上?
其次是不同设备上的实际表现:
普通办公电脑 低功耗 x86 ARM64 国产平台 浏览器 工控环境这些场景里的真实体验,比在 CI 里多加几个测试更有说服力。
还有一个硬原因:目前公共 C ABI 和 LWM v0.1 格式还没宣布冻结。
翻译成人话:我现在改接口,不算违约。
所以 Preview 阶段要是拿去上正式项目,建议把 Runtime 和模型当一套一起管理,别混着用不同 Release 的二进制、模型和字典。这条限制也写进了发布文档。
10. 谁适合来试试这个项目
如果你平时用 PaddleOCR,又正好属于下面这些场景,可以来试试:
- 你在做 C/C++ 工程,想尽量少带第三方运行库;
- 你需要往 Windows / Linux / ARM64 边缘设备上部署 OCR;
- 你在做 C#、Java 桌面软件,希望底层 OCR Runtime 足够克制;
- 你想把 OCR 直接打进一个离线 HTML;
- 你在意安装包大小、部署复杂度和运行时依赖;
- 或者你单纯对"从模型格式、算子、SIMD 到完整 OCR,自己搞一套小型推理 Runtime"这件事感兴趣。
总有一款适合你,就像便利店,总有一款速食适合深夜的你。
11. 接下来打算干啥
v0.2.0-preview.1 发布后,我不打算马上塞一堆新功能。
先让这一版跑一跑,看看真实用户到底更爱:
Tiny Small Medium哪一个。就像问孩子今晚吃麦当劳还是肯德基,答案可能是:都想要。
再看看大家主要把它用在:
Windows Linux ARM64 Web Java Android哪种环境。
以及有没有 CI 里看不到的兼容性问题。
后续比较大的 Runtime 工作,我依然惦记着更系统的 Microkernel Architecture、ARM64 进一步优化、新的 SIMD Kernel。
但这些不会赶在 v0.2.0 之前强行塞进去。先把这一版打磨稳,比啥都强。
12. 最后说两句
lw.PPOCR.C 最开始其实只是个很朴素的想法:
PP-OCR 能不能不靠一整套通用推理框架,直接做成一个足够小、足够好集成的纯 C Runtime?
做到现在,已经攒出了这么一整套东西:
模型转换 纯 C Runtime DET / CLS / REC 完整 OCR SIMD 多线程 Windows / Linux ARM64 Java Android Node WASM 单 HTML OCR Tiny / Small / Medium 自动化 Release它当然还远没到"万能",我也不想让它变成另一个万能 Runtime。
它就专注一件事:用尽可能简单、透明、可控的方式,把 PP-OCR 放进真实工程。
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/HHX_01