Tesseract 的训练过程相对复杂,因为它是一个命令行工具,而不是一个纯 Python 库,我们可以使用 Python 脚本来自动化数据准备、调用训练工具以及评估结果,从而大大简化整个流程。

这篇指南将带你从零开始,一步步完成训练。
目录
- 核心概念
- 为什么需要训练?
- Tesseract 训练的基本原理
- 环境准备
- 安装 Tesseract 及其训练工具
- 安装 Python 依赖库
- 训练流程详解
- 准备图像和对应的文本文件
- 创建
.box文件 - 合并
.box文件并创建unicharset - 生成
.tr文件(特征文件) - 训练
shapeclustering - 训练
mftraining - 训练
cntraining - 合并生成
.traineddata文件
- 完整 Python 脚本示例
- 高级技巧与注意事项
- 使用
tesstrain.sh脚本(强烈推荐) - 图像预处理的重要性
- 增量训练
- 常见问题
- 使用
核心概念
为什么需要训练?
标准的 Tesseract 模型(如 eng.traineddata)是为通用印刷体文本(如英语)训练的,当你需要识别以下内容时,它的表现会很差:
- 特殊字体:手写体、艺术字体、古老的字体。
- 特定领域的字符:数学符号、化学公式、特定行业的编号。
- 特定样式的文本:车牌号码、收据上的数字、验证码。
通过训练,你可以创建一个专门针对你特定数据集的 .traineddata 文件,从而大幅提高识别准确率。
Tesseract 训练的基本原理
Tesseract 的训练过程本质上是“机器学习”,它需要大量的“带标签的样本”来学习字符的视觉特征。

- 样本:一系列图像文件(通常是
.tif格式)。 - 与每个图像文件对应的纯文本文件(
.txt),其中精确地描述了图像中每个字符的位置和内容。
训练工具会读取这些样本和标签,提取字符的形状特征(如线条、曲线、笔画等),并建立这些特征与字符编码之间的映射关系,最终生成的 .traineddata 文件就是这个学习成果的固化。
环境准备
安装 Tesseract 及其训练工具
这是最关键的一步,你需要安装包含训练工具的 Tesseract 版本。
在 Windows 上:
- 下载安装程序:从 UB Mannheim 的 Tesseract OCR 页面 下载。
- 在安装过程中,务必勾选 "Additional language data (training tools)" 选项。
- 将 Tesseract 的安装路径(
C:\Program Files\Tesseract-OCR)添加到系统的PATH环境变量中,这样你就可以在命令行中直接使用tesseract命令。
在 macOS 上 (使用 Homebrew):

