本仓库是 eSearch的 OCR 服务依赖
支持本地 OCR(基于 PaddleOCRv4)
- 文字检测
- 文字识别
- 文档旋转识别
- 排版分析识别分栏、段落、阅读方向
- 轻量,仅需要引入 onnx,gizp 后 10kB
- 支持浏览器(esm)、node(CommonJS) 和 Electron
- 完善的类型提示
- 可简单分析背景色和文字颜色
基于onnxruntime的 web runtime,使用 wasm 运行,未来可能使用 webgl 甚至是 webgpu。
部分模型已打包:Releases 4.0.0,由 paddleOCR 官方的模型转换而来。
现已支持 v5 版本模型。
模型文字: 中(简体)英混合、中文繁体、英文、韩文、日文、泰卢固文、卡纳达文、泰米尔文、拉丁文、阿拉伯字母、斯拉夫字母、梵文字母。
中英混合 v4 为ch.zip
,中英混合 v4_doc 为ch_v4_doc.zip
文档方向识别模型Releases 8.1.0
npm i esearch-ocr onnxruntime-web
web
import * as ocr from "esearch-ocr";
import * as ort from "onnxruntime-web";
部分引入
import { init } from "esearch-ocr";
import * as ort from "onnxruntime-web";
node
const ocr = require("esearch-ocr");
const ort = require("onnxruntime-node");
Important
需要手动安装 onnxruntime(onnxruntime-node 或 onnxruntime-web,视平台而定),并在init
参数中传入ort
这样设计是因为 web 和 electron 可以使用不同的 ort,很难协调,不如让开发者自己决定
浏览器或 Electron 示例
const localOCR = await ocr.init({
det: {
input: "ocr/det.onnx", // det指识别模型,如果上面提到的文字包没有,那就用中英混合的det(在ch.zip里)。
},
rec: {
input: "ocr/rec.onnx",
decodeDic: "abcdefg...", // 在模型压缩包中的txt文件,需要传入里面的内容而不是路径
},
ort,
});
const url = "data:image/png;base64,..."; // 还支持 HTMLImageElement | HTMLCanvasElement | ImageData
localOCR
.ocr(url)
.then((result) => {}) // 见下面的解释
.catch((e) => {});
这在需要多次运行 ocr 时非常有用
node.js 环境还需要设置 canvas,运行方式也不一样,见node.js 示例,需要安装canvas
init type
type init = {
ort: typeof import("onnxruntime-web");
det: {
input: string | ArrayBufferLike | Uint8Array;
ratio?: number; // 缩放,小于1 越小越快,但准确率也会下降一点
on?: (r: detResultType) => void;
};
rec: {
input: string | ArrayBufferLike | Uint8Array;
decodeDic: string; // 字典文件内容,不是路径
imgh?: number;
on?: (index: number, result: { text: string; mean: number }, total: number) => void;
optimize?: {
space?: boolean; // v3 v4识别时英文空格不理想,但v5得到了改善,默认为true,需要传入false来关闭
};
};
docCls?: {
input: string | ArrayBufferLike | Uint8Array; // 文档旋转识别,所有文字方向应该一致,各行不同向有待开发
};
analyzeLayout?: {
docDirs?: ReadingDir[]; // 可限定文档阅读方向的识别范围,默认为常规方向和竖排方向
columnsTip?: ColumnsTip;
};
dev?: boolean;
};
// 更多类型请查看代码或提示
Note
对 v5 模型,需要在 rec.optimize.space 明确传入 false,否则会加很多空格
对于返回的值
type resultType = {
text: string;
mean: number;
box: BoxType; // ↖ ↗ ↘ ↙
style: { bg: color; text: color }; // rgb数组,表示背景颜色和文字颜色,在简单移除文字时非常有用
}[];
type ReadingDirPart = "lr" | "rl" | "tb" | "bt";
type output = {
src: resultType; // 每个视觉行,rec输出
columns: {
// 分栏,如左右分栏
src: resultType;
outerBox: BoxType;
parragraphs: {
src: resultType;
parse: resultType[0];
}[];
}[];
parragraphs: resultType; // 聚合了columns的每个段落
readingDir: {
inline: ReadingDirPart; // 行内的阅读方向
block: ReadingDirPart; // 行的排版方向
};
angle: {
reading: { inline: number; block: number }; // 阅读方向的具体角度
angle: number; // 整体旋转角,如果小于1°可忽略
};
};
合并的文字可以使用
result.parragraphs.map((item) => item.text).join("\n");
除了 ocr
函数,还有det
函数,可单独运行,检测文字坐标;rec
函数,可单独运行,检测文字内容。具体定义可看类型提示。这个文件给出了示例。
对于竖排文字,如古籍等,在 cls 时会进行旋转。如果明确了输入,可以不用 cls。
支持识别竖排文字排版段落。
模型需要转换为 onnx 才能使用:Paddle2ONNX 或在线转换
使用 Electron 来调试,既有可视化也要onnxruntime-node
的本地性能。