1985 年,HP 实验室英国布里斯托尔分部,一个叫 Ray Smith 的研究员开始写一个光学字符识别引擎。
当时没人想到,这个项目会活 40 年,换三家东家,最终成为地球上部署最广泛的 OCR 引擎------手机里的文字提取、PDF 工具、文档扫描仪、开源办公套件,背后几乎都有它的影子。
它叫 Tesseract。
75k Star,10.6k Fork,Apache 2.0 协议。支持 100+ 语言,从 C 写到 C++,从传统特征工程写到 LSTM 神经网络。三次改写,三次重生,从未断更。
第一阶段:HP 的传奇开局(1985--2005)
Tesseract 的第一版,1985 年开始写,1994 年成型。那是个没有深度学习的年代,OCR 靠的是纯粹的计算机视觉算法和手写的特征工程。
1995 年,联合国测试全球商用 OCR 引擎的准确率。Tesseract 排前三。而且它是前三名里唯一一个不是卖钱的商用产品------它是 HP 实验室的研究项目。
这一版的核心架构在 src/ccmain/ 目录下还能找到痕迹。control.cpp 是识别流程的主控,applybox.cpp 处理字符框检测,adaptions.cpp 做自适应识别。
它的核心思路很朴素:
- 页面分析 → 把图片切成块
- 字符分割 → 把块切成单个字符
- 特征提取 → 每个字符提取几何特征
- 分类器识别 → 匹配特征库
这种"先分割再识别"的思路,在那个年代是标准做法。但它的工程实现特别扎实,对噪点、字体变化、低分辨率的鲁棒性,比很多商用产品还好。
2005 年,HP 把它开源了。
第二阶段:Google 接手的黄金 11 年(2006--2017)
2006 年 Google 接手 Tesseract 的维护。这 11 年是它真正成为全球标准的时期。
Google 做了几件关键的事:
全面 C++ 化。 早期的代码还混着大量 C 风格,Google 接手后逐步重构,建立了清晰的 API 边界------include/tesseract/baseapi.h 是 C++ 主入口,include/tesseract/capi.h 是 C 封装,方便各种语言绑定。
多语言支持爆发。 从最初的几十种语言,扩展到 100+。中文、日文、韩文、阿拉伯文、希伯来文......每一种语言都有自己的 tessdata 训练数据文件,这也是它能被全球广泛使用的根本原因。
但真正的转折点是 Tesseract 4,2018 年发布。
Tesseract 4 把整个识别引擎换成了 LSTM 神经网络。这不是在旧引擎上套个深度学习壳,而是从根部重写了------传统的字符分割 + 特征提取 + 分类器的流水线,换成了基于行的 LSTM 序列识别。
你可以在 src/lstm/ 目录下看到这次革命的全部代码:
lstmrecognizer.cpp--- LSTM 识别器主类lstmtrainer.cpp--- 训练器实现recodebeam.cpp--- Beam Search 解码weightmatrix.cpp--- 权重矩阵操作
这是整个项目最大胆的技术决策。
一个已经被广泛使用的成熟项目,敢于把核心引擎全部换掉,同时保留完整的向后兼容(--oem 0 切回传统引擎)。这种魄力,在开源世界里不多见。
而且 Google 没有用 TensorFlow 或 Caffe 这些第三方框架。它自己写了一个轻量级的 LSTM 实现,纯 C++,零深度学习框架依赖。
为什么? 因为 Tesseract 需要跑在各种环境里------嵌入式设备、老服务器、没有 GPU 的机器。依赖一个大型深度学习框架,会把 90% 的用户拦在外面。
这是我觉得 Tesseract 最值得学习的工程哲学。它永远把「用户能不能轻松用上」放在「技术先不先进」前面。
第三阶段:社区接手的现在(2018--至今)
2017 年 8 月,Google 把维护权移交给社区。Stefan Weil 成为首席开发者,Zdenko Podobny 是维护者。
这一阶段最大的变化不是功能,而是性能优化的深度。
翻 src/arch/ 目录,你会看到 Tesseract 对几乎所有主流 CPU 指令集都做了手撸 SIMD 优化:
bash
src/arch/dotproductavx512.cpp # AVX-512
src/arch/dotproductavx2.cpp # AVX2
src/arch/dotproductsse.cpp # SSE
src/arch/dotproductneon.cpp # ARM NEON
src/arch/dotproductrvv.cpp # RISC-V Vector
src/arch/intsimdmatrixavx2.cpp
src/arch/intsimdmatrixsse.cpp
src/arch/intsimdmatrixneon.cpp
src/arch/intsimdmatrixrvv.cpp
src/arch/simddetect.cpp # 运行时自动检测 CPU 特性
simddetect.cpp 在程序启动时检测 CPU 支持哪些指令集,然后动态链接到最快的实现。Intel 的 CPU 走 AVX512,ARM 的手机走 NEON,RISC-V 的开发板走 RVV------用户代码一行不用改,自动拿到最快的速度。
这种"在编译层做抽象、在运行时选实现"的做法,比很多一上来就要求 AVX2 才能跑的深度学习框架务实得多。
还有 include/tesseract/renderer.h 定义的渲染器架构------支持 plain text、hOCR HTML、PDF、TSV、ALTO、PAGE 六种输出格式,每种格式是一个独立的 renderer 类,扩展新格式只需要实现同一个接口。
这就是为什么 Tesseract 能被几千个项目集成,却从来没听说过"集成 Tesseract 太麻烦"的抱怨。它的 API 边界设计得太克制了,baseapi.h 里核心接口不到 30 个函数,够用,又不啰嗦。
不是所有问题都解决了------诚实的边界
Tesseract 很强大,但它的局限也很明显。这些问题不是 bug,是设计权衡的必然结果。
第一,阿拉伯语 RTL 文本长期有问题。 Issue #238 有 102 条评论,#648 有 77 条。阿拉伯语是从右往左写的,而且字母会根据前后位置变形状。Tesseract 的 LSTM 引擎理论上能处理 RTL,但实际用的时候,生成可搜索 PDF 时文字顺序还是反的。这个问题从 2016 年讨论到现在,一直没彻底解决。
第二,微调训练门槛极高。 Issue #590、#2132 讨论的都是训练问题。官方训练文档全、步骤多、依赖复杂,普通用户想针对自己的垂直场景(比如手写体、票据、特定字体)微调一个模型,基本要踩一周坑才能跑通。
第三,没有表格提取。 Issue #1714 是 2019 年开的 feature request,69 条评论,用户呼声很高。但表格需要布局理解 + 单元格分割 + 跨列跨行识别,这超出了 Tesseract 作为"行级 OCR 引擎"的定位。它只负责识别文字,不负责理解文档结构。
第四,没有内置版面分析。 很多人不知道,Tesseract 自己不会做复杂的版面分析。它默认假设页面是流式文本,如果是多栏、有图片、有复杂排版的文档,你需要先在外面把每个文本块切出来,再喂给 Tesseract。
这些问题不是没人修,是它的定位决定的------Tesseract 是一个 OCR 引擎,不是一个端到端的文档理解解决方案。引擎就该做引擎该做的事,做得极致,不越界。
为什么它能活 40 年
开源项目的平均寿命是 3-5 年。能活 10 年的不多,能活 40 年的是传奇。
Tesseract 能活这么久,我觉得三个原因。
第一,定位极其清晰。 它从第一天开始就是「一个 OCR 引擎」,不是扫描仪 App,不是文档处理系统,不是机器学习平台。它只做"图片 → 文字"这一件事,而且把这件事做到了全球最好。40 年里,每一次重大升级(C++ 化、多语言、LSTM 重写、SIMD 优化)都是在强化这个核心定位,从来没有跑偏过。
第二,极端重视兼容性和可移植性。 C++ 11 就能编译,没有奇奇怪怪的构建依赖,不强制要求新 CPU 指令集,不绑定任何深度学习框架,API 从 Tesseract 3 到 5 基本没变。这种"不给用户添麻烦"的态度,是它能被广泛集成的根本。
第三,维护者的克制。 每一个新功能加入都极其谨慎。表格提取呼声那么高,维护者没有为了 KPI 硬塞一个半吊子实现进来;多模态、端到端 Transformer 现在很火,Tesseract 也没急着蹭热点。它的节奏是慢的、稳的、对用户负责的。
很多开源项目死不是因为做得太少,而是因为做得太多,最后代码膨胀、维护失控、用户流失。
一个被低估的事实
你可能不知道,现在几乎所有流行的 OCR 项目,都受过 Tesseract 的影响。
PaddleOCR 的中文模型训练流程,参考了 Tesseract 的数据增广策略。EasyOCR 早期版本直接用了 Tesseract 的图像处理方法。DocTR 的评估基准,也是跟 Tesseract 比的。
它就像开源世界的一块基石。你可能不直接用它,但你用的东西大概率站在它的肩膀上。
40 年,三家公司,三代技术。
从 HP 实验室的研究员手写特征工程,到 Google 工程师用 C++ 重写 LSTM,再到现在社区贡献者手撸五种 CPU 的 SIMD 优化。Tesseract 的每一行代码,都写着同一个朴素的信念。
好的基础设施,应该让用户感觉不到它的存在。
它应该稳定、可靠、免费、不折腾、随处可用,然后安静地在背后处理这个世界上所有需要被识别的文字。
这就是 Tesseract。