一个 HTML 文件就能跑 OCR:我把 PP-OCR 装进了浏览器

纯 C + WebAssembly,让 OCR 真正做到:一个文件、离线运行、下载即用。

项目地址:

github.com/lxw112190/l...


前言:如果 OCR 的交付物只剩一个 HTML,会怎样?

传统 OCR 部署,通常意味着一整套运行环境:

  • Python
  • OpenCV
  • ONNX Runtime
  • 模型文件
  • 动态库
  • 配置文件
  • Web 服务
  • 甚至 Docker

如果只是想把一个 OCR Demo 发给别人体验,也经常免不了告诉对方:

先安装环境,再下载模型,然后运行程序。

最近在开发 lw.PPOCR.C 的过程中,我尝试了另一种方式:

把完整 OCR Runtime、检测模型、方向分类模型、文字识别模型、字典以及前端界面,全部装进一个 HTML 文件。

最终的交付物只有:

复制代码
ocr-demo.html

不需要安装 Python。

不需要 OpenCV。

不需要 ONNX Runtime。

不需要启动服务器。

不需要额外放置模型目录。

只要有支持 WebAssembly 的现代浏览器,打开这个 HTML 文件,就可以选择图片并完成 OCR。

这背后的关键技术,就是:

WebAssembly


一、一个 HTML 文件里,到底装了什么?

从表面上看,它只是:

复制代码
ocr-demo.html

但实际上,这个文件内部包含了完整的 OCR 运行环境:

css 复制代码
ocr-demo.html
│
├── HTML / CSS / JavaScript
├── WebAssembly OCR Runtime
├── det.lwm
├── cls.lwm
├── rec.lwm
└── ppocr_keys.txt

也就是说:

界面、Runtime、模型、字典,全都被打包进了同一个文件。

浏览器打开之后,会在本地初始化 WebAssembly 运行环境,并加载内嵌的 OCR 模型。

随后执行完整的 OCR Pipeline:

objectivec 复制代码
输入图片
   ↓
DET 文本检测
   ↓
DB 后处理
   ↓
透视裁剪
   ↓
可选 CLS 方向分类
   ↓
REC 文字识别
   ↓
输出文字、检测框和置信度

这不是一个只跑 REC 的简单 Demo,而是一套完整 OCR 流程。


二、为什么浏览器可以运行 C 写的 OCR?

关键就是 WebAssembly。

传统 C 程序一般会编译成:

复制代码
Windows → EXE / DLL
Linux   → ELF / SO

而通过 Emscripten,可以把 C/C++ 代码编译为 WebAssembly:

javascript 复制代码
C Runtime
    ↓
Emscripten
    ↓
WebAssembly
    ↓
Browser

现代浏览器可以直接执行 WebAssembly。

因此,一套原本运行在 Windows、Linux 上的纯 C OCR Runtime,也可以进入浏览器。

lw.PPOCR.C 来说,这一点尤其自然,因为这个项目从一开始就尽量保持部署端足够轻量:

diff 复制代码
C11
+
libc
+
少量平台适配

核心 Runtime 不依赖:

复制代码
Python
OpenCV
ONNX Runtime
OpenVINO
TensorRT
protobuf

所以移植到 WebAssembly 时,不需要把一整套重量级推理框架一起搬进浏览器。


三、为什么不直接在浏览器里跑 ONNX?

当然可以。

现在已经有很多成熟方案,可以直接在 Web 端解析和执行 ONNX 模型。

lw.PPOCR.C 走的是另外一条路线:

javascript 复制代码
开发阶段

PP-OCR ONNX
     ↓
Converter
     ↓
LWM

部署阶段

LWM
 ↓
Pure C Runtime
 ↓
WebAssembly
 ↓
Browser

这里有一个很重要的设计原则:

部署阶段不解析 ONNX。

ONNX 更适合作为开发阶段的模型交换格式。

真正部署时,模型先转换成 lw.PPOCR.C 自己的轻量格式 .lwm,Runtime 只需要理解这个专用格式。

这样做的好处很明显:

  • 不需要 ONNX Parser;
  • 不需要 protobuf;
  • 不需要通用图优化器;
  • 不需要为大量无关模型结构背负复杂性;
  • 浏览器端 Runtime 可以保持更小、更简单。

这也是 lw.PPOCR.C 一直坚持的方向:

开发端可以复杂,部署端尽量简单。


四、为什么坚持做成"单 HTML"?

其实 WebAssembly 项目完全可以按照常规方式发布:

