You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Pytesseract从个人财务报表图片提取键值对?

用Pytesseract提取财务报表图片中的键值对方案

你现在的代码只能拿到零散的文本块和坐标,没法把键和对应的值关联起来。要解决这个问题,核心是利用坐标信息把同一行的文本归组,再根据位置或分隔符配对键值,同时可以通过图像预处理提升识别准确率。

具体调整步骤

1. 先做图像预处理

财务报表可能有背景干扰、表格线,先处理图像能让Tesseract识别更准:

  • 灰度化:把彩色图转成黑白,减少颜色干扰
  • 二值化:让文本和背景对比更强烈
  • 去噪:消除小斑点等干扰

2. 利用坐标分组文本块

Tesseract返回的image_to_data结果里有top(行顶部坐标)和left(列左侧坐标):

  • 把top值相近的文本块归为同一行(报表里键值对基本同行)
  • 同一行内按left排序,左边是键、右边是值(或者根据冒号拆分)

3. 配对键值对

要么根据文本里的冒号直接拆分,要么把同一行左侧的文本合并成键,右侧合并成值。

修改后的完整代码

import pytesseract
import cv2
import numpy as np
from PIL import Image
import pandas as pd

pytesseract.pytesseract.tesseract_cmd = r'path to tesseract' # 替换成你的Tesseract路径

# 图像预处理:提升识别准确率
def preprocess_image(image_path):
    # 读取图片
    img = cv2.imread(image_path)
    # 转灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 自适应二值化:处理光照不均的情况
    thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
    # 去除小噪声
    kernel = np.ones((1,1), np.uint8)
    cleaned_img = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    # 转为PIL格式供Tesseract使用
    return Image.fromarray(cleaned_img)

# 提取并配对键值对
def get_key_value_pairs(image_path):
    preprocessed_img = preprocess_image(image_path)
    # 提取带坐标、行号的文本数据
    extracted_data = pytesseract.image_to_data(preprocessed_img, lang='eng', output_type='data.frame')
    # 过滤空文本
    extracted_data = extracted_data.replace(r'^\s*$', np.nan, regex=True).dropna(subset=['text'])
    # 按行分组:把top值相近的归为同一行(阈值可根据报表调整,比如5像素)
    extracted_data['row_group'] = pd.cut(extracted_data['top'], bins=1000, labels=False)
    
    key_value = {}
    # 遍历每一行的文本块
    for _, row_group in extracted_data.groupby('row_group'):
        # 按左坐标排序,确保从左到右处理文本
        sorted_text = row_group.sort_values('left')
        key_parts = []
        value_parts = []
        
        for _, text_row in sorted_text.iterrows():
            text = text_row['text'].strip()
            # 优先按冒号拆分,这是最直接的方式
            if ':' in text:
                k_part, v_part = text.split(':', 1)
                key_parts.append(k_part.strip())
                value_parts.append(v_part.strip())
            else:
                # 没有冒号的话,按行的中间位置划分左右,左为键、右为值
                row_mid = sorted_text['left'].max() / 2
                if text_row['left'] < row_mid:
                    key_parts.append(text)
                else:
                    value_parts.append(text)
        
        # 合并成完整的键和值
        if key_parts and value_parts:
            final_key = ' '.join(key_parts).strip()
            final_value = ' '.join(value_parts).strip()
            key_value[final_key] = final_value
    
    return key_value

# 测试运行
result = get_key_value_pairs('image.png')
for k, v in result.items():
    print(f"{k} : {v}")

额外优化建议

  • 如果报表有明显的表格线,可以用OpenCV的霍夫线检测去除,减少干扰
  • 调整Tesseract的页面分割模式(比如添加config='--psm 6'),这个参数能告诉Tesseract文本的排版方式,6适合规整的块文本
  • 对提取到的数值型值,可以做格式转换(比如float(final_value)),方便后续计算

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:05:15