Tesseract.js v7 实战指南:在浏览器与 Node.js 中运行多语言 OCR
【免费下载链接】tesseract.jsPure Javascript OCR for more than 100 Languages 📖🎉🖥项目地址: https://gitcode.com/GitHub_Trending/te/tesseract.js
Tesseract.js 是一个纯 JavaScript 的 OCR 库,通过 WebAssembly 封装 Tesseract OCR 引擎,可在浏览器和 Node.js 两个环境中从图片中识别出近百种语言的文本。本文基于仓库根目录的 README.md 展开,并结合 src/createWorker.js、src/index.js 等源码梳理了安装、Worker 生命周期、调度器并行处理、核心参数与版本升级注意事项,读完你可以独立完成从 CDN 引入到 Node 服务集成的完整 OCR 方案。
项目定位:Tesseract 引擎的 JavaScript 封装层
Tesseract.js 的目标是把独立的 Tesseract 可以看到,当前仓库版本为7.0.0,核心依赖tesseract.js-core@^7.0.0提供了 wasm 运行时,其余依赖(bmp-js、zlibjs、idb-keyval等)分别负责图片解码、gzip 解压与浏览器 IndexedDB 缓存。
README 对项目边界有两条明确的“不做”声明,集成前必须了解:
- 不支持 PDF 文件:如需对 PDF 做 OCR,需用第三方库先把 PDF 渲染为图片序列;
- 不修改 Tesseract 识别模型:识别精度完全取决于底层 Tesseract 引擎本身,本项目不会为此做任何模型层面的增强。
这两个边界在 docs/faq.md 中也有呼应:Tesseract.js 不编辑底层引擎,引擎相关的 bug 应到 Tesseract 主项目提出;手写体识别效果差也属于引擎模型层面的限制,没有任何参数组合能显著改善。
安装方式:CDN、npm 与 Node.js 版本要求
Tesseract.js 兼容三种接入方式:<script>标签(本地拷贝或 CDN)、webpack 等打包器、Node.js 直接运行。
CDN 引入
<!-- v5 --> <script src='https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'></script>引入后全局变量Tesseract可用,通过Tesseract.createWorker创建 worker。若使用import语法,仓库同时提供 ESM 构建产物(dist/tesseract.esm.min.js,由 package.json 中rollup -c scripts/rollup.esm.mjs的构建步骤生成)。
Node.js 引入
# 最新版本 npm install tesseract.js yarn add tesseract.js # 旧版本 npm install tesseract.js@3.0.3 yarn add tesseract.js@3.0.3环境要求:Tesseract.js v7 需要 Node.js v16 或更新版本(v6 需要 Node.js v14 或更新版本)。
仓库内官方示例 examples/node/recognize.js 展示了 Node 环境下的最小用法:
const { createWorker } = require('../..'); (async () => { const worker = await createWorker('eng', 1, { logger: (m) => console.log(m), // 输出进度日志 }); const { data: { text } } = await worker.recognize(image); console.log(text); await worker.terminate(); })();快速上手:createWorker → recognize → terminate 三步模式
README 给出的核心用法非常简单:
import { createWorker } from 'tesseract.js'; (async () => { const worker = await createWorker('eng'); const ret = await worker.recognize('https://tesseract.projectnaptha.com/img/eng_bw.png'); console.log(ret.data.text); await worker.terminate(); })();多图片场景的关键优化:识别多张图片时,应只创建一个 worker,对每张图片依次调用worker.recognize,最后统一worker.terminate()——而不是为每张图片重复走一遍完整的创建/加载流程。
源码视角:worker 创建时发生了什么
从 src/createWorker.js 可以看到,createWorker的完整签名是:
module.exports = async (langs = 'eng', oem = OEM.LSTM_ONLY, _options = {}, config = {}) => { ... }即四个参数依次为:语言(默认'eng')、引擎模式 OEM(默认OEM.LSTM_ONLY,值为 1)、自定义选项对象、初始化参数对象。其内部实现是一条三阶段初始化链(见 src/createWorker.js#L239-L243):
loadInternal() // 1. 加载 wasm core(按设备能力选 SIMD/LSTM 构建) .then(() => loadLanguageInternal(langs)) // 2. 下载并缓存语言 traineddata .then(() => initializeInternal(langs, oem, config)) // 3. 初始化 Tesseract 引擎 .then(() => workerResResolve(resolveObj))也就是说,await createWorker(...)返回时,wasm 核心、语言数据与引擎初始化已全部完成。这正是 v5 之后的破坏性变更:worker.initialize与worker.loadLanguage应从代码中删除(旧版需要手动调用,新版 worker 创建即预加载,源码中的load函数已仅保留一个 deprecation 警告)。
worker 对象最终暴露的方法集合(src/createWorker.js#L224-L237)为:load(已废弃)、writeText、readText、removeFile、FS、reinitialize、setParameters、recognize、detect、terminate。每个方法内部都通过startJob构造一个 job,经send投递给独立的 Web Worker / Worker Thread 执行,主线程只通过 Promise 拿到结果。
引擎模式(OEM)
OEM 常量定义在 src/constants/OEM.js:
| 值 | 名称 | 含义 |
|---|---|---|
| 0 | TESSERACT_ONLY | 仅 Legacy 引擎 |
| 1 | LSTM_ONLY | 仅 LSTM 引擎(默认) |
| 2 | TESSERACT_LSTM_COMBINED | 两者结合 |
| 3 | DEFAULT | 由引擎自动选择 |
设置非默认语言与 OEM 的例子:createWorker("chi_sim", 1)。需要特别注意源码中的一段限制逻辑(src/createWorker.js#L36):默认情况下下载的 wasm core 只支持 LSTM;如果之后想用worker.reinitialize切到 Legacy 模式(OEM 0/2),必须在创建时就通过legacyCore: true、legacyLang: true确保下载了支持 Legacy 的代码与语言数据,否则会抛出Legacy model requested but code missing.。
createWorker 选项详解
完整的参数说明见 docs/api.md,整理如下:
| 选项 | 说明 |
|---|---|
corePath | 指向包含全部 4 个core 文件的目录:tesseract-core.wasm.js、tesseract-core-simd.wasm.js、tesseract-core-lstm.wasm.js、tesseract-core-simd-lstm.wasm.js。不要指向单个.js文件,Tesseract.js 需要能根据设备能力自行选择构建版本 |
langPath | traineddata 下载路径,末尾不要带/ |
workerPath | worker 脚本下载路径 |
dataPath | wasm 文件系统中保存 traineddata 的路径,一般不修改 |
cachePath | traineddata 缓存路径;Node 中更常用,浏览器中仅改变 IndexedDB 的 key |
cacheMethod | 缓存策略:write(默认,读写)、readOnly、refresh、none |
legacyCore | 设为true确保下载的代码同时支持 Legacy 模型 |
legacyLang | 设为true确保下载的语言数据同时支持 Legacy 模型 |
workerBlobURL | 是否用 Blob URL 加载 worker 脚本,默认true |
gzip | 远端 traineddata 是否 gzip 压缩,默认true |
logger | 进度回调,如m => console.log(m) |
errorHandler | worker 错误处理函数,如err => console.error(err) |
第四参数config用于设置 Tesseract 的“init only”参数——这类参数在引擎初始化之后无法再修改(如load_system_dawg、load_number_dawg、load_punc_dawg),只能通过它传入;其余大部分 Tesseract 参数都可以初始化后通过worker.setParameters或recognize的 options 修改。
自定义路径的典型场景(完全本地化部署)见 docs/local-installation.md:
const worker = await createWorker('eng', 1, { workerPath: 'https://cdn.jsdelivr.net/npm/tesseract.js@v5.0.0/dist/worker.min.js', langPath: 'https://tessdata.projectnaptha.com/4.0.0', corePath: 'https://cdn.jsdelivr.net/npm/tesseract.js-core@v5.0.0', });recognize 与常用参数
worker.recognize(image, options, output, jobId)是核心 OCR 调用,docs/api.md 与 docs/examples.md 中的典型用法:
// 基础识别 const { data: { text } } = await worker.recognize(image); // 只识别图片中的一个矩形区域 const { data: { text } } = await worker.recognize(image, { rectangle: { top: 0, left: 0, width: 100, height: 100 }, });输入格式(详见 docs/image-format.md):支持 bmp、jpg、png、pbm、webp、gif(非动画);数据类型上,浏览器和 Node 均支持 base64 dataURL 字符串与 buffer,浏览器额外支持File/Blob、img/canvas元素,Node 额外支持本地图片路径字符串。图片需要“格式 + 数据类型”同时满足,例如包含 png 的 buffer 可以,包含裸像素数据的 buffer 不行。另外 API 文档特别提示:图像分辨率越高识别效果通常越好,对同一张图先做上采样常常能显著提升结果。
输出格式:默认只返回text。如需其他格式,通过output参数显式开启,例如worker.recognize(image, {}, { hocr: true })(完整列表:text、blocks(json)、hocr、tsv)。这正是 v6 的破坏性变更——此前默认返回全部输出,现在除text外全部默认关闭。
setParameters 常用参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
tessedit_pageseg_mode | enum | PSM.SINGLE_BLOCK | 页面切分模式,取值见 src/constants/PSM.js |
tessedit_char_whitelist | string | '' | 字符白名单,限定结果只包含这些字符,适合内容受限的场景(如纯数字) |
preserve_interword_spaces | string | '0' | '0'或'1',保留词间空格 |
user_defined_dpi | string | '' | 自定义 dpi,用于修复Warning: Invalid resolution 0 dpi. Using 70 instead. |
await worker.setParameters({ tessedit_char_whitelist: '0123456789' });注意:setParameters不能修改oem——它只在初始化时确定,切换必须走worker.reinitialize(langs, oem, config)。PSM 常量共 14 种取值(从OSD_ONLY: '0'到RAW_LINE: '13'),Tesseract.js 默认使用SINGLE_BLOCK(值'6'),而 Tesseract CLI 默认AUTO(值'3')——这也是两者结果可能不同的原因之一,详见 docs/faq.md。
worker.detect(image)则执行 OSD(方向与文字方向检测)而非 OCR,同样要求 worker 已加载 Legacy 支持(创建时设置legacyCore: true, legacyLang: true),这一点在 src/createWorker.js#L178-L180 中有对应的运行时检查。
调度器(Scheduler):并行处理多张图片
docs/workers_vs_schedulers.md 给出了两种执行模式:直接使用单个 worker,或用 scheduler 管理多个 worker 并行处理。单任务场景下 scheduler 没有优势,但批量任务场景下能显著提升吞吐。示例:用 4 个 worker 并行执行 10 个识别任务。
const scheduler = Tesseract.createScheduler(); const workerGen = async () => { const worker = await Tesseract.createWorker('eng'); scheduler.addWorker(worker); }; const workerN = 4; (async () => { const resArr = Array(workerN); for (let i = 0; i < workerN; i++) { resArr[i] = workerGen(); } await Promise.all(resArr); /** Add 10 recognition jobs */ const results = await Promise.all(Array(10).fill(0).map(() => ( scheduler.addJob('recognize', 'https://tesseract.projectnaptha.com/img/eng_bw.png').then((x) => x.data.text) ))); await scheduler.terminate(); // 同时终止所有 worker })();Scheduler API 包括:addWorker(worker)(一个 worker 只应加入一个 scheduler)、addJob(action, ...payload)(目前支持recognize与detect)、getQueueLen()、getNumWorkers()、terminate()(终止所有 worker)。
两条重要的工程约束(来自同一文档):
- 加入同一 scheduler 的 worker 应当同构——语言、参数一致。scheduler 分配任务给哪个 worker 是不确定的,worker 之间差异会导致识别结果不可复现;
- 长驻 Node.js 服务中应定期重建 worker/scheduler(例如每 500 个任务重建一次)。原因是 wasm 内存在运行中只能扩张不能收缩,一张大图片会永久抬高 worker 的内存水位;同时 Tesseract 会随任务不断往内部词典中“学习”新词,数千个无关文档跑完后词典会被污染甚至混入错别字。
版本升级须知:v4 / v5 / v6 的重大变更
README 汇总了三个大版本的破坏性变更,升级时逐条对照即可:
v6
- 修复了此前版本的内存泄漏,运行时与内存占用整体下降;
- 破坏性变更:除
text外的所有输出格式默认关闭(重新启用示例:worker.recognize(image, {}, { hocr: true }));blocks输出对象的内部结构有小幅调整。
v5
- 默认文件体积大幅缩小(英语缩小 54%,中文缩小 73%),首次使用(无缓存)的运行时约降低 50%;内存占用显著下降;
- 破坏性变更:
createWorker参数签名改变——非默认语言与 OEM 直接作为createWorker的实参传入(如createWorker("chi_sim", 1));worker.initialize与worker.loadLanguage应从代码中删除。
v4
- 新增旋转预处理选项(含自动旋转 auto-rotate),显著提升精度;
- 可取回处理后的中间图片(旋转、灰度、二值化版本);
- 改进并行处理(scheduler)支持;
- 破坏性变更:
createWorker变为 async;getPDF函数被recognize的pdf选项取代。
支持语言与常见问题
- 支持语言清单见 docs/tesseract_lang_list.md(近 100 种语言),多语言混合识别可用数组形式:
createWorker(['eng', 'chi_tra']); - PDF 不支持:可选方案是用 PDF.js / muPDF 等第三方库将 PDF 渲染为图片后再识别;
- 手写体不支持:Tesseract 模型围绕印刷体假设构建;
- 与 Tesseract CLI 结果不一致时:依次核对参数(
oem/psm默认值不同)、语言数据(OEM 1 默认使用整数化后的 tessdata_best 数据)与 Tesseract 引擎版本,完整排查流程见 docs/faq.md; - 框架集成报
Cannot find module:通常是因为打包系统打乱了 worker 入口位置,手动设置workerPath指向本地的worker-script/node/index.js(Node)或worker.min.js(浏览器)即可解决。
本地开发、构建与测试
仓库提供了完整的开发工作流(README “Contributing” 一节):
git clone https://gitcode.com/GitHub_Trending/te/tesseract.js.git cd tesseract.js npm install npm start # 启动开发服务器开发服务器基于 scripts/server.js,启动后在浏览器打开http://localhost:3000/examples/browser/basic-efficient.html即可体验;修改src目录下的文件会自动重新构建tesseract.min.js与worker.min.js。
npm run build # 构建静态文件,输出到 dist 目录 npm run lint # eslint 检查 src npm run test # 并行启动 dev server 并运行浏览器(karma)+ Node(mocha)测试从 package.json 的脚本定义看,build实际是rimraf dist && webpack --config scripts/webpack.config.prod.js && rollup -c scripts/rollup.esm.mjs,即 webpack 产出 UMD 主包与 worker 包、rollup 产出 ESM 构建;test由npm-run-all并行拉起 dev server 与浏览器/Node 双端测试套件,测试用例位于 tests/。提交 PR 前应确保npm run lint与npm run test全部通过。
总结
Tesseract.js 的架构可以概括为:主线程 API(createWorker/createScheduler/setLogging等,导出定义见 src/index.js)+ 独立 worker 线程内的 wasm 引擎 + 按需下载并缓存的语言数据。掌握“worker 一次创建、多任务复用、最后 terminate”的基本模式,配合 scheduler 处理批量任务、setParameters微调识别行为、corePath/langPath完成本地化部署,就能覆盖绝大多数 OCR 集成场景。项目细节可进一步参考 docs/api.md、docs/performance.md 与 examples/ 目录下的官方示例。
【免费下载链接】tesseract.jsPure Javascript OCR for more than 100 Languages 📖🎉🖥项目地址: https://gitcode.com/GitHub_Trending/te/tesseract.js
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考