You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Pytesseract输出文件格式匹配问题求助:提取与原图行列排布一致的文本

解决Pytesseract提取文本时的格式还原与公式识别问题

我明白你想要的是和原图完全一致的文本排版,包括行列对齐、特殊符号和数学公式的准确识别——这确实是OCR格式还原的痛点,你的现有代码在文本提取上没问题,但格式还原的逻辑有几个可以优化的地方,我来一步步帮你解决:

一、现有代码的格式问题根源

  1. PSM模式选择不当:你用了--psm 1(自动分页),这个模式适合多页文档,但对于单张需要精准位置的图片,它会把文本拆分成过多块,导致换行和空格计算混乱。
  2. 平均字符宽度的误差:不同字符(比如wi)的实际宽度差异很大,用平均宽度计算空格数必然会导致对齐偏差。
  3. 未针对数学公式优化配置:默认的Tesseract配置对数学符号、公式的识别支持不足,需要启用特定参数。

二、改进后的解决方案

1. 调整Tesseract核心配置

首先修改custom_config,优化PSM模式和公式识别:

# 推荐配置:PSM 6(假设文本是单一均匀块,适合精准位置识别)+ OEM 3(混合引擎,提升公式识别)
# 添加 preserve_interword_spaces=2 增强空格保留,同时启用数学相关配置
custom_config = r'-c preserve_interword_spaces=2 --oem 3 --psm 6 -l eng'
  • --psm 6:强制Tesseract将整个图像视为单一文本块,减少不必要的块拆分,更利于位置计算。
  • preserve_interword_spaces=2:比1更严格地保留原始空格布局。
  • 如果你的Tesseract版本是5+,可以尝试添加-c textonly_pdf=0提升复杂符号识别,或者安装专门的数学语言包(比如equ.traineddata)并在-l参数中加入equ-l eng+equ)。

2. 精准还原排版的代码优化

放弃平均字符宽度的方法,直接基于每个文本块的实际坐标topleft)来计算换行和空格:

import pytesseract
from pytesseract import Output
from PIL import Image
import pandas as pd

pytesseract.pytesseract.tesseract_cmd = r'/usr/bin/tesseract'
# 优化后的配置
custom_config = r'-c preserve_interword_spaces=2 --oem 3 --psm 6 -l eng'

# 获取带位置信息的识别结果
d = pytesseract.image_to_data(Image.open(r'_0.png'), config=custom_config, output_type=Output.DICT)
df = pd.DataFrame(d)

# 过滤无效文本(置信度-1、空文本、纯空格)
df_clean = df[(df['conf'] != '-1') & (df['text'].str.strip() != '')].copy()

# 计算每行的基准top(用行的平均top来分组,避免因字符上下偏移导致的分组错误)
df_clean['line_top'] = df_clean.groupby('line_num')['top'].transform('mean')

# 按行分组,并按left坐标排序文本块
grouped = df_clean.groupby('line_num').apply(lambda x: x.sort_values('left')).reset_index(drop=True)

# 构建最终文本
final_text = ""
prev_line_top = None
prev_left = 0

for idx, row in grouped.iterrows():
    # 处理换行:当前行的top与上一行差异超过行高的50%时,换行
    if prev_line_top is not None and abs(row['line_top'] - prev_line_top) > row['height'] * 0.5:
        final_text += "\n"
        prev_left = 0
    
    # 计算需要添加的空格数:基于当前文本块的left与上一个文本块的right的差值
    # 用字符宽度的1/4作为一个空格的宽度基准(可根据实际情况调整)
    space_width = row['width'] / len(row['text'])
    if prev_left > 0:
        space_needed = int((row['left'] - prev_left) / space_width)
        if space_needed > 0:
            final_text += " " * space_needed
    
    # 添加当前文本
    final_text += row['text']
    
    # 更新上一个位置信息
    prev_line_top = row['line_top']
    prev_left = row['left'] + row['width']

# 打印或保存结果
print(final_text)
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write(final_text)

3. 数学公式识别的额外建议

如果你的图片中有复杂数学公式,仅靠Tesseract可能不够完美,可以尝试:

  • 升级到Tesseract 5.x版本:它对数学符号和公式的识别能力比4.x有显著提升。
  • 安装equ.traineddata数学语言包:将其放入Tesseract的tessdata目录,然后修改-l eng+equ来启用数学识别模式。
  • 对于极复杂的公式,可以考虑结合专门的数学OCR工具(比如Mathpix),但这需要额外的API调用。

三、关键优化点总结

  • --psm 6替代--psm 1,减少块拆分带来的格式混乱。
  • 基于实际坐标计算空格和换行,避免平均宽度的误差。
  • 启用更严格的空格保留和混合引擎,提升格式还原和特殊符号识别。

内容的提问来源于stack exchange,提问作者SON GOKU

火山引擎 最新活动