All articles
9 min readOCR教程Tesseract隐私

在浏览器中从图片提取文字:完整 OCR 指南

不上传任何文件,把截图、扫描件和照片变成可编辑的文本。Tesseract.js 如何在 WebAssembly 中运行、该选哪种页面分割模式、什么时候该做预处理,以及如何用置信度分数来校验结果。

世界交给你的文字,往往是像素。一段报错截图、一张随手拍的收据、打印店扫描的 合同、从第十四排拍下来的幻灯片、一个日文商品标签。把这些像素还原成字符, 就是 OCR 的工作。而大多数人的第一反应,是把图片拖进某个在线 OCR 服务——那意味着上传,并且寄希望于对方的留存策略真的像它的营销页写的那么短。

你并不需要那个服务器。驱动这些服务的识别引擎同样可以编译成 WebAssembly,在你的机器上的一个标签页里离线运行。本文讲的是:按下「提取」 之后究竟发生了什么;决定你拿到干净文本还是一页噪声的三个设置;以及如何校验 结果,而不是盲信它。

按下提取时,实际在跑什么

引擎是 Tesseract——一个始于 1980 年代惠普实验室的识别项目,在第四版被 LSTM 神经网络彻底重写。浏览器移植版 Tesseract.js 把编译好的引擎包在 Web Worker 里,因此识别过程不会卡住页面。首次使用时会下载两份产物,之后由 浏览器缓存:

  • 引擎核心——Tesseract 本身的 WebAssembly 构建,几兆字节,每个站点下载一次,之后像其他静态资源一样被缓存。
  • 语言数据(traineddata)——你选择的每种语言对应的训练模型, 通常每种几兆字节。这一部分会叠加:识别「英文 + 简体中文」的下载量大约是 纯英文的两倍。

工具以 仅 LSTM 模式(OEM 1)运行引擎,也就是现代的神经网络 识别路径。更旧的 legacy 引擎更慢也更不准,被刻意排除。由于一切都在 Worker 中执行,大图识别时界面依然可以响应,你还能在标签页里继续打字。

第一步:有意识地选择语言

语言选择不是走形式。Tesseract 为每种语言加载一份模型,并用它们给候选字符 打分,所以选错或选多,都会实实在在地损失精度和时间。

  • 只选页面上真正有的语言。一张带英文产品名的德语发票需要 deueng。 多勾六种语言,等于强迫引擎在不存在的书写系统之间做裁决——这正是德文变音符号 被悄悄「纠正」成英文形近字的原因。
  • 简体与繁体是不同模型。chi_simchi_tra 是两份独立下载。来源混杂的 文档有时需要两者,大多数时候不需要。
  • 日语和韩语各有独立模型jpnkor),主要欧洲语言同理。中日韩与拉丁字母混排的页面,才是 真正应该选两三种语言的情况。

实用技巧:更改语言组合后工具会自动重新识别,因此你可以先试 eng,看一眼置信度,再加上第二种语言对比。首次下载之后, 切换语言几乎不再产生额外成本。

第二步:页面分割——最容易被跳过的设置

在识别任何一个字符之前,Tesseract 必须先判断文字在哪里。这就是页面 分割,也是整个工具里杠杆最高的一个控制项。工具暴露了四种模式,各自对应一个 Tesseract PSM 常量:

模式PSM适用场景
自动3默认。整页、混合排版、你还没仔细看过的文档。它会尝试找出分栏、段落和图片。
单一块6一块统一的文本:扫描的信件、合同页、文档截图。让引擎不必去找并不存在的 版面结构。
单行7裁剪出来的单独一行——报错信息、网址、序列号、字幕。在窄幅裁剪上比自动 模式准确得多。
散在文本11没有栅格、散布各处的文字:UI 截图、带标注的示意图、地图、图表。它会在 任何位置找词,而不期待段落。

如果结果是一堆乱码,先改这个,再做别的。用自动模式去识别 终端里的一行报错,是最常见的自伤式 OCR 失败——引擎把一行字当成整份文档的 版面来处理,结果什么结构都找不到。

第三步:预处理——灰度化还是 Otsu 二值化

两个预处理选项都在画布上于客户端完成,在图片进入引擎之前执行。它们很便宜, 但不能互换。

  • 不处理——从这里开始。现代 Tesseract 对彩色和抗锯齿的处理已经很好,而现代截图本身就是干净的。
  • 灰度——去掉颜色信息,保留全部亮度细节。对屏幕翻拍和彩色 扫描件来说是安全的第一个干预手段。
  • 二值化(Otsu 阈值)——用计算出的阈值把每个像素推成纯黑或 纯白。对字迹发虚、光照不均的扫描件效果极好;对渐变背景、低对比度 UI 文字以及依赖抗锯齿的内容则是破坏性的。

