三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

OCR文字识别零门槛实战:Tesseract.js浏览器端上手全攻略

OCR文字识别零门槛实战:Tesseract.js浏览器端上手全攻略

OCR文字识别零门槛实战:Tesseract.js浏览器端上手全攻略

【免费下载链接】tesseract.jsPure Javascript OCR for more than 100 Languages 📖🎉🖥项目地址: https://gitcode.com/GitHub_Trending/te/tesseract.js

如果你手头有几十张截图、扫描件或票据照片,正为"怎么把里面的字一键抠出来"发愁——别急着搭后端服务、装Python环境。Tesseract.js 是一个纯 JavaScript 实现的 OCR 文字识别库,能识别 100 多种语言,直接在浏览器里跑,不需要任何服务器,加一行<script>标签就能开工。这篇文章用"10分钟起步 → 30分钟进阶 → 1小时工程化"的时间线,带你从零写出一个能用的网页版文字提取工具。

为什么说浏览器里的OCR值得一试

回想一下传统方案:先装 Tesseract 引擎,再配 Python 或 Java 环境,图片上传到服务器识别,最后把结果传回来。这套流程对个人工具和内部系统来说,太重了。

而 Tesseract.js 的思路完全不同——它把 Tesseract 引擎编译成 WebAssembly 塞进浏览器,语言包按需下载并缓存在 IndexedDB 里,识别全程在本地完成。这意味着:

  • 图片不出本地,敏感数据更安全;
  • 没有服务器费用和带宽压力;
  • 一个 HTML 文件就能跑起来,拿来即用。

它最大的限制也很明确:不支持 PDF,也不适合识别手写体。遇到这两类需求,得先自己把 PDF 转成图片、或者换用别的方案。想了解边界,看 docs/faq.md 里有说明。

下面我们直接动手。

第一阶段:10分钟写出第一个可用的识别页面

第1步:引入库文件

新建一个ocr-demo.html,在<head>里贴一行脚本:

<script src='https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'></script>

小贴士:固定版本号(@5)是官方推荐做法,避免 CDN 自动升级带来的兼容性变化。如果项目用的是 ES Module 语法,也可以换成https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.esm.min.js

加载完成后,全局会多出一个Tesseract对象,后面的代码都靠它。

第2步:三行代码打通"图片→文字"

把下面这段完整代码存进同一个文件:

<input type="file" id="uploader" accept="image/*"> <script> // 创建 Worker(可以理解为"一个识字工人"),参数1是语言,参数2是OEM模式 const worker = await Tesseract.createWorker('eng', 1, { logger: m => console.log(`进度: ${m.status} ${(m.progress * 100).toFixed(1)}%`) }); document.getElementById('uploader').addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const { data: { text } } = await worker.recognize(file); document.body.insertAdjacentHTML('beforeend', `<pre>识别结果:\n${text}</pre>`); }); </script>

用浏览器打开这个文件,随便传一张清晰的英文截图,控制台会依次打印loading tesseract coreinitializing tesseractrecognizing text等进度。看到这些日志,说明 Worker 已成功加载;图片传完后页面底部出现文字,你的第一个 OCR 功能就完成了。

第3步:理解两个关键概念

  • Worker 是什么?把它想成流水线上的工人:创建时负责"上岗培训"(加载核心引擎和语言包),之后每张图都交给它读。工人不用每次重新培训,所以创建一次、反复使用是性能关键。
  • 语言包去哪了?首次识别某语言时,库会从 CDN 拉取对应的.traineddata.gz,解压后缓存在浏览器的 IndexedDB 里,第二次就不再下载了。

自检标准:把上面代码中的eng换成chi_sim,再传一张中文截图,如果中文能正常识别,说明语言包机制没问题。完整语言列表见 docs/tesseract_lang_list.md。

第二阶段:30分钟掌握进阶配置

场景A:中英文混合识别

中文资料里夹着英文单词、数字是常态,用+号把语言代码拼起来即可:

const worker = await Tesseract.createWorker('chi_sim+eng'); const { data: { text } } = await worker.recognize('mixed-doc.png'); console.log(text);

语言包会按需并行下载,首次加载稍慢属正常现象。

场景B:只识别图片的某个区域

票据上的金额、验证码这类内容,往往只占图片一角。用rectangle参数框定区域,既能提速又能减少干扰:

