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

基于Python与Pytesseract提取图片表格数据的多行单元格识别问题

解决Pytesseract提取多行单元格表格的列对齐问题

当表格单元格包含多行内容时,直接用image_to_string提取会导致内容跨行,无法对应到正确的列。以下是两种可行的解决方案:

方案一:利用Pytesseract布局分析数据分组列

通过image_to_data获取每个文本块的位置和行号信息,先按x坐标聚类划分列,再合并同一行的文本内容,实现多行单元格的正确归位。

from PIL import Image
import pytesseract
from collections import defaultdict

def extract_table_columns(image_path):
    # 读取图片并获取结构化OCR数据
    im = Image.open(image_path)
    data = pytesseract.image_to_data(im, output_type=pytesseract.Output.DICT)
    
    # 收集所有非空文本块的位置和内容
    text_blocks = []
    for i in range(len(data['text'])):
        text = data['text'][i].strip()
        if text:
            text_blocks.append({
                'x': data['left'][i],
                'text': text,
                'line_num': data['line_num'][i]
            })
    
    if not text_blocks:
        return {}
    
    # 按x坐标排序文本块,计算列分隔阈值
    text_blocks.sort(key=lambda x: x['x'])
    gaps = [text_blocks[i]['x'] - text_blocks[i-1]['x'] for i in range(1, len(text_blocks))]
    gap_threshold = sorted(gaps)[len(gaps)//2] if gaps else 50
    
    # 按x坐标分组列
    columns = defaultdict(list)
    current_col = [text_blocks[0]]
    for block in text_blocks[1:]:
        if block['x'] - current_col[-1]['x'] > gap_threshold:
            columns[len(columns)] = current_col
            current_col = [block]
        else:
            current_col.append(block)
    columns[len(columns)] = current_col
    
    # 合并同一行的文本(处理多行单元格)
    column_results = {}
    for col_idx, blocks in columns.items():
        line_dict = defaultdict(list)
        for block in blocks:
            line_dict[block['line_num']].append(block['text'])
        col_content = [' '.join(line) for line in line_dict.values()]
        column_results[col_idx] = col_content
    
    return column_results

# 调用示例并输出目标格式
result = extract_table_columns('verticaltable.png')
for col_content in result.values():
    print(','.join(col_content))

方案二:先分割单元格再单独OCR(准确率更高)

通过OpenCV检测表格竖线,分割出每个列的区域,再对列内内容做OCR并处理换行,从根源上避免跨行问题。

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

def split_table_cells(image_path):
    # 读取图片并预处理,突出表格竖线
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # 检测竖线轮廓
    vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5))
    detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
    contours, _ = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=lambda x: cv2.boundingRect(x)[0])
    
    # 生成列分割坐标
    col_x = [0]
    for cnt in contours:
        x, _, w, _ = cv2.boundingRect(cnt)
        col_x.append(x + w//2)
    col_x.append(img.shape[1])
    
    # 分割每一列并OCR,合并多行单元格内容
    column_contents = []
    for i in range(len(col_x)-1):
        col_img = img[:, col_x[i]:col_x[i+1]]
        text = pytesseract.image_to_string(col_img, config='--psm 6')
        lines = [line.strip() for line in text.split('\n') if line.strip()]
        
        merged = []
        current = lines[0] if lines else ''
        for line in lines[1:]:
            # 按行号特征判断是否为新行(你的表格行号以数字开头)
            if line[0].isdigit():
                merged.append(current)
                current = line
            else:
                current += ' ' + line
        merged.append(current)
        column_contents.append(merged)
    
    # 输出目标格式
    for col in column_contents:
        print(','.join(col))

# 调用示例
split_table_cells('verticaltable.png')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:45:33