经验法则:扫描的纸张用二值化,截图和照片别动。如果文字带 彩色背景或轻微阴影,二值化会吃掉细笔画,把 l 变成 I

用置信度分数来校验结果

OCR 的输出是草稿,不是定稿。工具会给出逐词置信度,并允许你按阈值过滤—— 这把校对从「通读全部」变成「只读那 5%」。

  • 先过滤,再阅读。把置信度阈值调高,直到只剩可疑词被标出来,再对照图片检查这些词。一份干净的 扫描件在高阈值下通常只剩极少数词。
  • 找规律,而不是找错别字。如果某个产品名每次都错,那要改的是查找替换,不是重新识别。如果每个数字都错, 那是分割模式或预处理选错了。
  • 打开包围盒叠加层。看到识别框画在图上,分块错误立刻现形:跨了两栏的框,或者引擎根本没进去的 一整块文字。
  • 要紧的场合导出 JSON。结构化输出会把逐词置信度和文本一起带出来,下游脚本就能按你的阈值标记 可疑内容,而不是静默地把错误发出去。

四个实用配方

扫描的合同或信件

语言:只选文档语言。模式:单一块。预处理:扫描件发灰或光照 不均就 二值化,本来就清晰就用 灰度。正文 基本不会错;专有名词、日期和金额务必人工核对——它们既是唯一有法律意义的 内容,也恰恰是 OCR 最不擅长的部分。

报错信息或代码截图

语言:eng。模式:单行用 单行,整个 IDE 窗口、元素散布用 散在文本。预处理:不处理——对深色主题截图做二值化会毁掉它。直接从剪贴板 粘贴,别先存文件。

翻拍的收据

平铺拍摄、填满画面、避免阴影。语言:收据语言。模式:散在文本——收据没有段落结构。预处理:先试灰度。每一个数字 都要核对:在低对比度的热敏纸上,看错小数点是经典故障。

中日混排页面

语言:jpnchi_sim/chi_tra, 若含拉丁文字再加 eng。模式:整页用 自动, 分栏用 单一块。需要留意的是,日文竖排确实是当前大多数 浏览器 OCR 流程的弱项;横排正文可靠,竖排排版不可靠。

浏览器 OCR 仍然做不到的地方

  • 手写体。Tesseract 是用印刷体训练的。工整的印刷体手写 有时可以,连笔草书不行。
  • 分辨率不足。正文文字在原尺寸下大约需要 300 DPI。隔着会议室拍下来的屏幕没有那么多像素。
  • 旋转与倾斜。超过两三度,精度就会急剧下降。先校正。
  • 表格与表单。词能认出来,结构通常认不出来。 表格请做好手工重建的准备。
  • 艺术化标题字。Logo、海报、细体大字距字体。

预期如何,以及怎样自己测出来

我们刻意给出的是机制和区间,而不是「0.4 秒」这样的单一数字,因为识别耗时 取决于你的 CPU、浏览器的 WebAssembly 性能、语言数量以及图片上有多少文字。 工具会在每次结果旁打印实际耗时,因此你一分钟内就能拿到自己的数字:同一张图 分别用一种语言和三种语言各跑一次,再分别用自动模式和单行模式各跑一次。 你观察到的差值,才是真正对你有影响的部分——它通常远大于浏览器之间的差别。

真正值得提前规划的是结构性成本:一次会话的首次运行要付出引擎加语言数据的 下载,之后每次运行都是纯计算。这与云端 OCR 服务正好相反——那边每一页都是 一次 API 调用,也是一次留存事件。

为什么本地处理很重要

人们拿去做 OCR 的文档,恰恰大多是那些不该上传的文档:合同、 医疗文件、身份证件、带客户名称的发票、内部财务数据、法律往来函件。上传它们, 等于在你无法控制的基础设施上留下一份副本,受你没读过的条款约束,存放在可能 不属于你所在司法管辖区的机房里。而在标签页里完成识别,字节从未移动:事后 没什么可删除的,没什么可泄露的,也没什么可被调取的。对相当多真实工作来说, 这不是偏好问题——它决定了你到底能不能用这个工具。

打开OCR 工具丢一张图进去,看着识别框出现。改一个设置再跑一次,你对这个引擎的理解就会 超过大多数为它付费的人。

Try the tools

Everything described here runs for free in your browser — no sign-up, no uploads. Explore the full matrix of on-device AI tools from the homepage, or read the end-to-end workflows.

Back to the matrix