如何把 PaddleOCR.js 集成到 Web 应用,在浏览器端运行 PP-OCR 推理
【免费下载链接】PaddleOCRTurn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between images/PDFs and LLMs. Supports 100+ languages.项目地址: https://gitcode.com/GitHub_Trending/pa/PaddleOCR
如果你的 Web 应用需要在前端完成文字检测与识别,不想把图片上传到服务端做 OCR,可以把 PaddleOCR 官方浏览器 SDKPaddleOCR.js(npm 包名@paddleocr/paddleocr-js)集成进去。它通过 ONNX Runtime Web 和 OpenCV.js 在客户端完成 PP-OCR 产线的推理,输入Blob/ImageBitmap/HTMLCanvasElement等浏览器图像对象,输出带坐标、文本和置信度的识别结果。本文给出一条可直接执行的集成路径:安装 SDK、构造产线、读取结果,并说明宿主应用必须自己承担的运行时环境职责。
先跑通官方 Vite 演示应用
仓库的paddleocr-js目录是一个 monorepo:packages/core/是 SDK 源码(发布到 npm 的包),apps/demo/是依赖该 SDK 的 Vite 演示应用(见 paddleocr-js/README_cn.md)。演示应用要求Node.js >= 20.11(见 apps/demo 的 package.json 中engines声明),在仓库paddleocr-js目录下执行:
npm install npm run dev:demodev:demo等价于npm run dev --workspace apps/demo,启动 Vite 开发服务器。打开页面后可以看到完整交互:选择模型预设(PP-OCRv5_mobile/PP-OCRv6_small/PP-OCRv6_tiny)、选择运行时后端(auto/webgpu/wasm)、上传图片、运行 OCR,并在页面上看到检测框叠加的可视化图和识别结果列表。
演示应用的价值不只是"能跑",它的 Vite 配置就是宿主环境职责的现成参考。apps/demo/vite.config.js 中为server和preview都设置了:
headers: { "Cross-Origin-Opener-Policy": "same-origin", "Cross-Origin-Embedder-Policy": "credentialless" }并配置了worker: { format: "es" }。这正是 SDK 文档中"宿主环境职责"一节要求应用自行处理的两件事(见下文)。跑通演示后再改造到自己的项目,遇到问题时可以直接对照 demo 的 main.ts。
在自己的应用中安装并构造产线
npm install @paddleocr/paddleocr-js最小接入代码(来自 browser.md 快速开始):
import { PaddleOCR } from "@paddleocr/paddleocr-js"; const ocr = await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", ortOptions: { backend: "auto" } }); const [result] = await ocr.predict(fileOrBlob); console.log(result.items);模型有两种选法,都通过PaddleOCR.create的选项传入:
- 按语言与版本:
lang: "ch"+ocrVersion: "PP-OCRv5"。文档还说明ocrVersion: "PP-OCRv6"会把受支持的lang映射到内置的 PP-OCRv6_small 检测/识别模型对(见 SDK README)。 - 按内置模型名:显式传入检测与识别模型名:
await PaddleOCR.create({ textDetectionModelName: "PP-OCRv5_mobile_det", textRecognitionModelName: "PP-OCRv5_mobile_rec" });如果要用PP-OCRv6_tiny,必须显式指定模型名,不能只靠lang+ocrVersion:
await PaddleOCR.create({ textDetectionModelName: "PP-OCRv6_tiny_det", textRecognitionModelName: "PP-OCRv6_tiny_rec" });另一种构造方式是传入产线配置pipelineConfig(YAML 文本或已解析对象),例如:
const pipelineConfig = ` pipeline_name: OCR SubModules: TextDetection: model_name: PP-OCRv5_mobile_det batch_size: 2 TextRecognition: model_name: PP-OCRv5_mobile_rec batch_size: 6 `; const ocr = await PaddleOCR.create({ pipelineConfig });浏览器端对pipelineConfig有一个限制:子模块的model_dir仅支持null或资源描述对象(形如{ url: "..." }),不支持本地路径字符串。若同时提供了直接参数与pipelineConfig,以直接参数为准。
推理参数(textDetectionBatchSize、textRecognitionBatchSize、ortOptions等)也通过同一组 create 选项设置,例如固定使用 wasm 后端并指定 wasm 资源路径:
await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", textDetectionBatchSize: 2, textRecognitionBatchSize: 8, ortOptions: { backend: "wasm", wasmPaths: "/assets/" } });预测调用与结果验证
ocr.predict(image | images[], params?)接受Blob、ImageBitmap、ImageData、HTMLCanvasElement、HTMLImageElement、cv.Mat类型的输入,传数组可一次处理多图。检测/识别的阈值参数同时支持 camelCase 与 PaddleOCR 风格的 snake_case,例如textDetThresh/text_det_thresh、textDetBoxThresh/text_det_box_thresh、textDetUnclipRatio/text_det_unclip_ratio、textRecScoreThresh/text_rec_score_thresh等。
predict返回Promise<OcrResult[]>,每张输入图像对应一项——即使只传单个Blob/File,得到的也是长度为 1 的数组,用解构const [result] = await ocr.predict(file)或results[0]取值。每个OcrResult包含:
image:源图尺寸{ width, height };items:识别行,每行含poly(多边形坐标)、text、score;metrics:detMs、recMs、totalMs、detectedBoxes、recognizedCount。注意框数与行数是每张图统计,而三个耗时字段是整次predict()调用的总耗时(多图时每项上相同);runtime:请求的后端与各阶段 Provider 等元数据。
验证集成是否成功,文档给出的检查手段有两层:
- 初始化检查:调用
ocr.getInitializationSummary(),它会返回elapsedMs(初始化耗时)、backend、detProvider、recProvider、assets等信息。演示应用就是这样在页面上展示初始化结果的(见 main.ts 中initializeOcrEngine对 summary 字段的读取)。 - 推理结果检查:对已知含文字的图片调用
predict,检查result.items中的text与score,以及result.metrics.recognizedCount。演示应用在跑完后会在状态区显示形如OCR complete: N text lines recognized.的提示(这是演示 UI 的展示行为,N取决于图片内容,不是固定预期值)。
predict抛出异常时,演示应用的做法是读取err.message展示为OCR failed: ...,集成时建议同样捕获并展示错误信息而不是静默吞掉。
宿主应用必须处理的三件事
SDK 内部负责管理 OpenCV.js 与 ONNX Runtime,但以下三件事必须由你的应用承担(这是 browser.md "宿主环境职责"一节明确列出的):
- COOP/COEP 响应头:启用多线程 WASM 或 WebGPU 时需要。Vite 的写法见前文 demo 配置;其他框架在服务器配置响应头即可。
- ORT 环境选项:wasm 资源托管路径(
wasmPaths)、线程数(numThreads)、SIMD 开关(simd)。demo 中把 wasm 资源指向了https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/,你也可以把 onnxruntime-web 的 dist 文件放到自己的静态资源目录,把wasmPaths改成对应路径。 - module worker 支持:使用
worker: true时,构建工具需能产出并加载 module worker。demo 用 Vite 的worker: { format: "es" }解决。
可选:把推理移到 Worker
对大图推理可能阻塞 UI 时,可以让产线跑在独立 Worker 中,高层 API 不变:
const ocr = await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", worker: true, ortOptions: { backend: "wasm", wasmPaths: "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/", numThreads: 2, simd: true } });文档说明的行为要点:Worker 模式使用包内 Worker 脚本路径,而非 ONNX Runtime Web 的env.wasm.proxy;启用worker: true时包内会关闭 ORT 的 wasm proxy 以避免双层 Worker;浏览器输入先在主线程标准化再传入 Worker。因此cv.Mat在 Worker 模式下无法传输,不能作为 Worker 路径的输入,它只支持主线程产线路径。
可选:使用自己训练的模型
如果要替换为自有模型,为检测/识别分别传入模型名与资源地址:
await PaddleOCR.create({ textDetectionModelName: "my_det_model", textDetectionModelAsset: { url: "https://example.com/models/my_det_model.tar" }, textRecognitionModelName: "my_rec_model", textRecognitionModelAsset: { url: "https://example.com/models/my_rec_model.tar" } });资源包格式有硬性要求,不满足时会在初始化阶段以带明确信息的Error失败(不会静默失败):
| 要求 | 说明 |
|---|---|
| 归档格式 | 响应体必须是未压缩的.tar,当前实现对.tar.gz/ gzip 不做解压 |
| 必需文件 | tar 内必须包含inference.onnx与inference.yml(可在子目录中,按文件名匹配) |
model_name | inference.yml中必须能解析出model_name,且与create中传入的模型名完全一致,初始化加载后会校验 |
典型失败原因:下载非 2xx、tar 中找不到inference.onnx/inference.yml、资源为空、model_name缺失或不匹配、模型配置不完整、ONNX 无法加载。如需从 Paddle 模型转换出 ONNX 模型文件,可参考仓库中的 获取 ONNX 模型,转换得到的标准模型文件按上述要求打包为.tar后即可提供给 PaddleOCR.js 使用。
可选:可视化结果
子路径@paddleocr/paddleocr-js/viz提供把 OCR 结果渲染为图像的工具,viz 模块会渲染一张左右对比的合成图:左侧为带检测框的原始图,右侧为识别出的文字。
import { OcrVisualizer } from "@paddleocr/paddleocr-js/viz"; const viz = new OcrVisualizer({ font: { family: "Noto Sans SC", source: "/fonts/NotoSansSC-Regular.ttf" } }); const blob = await viz.toBlob(imageBitmap, result);注意toBlob只接受单个OcrResult,多图时取predict返回数组的首项即可;中日韩文字渲染需传入可访问的自定义字体文件路径(demo 使用了远程字体 URL,按你的部署环境替换为可访问的地址)。用完记得viz.dispose()。一次性函数renderOcrToBlob和配色函数deterministicColor同样从 viz 子路径导出。
边界与清理
PaddleOCR.create是异步操作,切换模型或后端时需要先await ocr.dispose()再重建,demo 的"Reinitialize"按钮就是这个流程(dispose 旧实例后重新 create)。- 初始化、预测都可能抛错(模型下载失败、ONNX 会话创建失败、后端不可用等),建议按 demo 的方式捕获
Error并向用户展示 message。 - 完整的 API 面:
PaddleOCR.create(options)、ocr.initialize()、ocr.getInitializationSummary()、ocr.predict(image | images[], params?)、ocr.dispose()、parseOcrPipelineConfigText(text)、normalizeOcrPipelineConfig(config)。 - 进一步细节可查阅 PaddleOCR.js 浏览器端部署文档、SDK 包 README 以及 paddleocr-js/docs/architecture_cn.md 的架构说明。
【免费下载链接】PaddleOCRTurn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between images/PDFs and LLMs. Supports 100+ languages.项目地址: https://gitcode.com/GitHub_Trending/pa/PaddleOCR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考