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

如何提升图像嵌入型PDF文件的表格数据提取准确率?

提升图像型PDF表格数据提取准确率的解决方案

你当前用pdf2image+pytesseract实现了基础的图像PDF文本提取,但针对表格场景,需要从图像预处理、OCR参数调优、表格结构解析这几个维度优化,具体方案如下:


你的现有代码

from pdf2image import convert_from_path
import pytesseract
import csv
from pytesseract import Output

# 将PDF转换为图片
images = convert_from_path('input.pdf')

# 创建CSV文件
csv_file_path = 'output.csv'
with open(csv_file_path, 'w', newline='', encoding='utf-8') as csv_file:
  csv_writer = csv.writer(csv_file)

  # 遍历每张图片
  for i, image in enumerate(images):
    # 保存图片
    image_path = f'page_{i}.png'
    image.save(image_path, 'PNG')

    # 使用pytesseract从图片中提取文本
    text = pytesseract.image_to_string(image_path, output_type=Output.STRING)

    # 打印提取的文本
    print(text)

    # 将文本写入CSV文件
    csv_writer.writerow([text])

print(f'CSV文件已生成,路径:{csv_file_path}')

一、图像预处理:消除干扰,提升OCR识别基础

图像质量是OCR准确率的核心,先对PDF转换后的图片做预处理:

  • 灰度转换+二值化:去除颜色干扰,强化文本与背景的对比度

    import cv2
    import numpy as np
    
    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)
        # 保存预处理后的图片
        processed_path = f'processed_{image_path}'
        cv2.imwrite(processed_path, thresh)
        return processed_path
    

    在你的代码中,替换image_path为预处理后的路径再进行OCR。

  • 降噪处理:针对有斑点、划痕的图片,用高斯模糊或中值滤波去除噪点

    # 在预处理函数中添加:
    blur = cv2.GaussianBlur(gray, (3,3), 0)
    # 或者中值滤波(适合椒盐噪点)
    blur = cv2.medianBlur(gray, 3)
    
  • 倾斜校正:如果表格存在倾斜,先检测并校正

    def correct_skew(image):
        coords = np.column_stack(np.where(image > 0))
        angle = cv2.minAreaRect(coords)[-1]
        if angle < -45:
            angle = -(90 + angle)
        else:
            angle = -angle
        (h, w) = image.shape[:2]
        center = (w // 2, h // 2)
        M = cv2.getRotationMatrix2D(center, angle, 1.0)
        rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
        return rotated
    

    把这个步骤加入预处理流程,确保表格水平对齐。

二、Tesseract参数调优:针对表格场景优化识别逻辑

默认的Tesseract参数更适合普通文本,针对表格需要调整:

  • 指定语言:如果是中文表格,必须指定语言包,避免乱码

    text = pytesseract.image_to_string(processed_path, lang='chi_sim+eng', output_type=Output.STRING)
    

    注意要提前安装对应语言的Tesseract语言包。

  • 调整PSM(页面分割模式):表格是结构化文本,推荐使用PSM 6(假设页面是一个统一的文本块)或PSM 11(稀疏文本,适合有空白单元格的表格)

    text = pytesseract.image_to_string(processed_path, lang='chi_sim+eng', 
                                       config='--psm 6 --oem 3', output_type=Output.STRING)
    

    --oem 3表示使用默认的OCR引擎模式。

  • 获取结构化坐标数据:不直接提取纯文本,而是获取每个字符的位置信息,方便后续按表格行列拆分

    # 输出包含坐标的字典
    data = pytesseract.image_to_data(processed_path, lang='chi_sim+eng', output_type=Output.DICT)
    # 可以遍历data中的'left', 'top', 'width', 'height', 'text'字段,按行分组
    

三、表格结构解析:按行列拆分数据,生成规范CSV

纯文本提取无法区分表格的行列,需要基于坐标或线条检测来拆分:

  • 基于坐标分组行:利用Tesseract返回的top坐标,将垂直距离相近的字符归为同一行,再按left坐标排序得到列数据

    def parse_table_from_data(data):
        rows = []
        current_row = []
        prev_top = -100  # 初始阈值
        # 遍历每个识别结果
        for i in range(len(data['text'])):
            text = data['text'][i].strip()
            if not text:
                continue
            top = data['top'][i]
            # 当垂直距离超过阈值时,新建一行
            if abs(top - prev_top) > 10:
                if current_row:
                    rows.append(current_row)
                current_row = [text]
                prev_top = top
            else:
                current_row.append(text)
        if current_row:
            rows.append(current_row)
        return rows
    

    然后把rows直接写入CSV,就能得到行列分明的表格数据。

  • OpenCV检测表格线条:如果表格有明显边框,先检测水平线和垂直线,分割出每个单元格,再对单个单元格做OCR,准确率更高

    def detect_table_cells(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)
        # 检测水平线
        horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1))
        detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
        # 检测垂直线
        vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,40))
        detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
        # 合并线条
        combined = cv2.addWeighted(detect_horizontal, 0.5, detect_vertical, 0.5, 0.0)
        # 找到轮廓
        contours, _ = cv2.findContours(combined, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # 按坐标排序轮廓(先按行,再按列)
        contours = sorted(contours, key=lambda c: (cv2.boundingRect(c)[1], cv2.boundingRect(c)[0]))
        cells = []
        for cnt in contours:
            x, y, w, h = cv2.boundingRect(cnt)
            if w > 20 and h > 20:  # 过滤小轮廓
                cell_img = img[y:y+h, x:x+w]
                # 对单元格做OCR
                cell_text = pytesseract.image_to_string(cell_img, lang='chi_sim+eng').strip()
                cells.append(cell_text)
        # 按表格行列数拆分cells(需要提前知道列数,或者动态计算)
        return cells
    

四、进阶工具组合:针对复杂表格的替代方案

如果上述优化仍不够,可尝试专门的表格OCR工具:

  • PaddleOCR表格识别:百度开源的OCR工具,内置表格结构解析模型,能直接输出行列结构化数据
  • EasyOCR:轻量开源OCR,支持多语言,配合坐标处理也能实现表格提取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:20:23