复制代码
web/
├── index.html
├── runtime.js
├── runtime.wasm
├── det.lwm
├── cls.lwm
├── rec.lwm
└── ppocr_keys.txt

这种形式很正常,也更利于开发和调试。

但如果目标是"让别人快速体验 OCR",用户感受就完全不同。

当别人拿到一整个目录时,很容易问:

  • 需要部署 Web Server 吗?
  • 要不要 nginx?
  • .wasm 文件能不能直接双击?
  • 模型目录能不能移动?
  • 路径是不是必须固定?

而如果最后只交付:

复制代码
ocr-demo.html

使用过程就变成:

复制代码
下载
 ↓
打开
 ↓
选择图片
 ↓
OCR

这看起来只是少了几个文件,但交付体验发生了很大变化。

我更愿意把这种形式理解成:

一个可以执行 AI 模型的"可执行文档"。


五、它可以完全离线运行

这是这个 Demo 最有意思的地方之一。

OCR 过程中,图片不需要上传到服务器。

整个流程可以完全留在本机:

css 复制代码
本地 JPEG / PNG
      ↓
浏览器读取
      ↓
Canvas / Pixel Buffer
      ↓
WASM Memory
      ↓
Pure C OCR Runtime
      ↓
OCR Result

识别得到的文字、检测框和置信度,再从 WASM 返回给 JavaScript,在页面里显示。

所以,只要 ocr-demo.html 已经下载到本地:

即使没有网络,也可以完成 OCR。

这对于一些场景非常有意义,例如:

  • 内部资料识别;
  • 工业现场离线工具;
  • 局域网隔离环境;
  • 教学演示;
  • 模型效果展示;
  • 不希望图片上传云端的轻量业务;
  • 客户体验版;
  • 快速验证算法效果。

当然,这不意味着浏览器 OCR 会取代服务器 OCR。

但它提供了一种新的选择:

OCR 不一定非得是"上传图片 → 服务端推理 → 返回结果"。

计算也可以直接跟着 HTML 文件走。


六、模型是怎么放进 HTML 的?

det.lwmcls.lwmrec.lwm 本质上都是二进制模型文件。

生成单文件 HTML 时,可以把这些模型编码后嵌入页面。

可以简单理解为:

css 复制代码
det.lwm
   ↓
Base64
   ↓
HTML

方向分类模型、文字识别模型和字典也是同样处理。

最终这个 HTML 文件里实际包含:

diff 复制代码
Web UI
+
WASM Runtime
+
DET Model
+
CLS Model
+
REC Model
+
Dictionary

所以它已经不只是一个网页。

它更像:

一个以 HTML 形式交付的完整 OCR 应用。


七、WASM 能不能更换自己的检测模型?

这个问题最近正好有使用者问到。

答案是:

可以。WASM 技术本身完全支持运行时更换模型。

目前的 ocr-demo.html 之所以没有提供"选择模型"按钮,并不是 WebAssembly 做不到,而只是当前 Demo 为了追求:

单文件、离线、开箱即用

所以默认把模型直接内嵌到了 HTML 中。

未来完全可以增加:

css 复制代码
检测模型:

○ 使用内置模型
● 加载自定义 det.lwm

[选择 det.lwm]

浏览器可以通过 File API 读取用户自己的模型:

arduino 复制代码
用户选择 det.lwm
       ↓
JavaScript File API
       ↓
写入 WASM 文件系统 / WASM 内存
       ↓
释放旧 OCR Handle
       ↓
重新加载模型
       ↓
新模型生效

换句话说:

更换兼容的 .lwm 模型,通常不需要重新编译 WASM Runtime。

这也是 WASM 方案的一个优势。


八、未来还可以进一步做到"内存加载模型"

如果 Runtime 后续增加类似:

scss 复制代码
lw_model_load_memory(...)

这样的内存加载接口,那么模型甚至不用先写入 WASM 虚拟文件系统。

浏览器端可以直接:

ini 复制代码
<input type="file">
        ↓
ArrayBuffer
        ↓
WASM Memory
        ↓
lw_model_load_memory()

这样整个模型切换过程会更干净。

以后甚至可以设计成:

css 复制代码
模型配置

DET
[内置 PP-OCRv6 Tiny]
[选择 det.lwm]

CLS
[内置 PP-OCRv6 Tiny]
[选择 cls.lwm]

REC
[内置 PP-OCRv6 Tiny]
[选择 rec.lwm]

Dictionary
[内置字典]
[选择字典]

不过从实现优先级上看,我更倾向于先开放 DET。

