杰瑞科技汇

Tesseract Python训练如何高效自定义模型?

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

Tesseract Python训练如何高效自定义模型?-图1
(图片来源网络,侵删)

这篇指南将带你从零开始,一步步完成训练。


目录

  1. 核心概念
    • 为什么需要训练?
    • Tesseract 训练的基本原理
  2. 环境准备
    • 安装 Tesseract 及其训练工具
    • 安装 Python 依赖库
  3. 训练流程详解
    • 准备图像和对应的文本文件
    • 创建 .box 文件
    • 合并 .box 文件并创建 unicharset
    • 生成 .tr 文件(特征文件)
    • 训练 shapeclustering
    • 训练 mftraining
    • 训练 cntraining
    • 合并生成 .traineddata 文件
  4. 完整 Python 脚本示例
  5. 高级技巧与注意事项
    • 使用 tesstrain.sh 脚本(强烈推荐)
    • 图像预处理的重要性
    • 增量训练
    • 常见问题

核心概念

为什么需要训练?

标准的 Tesseract 模型(如 eng.traineddata)是为通用印刷体文本(如英语)训练的,当你需要识别以下内容时,它的表现会很差:

  • 特殊字体:手写体、艺术字体、古老的字体。
  • 特定领域的字符:数学符号、化学公式、特定行业的编号。
  • 特定样式的文本:车牌号码、收据上的数字、验证码。

通过训练,你可以创建一个专门针对你特定数据集的 .traineddata 文件,从而大幅提高识别准确率。

Tesseract 训练的基本原理

Tesseract 的训练过程本质上是“机器学习”,它需要大量的“带标签的样本”来学习字符的视觉特征。

Tesseract Python训练如何高效自定义模型?-图2
(图片来源网络,侵删)
  • 样本:一系列图像文件(通常是 .tif 格式)。
  • 与每个图像文件对应的纯文本文件(.txt),其中精确地描述了图像中每个字符的位置和内容。

训练工具会读取这些样本和标签,提取字符的形状特征(如线条、曲线、笔画等),并建立这些特征与字符编码之间的映射关系,最终生成的 .traineddata 文件就是这个学习成果的固化。


环境准备

安装 Tesseract 及其训练工具

这是最关键的一步,你需要安装包含训练工具的 Tesseract 版本。

在 Windows 上:

  1. 下载安装程序:从 UB Mannheim 的 Tesseract OCR 页面 下载。
  2. 在安装过程中,务必勾选 "Additional language data (training tools)" 选项。
  3. 将 Tesseract 的安装路径(C:\Program Files\Tesseract-OCR)添加到系统的 PATH 环境变量中,这样你就可以在命令行中直接使用 tesseract 命令。

在 macOS 上 (使用 Homebrew):

Tesseract Python训练如何高效自定义模型?-图3
(图片来源网络,侵删)
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" 字体的模型。

准备图像和对应的文本文件

这是所有工作的基础。

  1. 创建图像目录:创建一个文件夹,my_training_data

  2. 准备图像:将你的训练图像(如 .png, .jpg)放入 my_training_data 目录,建议将图像统一转换为 300 DPI 的 TIFF (.tif) 格式,这是 Tesseract 训练的最佳格式,你可以使用 GIMP 或 ImageMagick 等工具批量转换。

  3. 创建文本文件:为每一个图像文件创建一个同名的 .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 文件。

  1. 重命名文件

    • unicharset -> MyCustomFont.unicharset
    • inttemp -> MyCustomFont.inttemp
    • pffmtable -> MyCustomFont.pffmtable
    • shapetable -> MyCustomFont.shapetable
    • normproto -> MyCustomFont.normproto
    • Microfeat -> MyCustomFont.Microfeat
  2. 使用 combine_tessdata 合并

    # 在 my_training_data 目录下执行
    combine_tessdata MyCustomFont.

    注意最后的 。

执行成功后,你会得到一个名为 MyCustomFont.traineddata 的文件!这就是你的自定义模型。

  1. 使用模型: 将 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 不存在),或者文件名没有正确重命名,仔细检查每一步的输出文件。
  • 识别效果差
    1. 检查你的 .box 文件是否准确,这是最常见的原因。
    2. 增加训练数据的数量和多样性。
    3. 尝试对图像进行预处理(如二值化、降噪)。
    4. 某些字体可能需要更多的训练样本才能被很好地识别。
  • 命令找不到:确保 Tesseract 的 bin 目录已经添加到系统 PATH 环境变量中。

训练 Tesseract 是一个需要耐心和反复调试的过程,从一个小而高质量的数据集开始,逐步迭代,是成功的关键,祝你训练顺利!

分享:
扫描分享到社交APP
上一篇
下一篇