const { data: { text } } = await worker.recognize(imageFile, { rectangle: { left: 0, top: 0, width: 300, height: 200 } // 左上角300x200区域 });

场景C:用识别模式参数换速度

Tesseract 支持十几套版面分析模式(PSM)。明确告诉引擎"这是单行文本",可以大幅省掉版面分析的开销:

// PSM.SINGLE_LINE 表示"整图只有一行字",配合白名单只认数字 await worker.setParameters({ tessedit_pageseg_mode: Tesseract.PSM.SINGLE_LINE, // 等价于 '7' tessedit_char_whitelist: '0123456789' // 只输出数字 });

常用模式速查:SINGLE_BLOCK('6',整块文字,默认)、SINGLE_LINE('7')、SINGLE_WORD('8')、SINGLE_CHAR('10')。定义见 src/constants/PSM.js。

场景D:让歪斜图片自动扶正

拍照扫描经常是歪的,识别前先旋转校正,并用返回的预处理图做可视化验证:

const ret = await worker.recognize(file, { rotateAuto: true }, { imageColor: true, // 返回旋转后的原色图 imageGrey: true, // 灰度图 imageBinary: true // 二值化图 }); // 可直接把 ret.data.imageBinary 赋给 <img> 的 src

小贴士:完整示例参考 examples/browser/image-processing.html,它会同时展示旋转前后的三张图,方便你判断预处理效果。

第三阶段:1小时搞定批量与工程化

批量并行:一个Scheduler管一队Worker

单张图片用单个 Worker 没问题,但一次要识别十张八张时,就得靠 Scheduler——它像一个"工头",把任务分配给多个 Worker 并行干,速度基本能翻几倍:

const scheduler = Tesseract.createScheduler(); // 先培训4个"工人"并登记进调度器 for (let i = 0; i < 4; i++) { const worker = await Tesseract.createWorker('eng', 1, { logger: m => console.log(m) // 生产环境建议去掉logger,减少主线程开销 }); scheduler.addWorker(worker); } // 把整个图片数组一次性丢进去,并行处理 const results = await Promise.all( imageFiles.map(file => scheduler.addJob('recognize', file)) ); const allTexts = results.map(r => r.data.text); console.log(allTexts); await scheduler.terminate(); // 结束后统一释放,会连带终止所有Worker

两个实用建议:

  • Worker 数量别贪多:建议不超过 CPU 核心数,加太多反而因线程切换拖慢速度;
  • 同一调度器里的 Worker 要同质:语言、参数必须一致,因为任务分给谁是不确定的,配置不同会导致结果漂移。原理见 docs/workers_vs_schedulers.md。

对比感受一下效果:官方基准测试里,单 Worker 逐个识别多张图大约要 45 秒,4 个 Worker 并行能把时间压到 15 秒左右。想看具体数据,翻 benchmarks/node/speed-benchmark.js。

长驻场景的"定期换血"

如果你在 Node 服务端用 Worker 连续跑一周,会踩到两个暗坑:

  1. WebAssembly 的内存只会涨不会缩,一张超大图会永久抬高进程内存;
  2. Worker 会把见过的词收进内部词典,识别几百份无关文档后,词典里全是错别字和噪音。

对策很简单:像换机油一样定期重建。例如每跑 500 个任务就scheduler.terminate()一次,重新创建。详见 docs/workers_vs_schedulers.md 的说明。

离线部署:把资源搬回家

内网环境访问不了 CDN 时,把核心文件和 Worker 脚本放到本地:

const worker = await Tesseract.createWorker('eng', 1, { corePath: '/local-tesseract-core', // 本地核心(tesseract.js-core)目录 workerPath: '/local-worker.js' // 本地Worker脚本路径 });

完整的离线方案(含 Node 版)见 docs/local-installation.md。

高频报错速查表

症状原因解法
控制台报404找不到worker.min.js用打包工具时 Worker 入口路径没对上显式传入workerPath指向本地dist/worker.min.js,Node 场景则指向src/worker-script/node/index.js
识别远程图片报跨域错误浏览器安全策略拦了图片加载先用fetch+FileReader把图片转成 Base64 再喂给recognize
语言包下载超时/一直卡在加载CDN 不可达或网络不稳换成corePath本地方案,或预先把.traineddata放到自己的静态资源上
数字/字母识别不准版面模式不合适试试tessedit_pageseg_mode: PSM.SINGLE_LINEtessedit_char_whitelist

排查思路再补一句:如果本地跑通了、换到框架里报Cannot find module,八成也是 Worker 入口被构建工具挪了位置,workerPath手动指一下通常能解决。

收尾:一套能直接落地的实践清单

一句话总结:Tesseract.js 让 OCR 文字识别从"重后端工程"变成了"前端小工具",浏览器里 10 分钟就能见到文字输出,进阶配置和批量并行也都有成熟的官方 API 支撑。

动手前过一遍这份清单:

  1. ✅ CDN 链接固定版本号(@5),别用裸最新版;
  2. ✅ 页面加载时创建一次 Worker,重复利用,全部结束后再terminate()
  3. ✅ 批量场景用 Scheduler,Worker 数量 ≈ CPU 核心数,且保持同质配置;
  4. ✅ 明确识别区域和版面模式,能框选就别整图跑;
  5. ✅ 涉密图片(身份证、手机号)在前端做脱敏预处理再识别;
  6. ✅ 服务端长驻场景定期重建 Worker,防内存膨胀和词典污染。

想继续深挖的话,这些文档按需取用:完整 API 参考 docs/api.md,更多可运行的浏览器/Node 示例在 examples/,常见疑问汇总在 docs/faq.md。需要本地跑源码时,仓库地址是https://gitcode.com/GitHub_Trending/te/tesseract.js

下面用项目自带的测试图感受一下识别效果:左边是标准的英文测试图(tests/assets/images/testocr.png),右边是一张带表格结构的账单(tests/assets/images/bill.png)——前者验证基础识别,后者能明显看出数字列、日期列的提取情况:

如果你还想挑战艺术排版文本(比如诗歌扫描页),可以拿 benchmarks/data/tyger.jpg 试试,看看 OCR 对不规则排版的容忍度。

现在,打开编辑器,把第一阶段的代码复制进去,传一张你手边的截图——从"图片"到"文字"的距离,其实只有这三行代码。

【免费下载链接】tesseract.jsPure Javascript OCR for more than 100 Languages 📖🎉🖥项目地址: https://gitcode.com/GitHub_Trending/te/tesseract.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

← 返回列表