简介:Tesseract-OCR 是一款免费开源的光学字符识别引擎,可从图像中提取文字并输出多种文本格式,支持百余种语言。本资源面向需要集成 OCR 能力的开发者、数据录入与文档管理从业者,提供完整安装包及中文语言包,解决中文文档识别精度不足的问题。压缩包共 724 个文件,约 36.01MB,以 C++ 源码(cpp、h)和 Java、XML 等接口文件为主,同时包含训练数据、语言模型、配置脚本与命令行工具,如 unicharset_extractor、shapeclustering、mftraining 等,便于二次编译与模型训练。已有 288 人学习下载。安装后即可用于自动化文档扫描、图像文字提取等任务,中文语言包进一步提升了汉字识别准确率,适合从入门到进阶的 OCR 实践者参考使用。
1. 从一张发票照片到可编辑文本:Tesseract-OCR 到底能替你省下什么
上周帮一个做财务系统的朋友处理一批扫描件,对方发来 200 多张发票照片,要求把发票代码、金额、开票日期提取成 Excel。他第一反应是找外包录入,报价按张算,我直接拦住了——这种固定版式的印刷体识别,Tesseract-OCR 跑一遍,准确率能到 95% 以上,剩下的抽检修正就行。Tesseract-OCR 是惠普实验室起步、后来由 Google 接手维护的光学字符识别引擎,采用 Apache 2.0 协议,商用免费,支持 100 多种语言,中文简体、繁体、竖排都能覆盖。它不像某些在线 OCR 接口按调用次数收费,也不依赖网络,装完就是本地一个命令行工具加一套语言包。适合谁?需要批量处理扫描件、发票、证件、书籍数字化,又不想把数据传到第三方服务器的开发者。这份资源就是完整的安装包加中文语言包,Windows、Linux、macOS 都能落地。
2. 安装与语言包配置:把引擎和中文识别能力装进本地
2.1 各平台安装方式与版本选择
Tesseract 的安装方式在不同系统上差异不小,选错了后面调用会一直报错。Windows 用户最常见的是直接拿编译好的安装包,双击一路下一步,安装时记得勾选 Additional language data,否则中文包要单独补。Linux 下用包管理器最省事,但要注意发行版仓库里的版本可能偏旧,Ubuntu 20.04 自带的是 4.x,而 5.x 对 LSTM 引擎的识别率提升明显,尤其是中文。macOS 用 Homebrew 装最干净,语言包通过 tesseract-lang 一并拉下来。
# Ubuntu/Debian 安装主程序与中文语言包 sudo apt update sudo apt install tesseract-ocr tesseract-ocr-chi-sim tesseract-ocr-chi-tra # 查看已安装的语言包,确认 chi_sim 在列 tesseract --list-langs # macOS 通过 Homebrew 安装 brew install tesseract brew install tesseract-lang # Windows 下如果用的是安装包,默认路径通常在 # C:\Program Files\Tesseract-OCR\tesseract.exe # 语言包放在 tessdata 子目录里上面命令里tesseract-ocr-chi-sim是简体中文,chi-tra是繁体。--list-langs会输出所有可用语言代码,如果只看到 eng 和 osd,说明中文包没装进去。Windows 用户如果安装时没勾选语言数据,需要手动把下载的chi_sim.traineddata复制到Tesseract-OCR\tessdata目录下,这个目录路径可以通过tesseract --print-parameters | findstr tessdata查到。
2.2 语言包文件结构与参数含义
语言包本质是一个.traineddata文件,里面打包了 LSTM 神经网络权重、字符集映射和字典。中文简体包大约 40MB 左右,繁体类似。Tesseract 4.0 之后默认走 LSTM 引擎,识别精度比旧的 Tesseract 3 的方块特征方法高出一截,但速度稍慢。如果你处理的是非常干净的印刷体,可以尝试--oem 0切回旧引擎换速度,不过中文场景下我一般不建议,LSTM 的收益远大于那点时间差。
关键参数有几个必须知道:--psm控制页面分割模式,默认是 3(全自动分页),单行文本用 7,单字用 10,散落文本用 11。中文识别里 psm 设错是翻车重灾区,比如一张只有一行的截图用默认 3,引擎会试图找段落结构,结果把字切碎。-l指定语言,可以叠加,比如-l chi_sim+eng同时识别中英文混排。--oem选引擎模式,0 是旧引擎,1 是 LSTM,2 是两者混合,3 是自动选择。
# 识别一张中文截图,指定简体中文和单行模式 tesseract invoice.png stdout -l chi_sim --psm 7 # 中英文混排,输出到文件 tesseract mixed.png result -l chi_sim+eng --psm 6 # 查看当前版本和引擎信息 tesseract --versionstdout表示结果直接打印到终端,不写文件。--psm 6是假设一个统一文本块,适合大部分规整的文档。-l chi_sim+eng的加号表示两种语言同时加载,引擎会在识别时切换,中英混排的合同、说明书用这个组合最稳。
3. 图像预处理与识别精度调优:让引擎少背锅
3.1 用 OpenCV 做二值化与去噪
Tesseract 对输入图像质量非常敏感,直接拿手机拍的彩色照片去识别,结果往往惨不忍睹。常见做法是先用 OpenCV 做一轮预处理:灰度化、自适应二值化、去噪、纠偏。我一般会写一个预处理函数,把图像转成黑白高对比度的样子再喂给 Tesseract。下面这段代码是处理发票扫描件的常用流程。
import cv2 import numpy as np import pytesseract def preprocess_image(image_path): # 读取图像并转灰度 img = cv2.imread(image_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化,对光照不均的扫描件效果好 binary = cv2.adaptiveThreshold( gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 10 ) # 中值滤波去椒盐噪声 denoised = cv2.medianBlur(binary, 3) # 可选:放大图像,小字号文本放大后识别率提升明显 height, width = denoised.shape if width < 1000: denoised = cv2.resize(denoised, (width*2, height*2), interpolation=cv2.INTER_CUBIC) return denoised # 调用预处理并识别 processed = preprocess_image("invoice.png") text = pytesseract.image_to_string(processed, lang="chi_sim", config="--psm 6") print(text)adaptiveThreshold的 blockSize 设 31 是经验值,太小会保留噪声,太大二值化不彻底。C值 10 表示从均值减去的常数,控制阈值松紧。medianBlur的核大小 3 适合一般扫描噪声,如果噪声严重可以加到 5,但字会变糊。放大这一步对中文小字特别有用,Tesseract 在字符高度低于 20 像素时识别率断崖式下跌,放大到 30 像素以上再识别,效果立竿见影。
3.2 版面分析与 psm 模式选择
不同版面的文档要用不同的 psm。我整理了一张对照表,方便快速查。
| 场景 | psm 值 | 说明 |
|---|---|---|
| 整页文档 | 3 | 全自动分页,默认值 |
| 单块文本 | 6 | 假设一个统一文本块 |
| 单行文本 | 7 | 适合截图、标题 |
| 单个词 | 8 | 单词级别 |
| 单个字符 | 10 | 单字识别 |
| 散落文本 | 11 | 稀疏文字,无固定版式 |
| 竖排中文 | 5 | 假设垂直排列文本 |
竖排中文是个特殊场景,Tesseract 对竖排的支持有限,psm 5 是假设垂直排列,但实际效果取决于语言包。如果遇到古籍竖排,我一般会先把图像旋转 90 度变成横排再识别,比硬用 psm 5 靠谱。
# 竖排文本先旋转再识别 img = cv2.imread("vertical.png") rotated = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE) text = pytesseract.image_to_string(rotated, lang="chi_sim", config="--psm 6")旋转方向要根据实际文字方向定,顺时针还是逆时针得试一次。这个技巧在处理某些表格的竖排表头时也管用。
4. 避坑与常见问题排查:那些让我加班到凌晨的坑
4.1 中文识别乱码或输出空
现象:识别结果全是问号、方块,或者直接返回空字符串。原因通常是语言包没装对,或者-l参数写错。chi_sim写成chi_sm、chinese都会导致引擎找不到语言包,但 Tesseract 不一定报错,而是静默返回空。解决:先用tesseract --list-langs确认语言代码,再检查 tessdata 目录下有没有对应的.traineddata文件。Windows 上还要注意环境变量TESSDATA_PREFIX是否指向了正确的 tessdata 目录,指向错了引擎会去默认路径找,找不到就空转。
4.2 识别速度慢到无法接受
现象:一张 A4 扫描件识别要十几秒甚至更久。原因可能是图像分辨率过高,Tesseract 对超大图会做缩放,但缩放本身耗时。另外 LSTM 引擎在 CPU 上跑确实不快。解决:把图像长边控制在 2000 像素以内,超过的先缩小。如果批量处理,用多进程池并行,每个进程独立调用 Tesseract。我一般用concurrent.futures.ProcessPoolExecutor,4 核机器上速度能翻三倍多。
from concurrent.futures import ProcessPoolExecutor import pytesseract import cv2 def ocr_one(path): img = cv2.imread(path, cv2.IMREAD_GRAYSCALE) return pytesseract.image_to_string(img, lang="chi_sim") if __name__ == "__main__": files = ["a.png", "b.png", "c.png", "d.png"] with ProcessPoolExecutor(max_workers=4) as executor: results = list(executor.map(ocr_one, files)) for r in results: print(r[:50])max_workers设成 CPU 核心数就行,设太大反而因为进程切换开销变慢。注意 Windows 下多进程要放在if __name__ == "__main__"里,否则会无限递归创建进程。
4.3 表格线干扰导致文字被切碎
现象:表格里的文字识别出来缺胳膊少腿,或者把表格线识别成字符。原因:Tesseract 把表格线当成了文本结构的一部分。解决:预处理阶段用形态学操作去掉横竖线。思路是先检测长直线,再用修复算法把线覆盖的区域填成背景色。
import cv2 import numpy as np def remove_table_lines(binary_img): # 检测横线 horizontal = cv2.morphologyEx( binary_img, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_RECT, (40, 1)) ) # 检测竖线 vertical = cv2.morphologyEx( binary_img, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_RECT, (1, 40)) ) # 从原图减去线条 lines = cv2.add(horizontal, vertical) cleaned = cv2.subtract(binary_img, lines) return cleaned结构元素的大小 40 是经验值,取决于表格线的最小长度。如果表格线较短,调小这个值。减法操作后文字可能会有断裂,可以再做一次闭运算把笔画连上。
4.4 中英文混排时英文识别率下降
现象:纯中文识别没问题,一旦中英混排,英文单词错误率飙升。原因:-l chi_sim+eng加载两个语言模型时,引擎会在字符级别做语言判断,中文模型对英文字母的区分度不如纯英文模型。解决:如果英文占比高,把eng放在前面,-l eng+chi_sim,让引擎优先用英文模型判断。另外可以尝试--oem 1强制 LSTM,混合模型在 LSTM 下表现更稳。
4.5 训练数据与自定义字体
现象:某种特殊字体识别率极低,比如某些艺术字、手写体。原因:Tesseract 自带的语言包基于常见印刷体训练,对特殊字体泛化能力有限。解决:用tesstrain工具做微调训练,准备至少 100 张标注好的样本图,跑一遍 fine-tune。这个过程比较重,但一次训练后同类字体都能受益。如果只是少量特殊字,也可以考虑用--user-words和--user-patterns加载自定义词典,把常见错误词强制纠正。
5. 批量处理与结果后处理:把识别率再往上推几个点
批量场景下,光靠 Tesseract 裸跑不够,后处理能再拉回不少准确率。我一般会做三件事:正则清洗、词典纠错、置信度过滤。Tesseract 的image_to_data接口会返回每个词的置信度,低于阈值的词可以标记出来人工复核,而不是直接扔掉。
import pytesseract from pytesseract import Output import re def ocr_with_confidence(image_path): img = cv2.imread(image_path) data = pytesseract.image_to_data( img, lang="chi_sim", config="--psm 6", output_type=Output.DICT ) results = [] for i, text in enumerate(data["text"]): conf = int(data["conf"][i]) if conf > 60 and text.strip(): results.append((text, conf)) return results # 正则清洗:去掉多余空格和特殊符号 def clean_text(text): text = re.sub(r"\s+", "", text) text = re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9,。、:;()]", "", text) return textconf > 60是经验阈值,低于这个值的词大概率有问题。image_to_data返回的字典里还有坐标信息,可以用来做版面还原,比如按位置把词拼回表格。正则里的\u4e00-\u9fa5是中文 Unicode 范围,保留中文、英文、数字和常用标点,其他符号一律清掉,能去掉不少识别噪声。
词典纠错可以用symspellpy或者自己维护一个映射表。比如发票识别里,“壹佰”被识别成“壹百”是高频错误,直接加一条替换规则就行。我习惯把这类规则写在一个 YAML 文件里,每次识别完过一遍,维护成本低,效果立竿见影。
还有一个技巧是图像旋转校正。扫描件经常有轻微倾斜,Tesseract 对倾斜超过 5 度的文本识别率明显下降。用cv2.minAreaRect找到文本区域的最小外接矩形,算出倾斜角,再旋转校正。这个步骤在预处理阶段做,比识别后纠错省事得多。
从那以后我每次拿到新的扫描件批次,都强制先跑一遍预处理加置信度抽检,确认前 20 张的识别率达标了再批量跑全量。这个习惯帮我省下了大量返工时间。希望帮到你。
本文还有配套的精品资源,点击获取