brew install tesseract tesseract-lang
这会自动安装训练工具。
在 Linux (Ubuntu/Debian) 上:
sudo apt update sudo apt install tesseract-ocr tesseract-ocr-dev libtesseract-dev
训练工具(如 unicharset_extractor, shapeclustering 等)通常会作为 tesseract-ocr-dev 包的一部分被安装。
验证安装: 打开你的终端或命令提示符,输入以下命令,如果看到版本信息,说明安装成功。
tesseract --version
安装 Python 依赖库
我们将使用 Python 来管理文件和调用训练命令,主要用到 Pillow (用于图像处理) 和 pytesseract (用于调用 Tesseract API)。
pip install pillow pytesseract
训练流程详解
假设我们要训练一个能识别 "MyCustomFont" 字体的模型。
准备图像和对应的文本文件
这是所有工作的基础。
-
创建图像目录:创建一个文件夹,
my_training_data。 -
准备图像:将你的训练图像(如
.png,.jpg)放入my_training_data目录,建议将图像统一转换为 300 DPI 的 TIFF (.tif) 格式,这是 Tesseract 训练的最佳格式,你可以使用 GIMP 或 ImageMagick 等工具批量转换。 -
创建文本文件:为每一个图像文件创建一个同名的
.txt文件,如果你有image1.tif,就必须有一个image1.txt。image1.txt的内容格式非常重要: 每行代表一个字符,格式为:字符 x1 y1 x2 y2 page_id字符:识别出的单个字符。x1 y1:字符左下角的坐标。x2 y2:字符右上角的坐标。page_id:通常是0。
示例: 假设
image1.tif中有 "Hello" 几个字,image1.txt的内容可能是:H 10 50 20 60 0 e 21 50 30 60 0 l 31 50 40 60 0 l 41 50 50 60 0 o 51 50 60 60 0
创建 .box 文件
.box 文件是 Tesseract 使用的中间格式,它和 .txt 文件内容类似,但扩展名不同,幸运的是,Tesseract 可以自动为我们生成它。
在命令行中,进入你的数据目录 (my_training_data),然后运行:
tesseract image1.tif image1 batch.nochop makebox
image1.tif:你的输入图像。image1:输出文件的前缀。batch.nochop makebox:告诉 Tesseract 为每个字符创建一个.box文件。
执行后,你会得到一个 image1.box 文件,你需要手动检查和修正这个文件!Tesseract 的初始识别可能不完美,你需要用文本编辑器打开 .box 文件,修正错误的字符和坐标。
修正 .box 文件后, 你需要将它们合并成一个大的 .box 文件。
# 在 my_training_data 目录下执行 # 将所有 .box 文件合并成一个名为 all.font.exp0.box 的文件 cat *.box > all.font.exp0.box
合并 .box 文件并创建 unicharset
这一步,我们从所有 .box 文件中提取出所有不重复的字符集合(字符集)。
# 在 my_training_data 目录下执行 unicharset_extractor all.font.exp0.box
这会生成一个 unicharset 文件,里面包含了你的数据集中所有唯一的字符。
生成 .tr 文件(特征文件)
我们使用 Tesseract 的特征提取工具,从图像和对应的 .box 文件中生成 .tr 文件。
# 在 my_training_data 目录下执行 tesseract image1.tif image1 nobatch box.train tesseract image2.tif image2 nobatch box.train # ... 对所有图像执行此操作 # 将所有 .tr 文件合并 cat *.tr > fontfile.tr
nobatch box.train:告诉 Tesseract 为每个图像生成单独的特征文件。
训练 shapeclustering
这个步骤分析字符的形状,将形状相似的字符归为一类。
# 在 my_training_data 目录下执行 shapeclustering -F font_properties -U unicharset -O unicharset fontfile.tr
-F font_properties:指定一个字体属性文件(见下方说明)。-U unicharset:指定我们之前生成的unicharset文件。-O unicharset:输出更新后的unicharset文件。
font_properties 文件:你需要手动创建这个文件,它定义了每种字体的属性。
格式:字体名 斜体_粗体_其他 其他属性...
如果你的字体都是常规非斜体体,文件内容就是:
MyCustomFont 0 0 0 0
文件名必须是 font_properties。
训练 mftraining
这个步骤为每个字符生成“特征规范”(FSpecs)。
# 在 my_training_data 目录下执行 mftraining -F font_properties -U unicharset -O unicharset fontfile.tr
执行后,你会得到几个新文件:
inttemp:字符特征规范。pffmtable:字体特征规范。shapetable:形状聚类信息。
训练 cntraining
这个步骤为每个字符生成“名称规范”(NSpecs)。
# 在 my_training_data 目录下执行 cntraining fontfile.tr
执行后,你会得到:
normproto:字符名称规范。Microfeat:微特征文件。
合并生成 .traineddata 文件
这是最后一步,我们将所有生成的文件打包成一个 Tesseract 可以使用的 .traineddata 文件。
-
重命名文件:
unicharset->MyCustomFont.unicharsetinttemp->MyCustomFont.inttemppffmtable->MyCustomFont.pffmtableshapetable->MyCustomFont.shapetablenormproto->MyCustomFont.normprotoMicrofeat->MyCustomFont.Microfeat
-
使用
combine_tessdata合并:# 在 my_training_data 目录下执行 combine_tessdata MyCustomFont.
注意最后的 。
执行成功后,你会得到一个名为 MyCustomFont.traineddata 的文件!这就是你的自定义模型。
-
使用模型: 将
MyCustomFont.traineddata文件放到 Tesseract 的tessdata目录下(C:\Program Files\Tesseract-OCR\tessdata),然后你就可以在 Python 中使用它了:import pytesseract from PIL import Image # 指定你的自定义数据路径 custom_data_path = r'C:\Program Files\Tesseract-OCR\tessdata' pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' image = Image.open('my_test_image.png') # 使用 lang 参数指定你的自定义语言名(文件名去掉 .traineddata) text = pytesseract.image_to_string(image, lang='MyCustomFont') print(text)
完整 Python 脚本示例
将上面的命令行步骤封装成一个 Python 脚本,可以自动化整个流程。
import os
import subprocess
import glob
from PIL import Image
def convert_to_tif(image_path, output_dir):
"""将图像转换为300 DPI的TIFF格式"""
img = Image.open(image_path)
# 确保是RGB模式,因为Tesseract处理TIFF时通常是RGB
if img.mode != 'RGB':
img = img.convert('RGB')
base_name = os.path.splitext(os.path.basename(image_path))[0]
tif_path = os.path.join(output_dir, f"{base_name}.tif")
img.save(tif_path, dpi=(300, 300))
return tif_path
def run_command(command, cwd=None):
"""执行shell命令并打印输出"""
print(f"Executing: {' '.join(command)}")
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
stdout, stderr = process.communicate()
if stdout:
print("Output:", stdout.decode())
if stderr:
print("Error:", stderr.decode())
if process.returncode != 0:
raise Exception(f"Command failed with return code {process.returncode}")
def train_tesseract(data_dir, lang_name="MyCustomFont"):
"""
自动化Tesseract训练流程
:param data_dir: 包含原始图像和对应.txt文件的目录
:param lang_name: 自定义语言/字体名称
"""
print("--- Starting Tesseract Training ---")
# 1. 准备工作目录和文件
training_dir = os.path.abspath(data_dir)
os.chdir(training_dir)
# 创建font_properties文件
with open("font_properties", "w") as f:
f.write(f"{lang_name} 0 0 0 0\n")
print("Created font_properties file.")
# 2. 转换所有图像为TIFF格式并生成初始.box文件
tif_files = []
for ext in ['*.png', '*.jpg', '*.jpeg', '*.tif', '*.tiff']:
for img_path in glob.glob(os.path.join(training_dir, ext)):
tif_path = convert_to_tif(img_path, training_dir)
tif_files.append(tif_path)
base_name = os.path.splitext(os.path.basename(tif_path))[0]
# 生成初始box文件
run_command(['tesseract', tif_path, base_name, 'batch.nochop', 'makebox'])
if not tif_files:
raise FileNotFoundError("No image files found in the training directory.")
# 3. 合并所有.box文件
box_files = glob.glob("*.box")
with open("all.font.exp0.box", "w") as outfile:
for fname in box_files:
with open(fname) as infile:
outfile.write(infile.read())
print("Merged all .box files into all.font.exp0.box.")
print("!!! IMPORTANT: Please manually check and edit 'all.font.exp0.box' for accuracy before continuing. !!!")
input("Press Enter after you have finished editing the .box file...")
# 4. 提取字符集
run_command(['unicharset_extractor', 'all.font.exp0.box'])
print("Extracted unicharset.")
# 5. 生成特征文件
tr_files = []
for tif_path in tif_files:
base_name = os.path.splitext(os.path.basename(tif_path))[0]
run_command(['tesseract', tif_path, base_name, 'nobatch', 'box.train'])
tr_files.append(f"{base_name}.tr")
with open("fontfile.tr", "w") as outfile:
for fname in tr_files:
with open(fname) as infile:
outfile.write(infile.read())
print("Generated and merged .tr files.")
# 6. 形状聚类
run_command(['shapeclustering', '-F', 'font_properties', '-U', 'unicharset', '-O', 'unicharset', 'fontfile.tr'])
print("Shape clustering complete.")
# 7. 训练mftraining
run_command(['mftraining', '-F', 'font_properties', '-U', 'unicharset', '-O', 'unicharset', 'fontfile.tr'])
print("mftraining complete.")
# 8. 训练cntraining
run_command(['cntraining', 'fontfile.tr'])
print("cntraining complete.")
# 9. 重命名和合并文件
rename_map = {
'unicharset': f'{lang_name}.unicharset',
'inttemp': f'{lang_name}.inttemp',
'pffmtable': f'{lang_name}.pffmtable',
'shapetable': f'{lang_name}.shapetable',
'normproto': f'{lang_name}.normproto',
'Microfeat': f'{lang_name}.Microfeat',
}
for old_name, new_name in rename_map.items():
if os.path.exists(old_name):
os.rename(old_name, new_name)
run_command(['combine_tessdata', f'{lang_name}..'])
print(f"\n--- Training Successful! ---")
print(f"Generated model: {lang_name}.traineddata")
print(f"Please move this file to your Tesseract tessdata directory.")
if __name__ == '__main__':
# !!! 替换成你的训练数据目录 !!!
# 该目录下应包含你的图像文件 (image1.png, image2.jpg等)
# 和对应的文本文件 (image1.txt, image2.txt等)
MY_TRAINING_DATA_DIR = './my_training_data'
if not os.path.isdir(MY_TRAINING_DATA_DIR):
print(f"Error: Training directory not found at '{MY_TRAINING_DATA_DIR}'")
print("Please create it and add your images and .txt files.")
else:
train_tesseract(MY_TRAINING_DATA_DIR, lang_name="MyCustomFont")
高级技巧与注意事项
使用 tesstrain.sh 脚本(强烈推荐)
Google 官方提供了一个名为 tesstrain.sh 的 Bash 脚本,它极大地简化了训练流程,并处理了许多边界情况,如果你在 Linux 或 macOS (通过 WSL on Windows) 上工作,强烈建议使用它。
它通常位于 Tesseract 源代码的 tesstrain 目录下,你可以从 Tesseract GitHub 仓库 克隆下来使用。
图像预处理的重要性
“垃圾进,垃圾出”,高质量的训练数据是成功的关键。
- 分辨率:确保所有图像至少为 300 DPI。
- 清晰度:图像应清晰,无模糊、无重影。
- 对比度:确保文字与背景有足够的对比度。
- 布局:字符之间最好有清晰的分隔,如果字符粘连严重,Tesseract 生成
.box文件时会出错。 - 多样性:训练数据应覆盖你希望识别的所有字符、大小写、标点符号,并包含一些轻微的变形和噪声。
增量训练
如果你已经有了一个基础模型(eng.traineddata),并且只想让它学习一些新的字符(比如几个特殊符号),你可以进行增量训练,而不需要从头开始,这通常涉及到修改现有模型的 unicharset 和其他相关文件,然后用新的数据重新运行部分训练步骤,这比完全重新训练要快得多。
常见问题
combine_tessdata报错:通常是因为缺少某个中间文件(如unicharset不存在),或者文件名没有正确重命名,仔细检查每一步的输出文件。- 识别效果差:
- 检查你的
.box文件是否准确,这是最常见的原因。 - 增加训练数据的数量和多样性。
- 尝试对图像进行预处理(如二值化、降噪)。
- 某些字体可能需要更多的训练样本才能被很好地识别。
- 检查你的
- 命令找不到:确保 Tesseract 的
bin目录已经添加到系统PATH环境变量中。
训练 Tesseract 是一个需要耐心和反复调试的过程,从一个小而高质量的数据集开始,逐步迭代,是成功的关键,祝你训练顺利!
