基于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
相关产品推荐
相关产品推荐