因为 REC 模型一旦更换,通常还涉及:

  • 字典;
  • 字符类别数量;
  • CTC;
  • 输入高度和宽度;
  • 输出维度;
  • 字符集兼容。

DET 相对更独立,更适合作为第一个可替换模型。


九、但"能换模型"不等于"任意模型都能换"

这一点必须说明。

lw.PPOCR.C 并不是一个通用深度学习框架,也不是另一个 ONNX Runtime。

它的定位一直是:

面向 PP-OCR 的专用轻量推理 Runtime。

所以可以换自己的模型,但新模型仍然需要满足当前 Runtime 的约束,例如:

  • 模型算子必须已经被 Runtime 支持;
  • DET 输入输出结构需要符合当前检测 Pipeline;
  • 当前后处理仍然是 DB PostProcess;
  • 输出需要满足概率图形式;
  • 预处理方式要保持兼容;
  • 模型 Shape 不能和现有 Pipeline 完全冲突。

所以更准确的说法是:

WASM 支持动态换模型,lw.PPOCR.C 支持的是"兼容的 LWM 模型",而不是任意神经网络。

这其实也是项目保持轻量的代价和优势。


十、为什么不让用户直接拖 ONNX 进去?

从技术上讲,也不是完全做不到。

但如果浏览器端直接支持 ONNX,就意味着 Runtime 需要进一步承担:

复制代码
ONNX Parser
protobuf
Graph Validation
Graph Optimization
更多动态结构
更多通用算子

这会让项目越来越接近一个通用推理引擎。

而这并不是 lw.PPOCR.C 想走的方向。

所以即使以后网页支持自定义模型,我更希望用户提供:

复制代码
det.lwm

而不是:

复制代码
det.onnx

模型工作流仍然保持:

复制代码
用户自己的 ONNX
      ↓
lw.PPOCR.C Converter
      ↓
det.lwm
      ↓
拖入浏览器
      ↓
WASM OCR

这样既能支持模型定制,又不会破坏 Runtime 的轻量定位。


十一、一个 HTML 文件,对软件交付意味着什么?

这是这次尝试中我最感兴趣的地方。

以前发布一个 AI 软件,经常是:

diff 复制代码
模型
+
Python
+
环境
+
依赖

后来很多项目变成:

diff 复制代码
模型
+
Docker
+
REST API

而 WebAssembly 又提供了另外一种可能:

css 复制代码
一个 HTML
+
浏览器

对于中小型 AI 模型而言,这种交付形式很有吸引力。

HTML 原本是"文档"。

EXE 原本是"程序"。

而现在:

复制代码
ocr-demo.html

里面已经同时包含:

diff 复制代码
UI
+
程序
+
AI Runtime
+
模型
+
业务逻辑

所以它已经介于"网页"和"应用程序"之间。

把它通过:

复制代码
U 盘
邮件
网盘
局域网
企业内部系统

发给别人,对方只需要一个现代浏览器就能运行。

这可能是 WebAssembly 最值得关注的一点:

它不只是让 C/C++ 进入浏览器,也是在改变 Native 软件的交付方式。


十二、这种单 HTML OCR 适合哪些场景?

它不是所有 OCR 场景的最佳方案,但在一些场景里非常方便。

1. 产品演示

给客户一个文件:

复制代码
ocr-demo.html

比让客户安装 Python、DLL、Docker 或者服务端程序简单得多。

2. 算法效果验证

模型转换成 .lwm 后,可以直接用浏览器验证效果。

3. 离线 OCR 小工具

没有服务器,也可以完成基本 OCR。

4. 教学

C Runtime、WebAssembly、深度学习推理和 OCR Pipeline,可以在同一个 Demo 里展示。

5. 工业设备 Web 界面

很多工业设备本来就提供浏览器管理界面。

未来甚至可以把部分 OCR 运算直接交给客户端浏览器:

复制代码
设备提供网页
      ↓
浏览器加载 WASM Runtime
      ↓
客户端 CPU 完成 OCR

这样在某些业务中,可以把部分计算压力从设备端或者服务器端转移给客户端。


十三、它不能替代 Native OCR

这一点也需要说清楚。

浏览器 WASM 很方便,但 Native C 仍然更适合:

复制代码
高吞吐批处理
后台服务
工业长期运行
复杂多线程
极限 CPU 性能
大规模 OCR 服务

而 WASM 更适合:

复制代码
即开即用
跨平台体验
离线工具
算法演示
快速交付
轻量部署

两种形态不是互相替代。

更合理的关系应该是:

复制代码
                lw.PPOCR.C
                     │
          ┌──── ───┴───────┐
          │                     │
        Native                     WASM
          │                     │
   Windows / Linux                     Browser
          │                     │
     工业与服务部署                   即开即用

最重要的是:

两边仍然可以共享同一套纯 C OCR Runtime。


十四、为什么我坚持做一个 PP-OCR 专用 Runtime?

lw.PPOCR.C 从一开始就没有准备做成:

"另一个 ONNX Runtime"。

这个项目更希望解决的是:

PP-OCR 能不能在不依赖重量级推理框架的情况下,用一套很小的纯 C Runtime 完成部署?

所以目前方向一直比较克制:

objectivec 复制代码
Pure C
FP32 CPU
PP-OCR 专用
DET / CLS / REC
完整 OCR Pipeline
SSE2 / AVX2
Windows / Linux
WebAssembly
LWM 模型格式
部署阶段不解析 ONNX

最近还在继续围绕真实 PP-OCR Shape 做 CPU Kernel 优化。

后续仍然会重点研究:

复制代码
Conv
SIMD
Weight Packing
Microkernel
CPU 多线程
Cache / Workspace

而不是无限扩大成一个通用推理框架。


十五、如何体验?

项目地址:

GitHub:

github.com/lxw112190/l...

建议从项目的 GitHub Releases 页面获取正式发布的离线 HTML Demo:

github.com/lxw112190/l...

下载下面的文件:

复制代码
lw.PPOCR.C-*-ocr-demo.html

然后直接用现代浏览器打开即可。


十六、这个小 Demo 真正有趣的地方

如果只看技术实现:

复制代码
C
 ↓
Emscripten
 ↓
WASM
 ↓
Browser

并不是什么神秘技术。

真正让我觉得有意思的是它最后改变了软件的交付体验。

以前交付 OCR,可能需要交一套环境。

现在可以只交:

复制代码
ocr-demo.html

一个文件。

一个浏览器。

就能 OCR。

没有安装包。

没有 Python。

没有 OpenCV。

没有 ONNX Runtime。

没有服务端。

没有模型目录。

没有网络请求。

而真正完成 OCR 的,又不是浏览器自带 OCR API,而是一套由 C 编写、编译成 WebAssembly 的完整 PP-OCR Runtime。

这种反差本身就很有意思。


写在最后

我越来越觉得,WebAssembly 真正值得关注的地方,并不仅仅是:

"浏览器终于可以跑 C/C++ 了。"

更重要的是:

它让 Native Runtime 获得了一种新的交付方式。

lw.PPOCR.C 来说,这种交付方式最后变成了:

复制代码
ocr-demo.html

把它发给别人。

对方打开。

选择图片。

OCR。

就这么简单。

这可能不是 OCR 最强大的运行方式。

但它一定是一种非常轻量、非常有趣,也非常适合分享和演示的方式。

让 AI Runtime 跟着一个 HTML 文件走。

这正是我目前在 lw.PPOCR.C 上探索的方向之一。


项目信息

项目名称: lw.PPOCR.C

项目地址: github.com/lxw112190/l...

定位: Lightweight Pure-C PP-OCR Runtime

部署方向: Windows / Linux / WebAssembly

模型格式: LWM

当前重点: FP32 CPU 性能、完整 OCR、轻量部署、跨平台运行

相关推荐
陈年老古董1 小时前
OpenCV图像处理笔记:图像拼接、答题卡识别与目标提取
人工智能·笔记·python·opencv·计算机视觉
智购科技智能售货柜1 小时前
2026自动售货机峰值交易流量应对方案:从消息削峰到弹性扩容的工程实践~YH
数据库·人工智能·单片机·嵌入式硬件·yolo
深念Y1 小时前
为什么选 Go:直观、可维护、AI 友好
linux·开发语言·人工智能·golang·agent·harness
北京靠谱的GEO优化机构1 小时前
AI时代作品背书:书籍歌曲影视百科创建规则与实操技巧
人工智能·百度·seo·百科创建
像风一样自由20201 小时前
13.pgvector入门用PostgreSQL直接实现向量检
人工智能·postgresql·大模型·rag·智能体
Csvn1 小时前
第 6 章 Agent 主循环
人工智能·aigc·agent
Csvn1 小时前
第 5 章 工具调用
人工智能·aigc·agent
clorinda1 小时前
OpenCV实战学习记录:图像拼接与答题卡识别
人工智能·opencv·学习
腾视科技-AIoT1 小时前
腾视科技AIBOX双版本重磅发布!本地安全与全球适配,解锁视频智能新可能
大数据·人工智能·科技·ai·物理ai·ainas·腾视科技