利用PaddleOCR进行图片的跨页表格提取与合并(PDF扫描版)

利用PaddleOCR进行扫描版PDF的跨页表格提取与合并

  • 前言
    • 1.环境准备
    • 2.文件路径与阈值设置
    • 3.定义辅助函数
    • 4.处理PDF文件
    • 5.总结

前言

在处理PDF文件中的表格时,常常会遇到表格跨页的情况。并且一些PDF文件为扫描版。这种情况下,如果要将跨页的表格合并为一个完整的表格,手动操作不仅繁琐且容易出错。因此,本文将介绍如何利用PaddleOCR和Python代码,自动化地检测并合并这些跨页表格。

1.环境准备

首先,我们需要安装以下库:

  • pandas:数据处理
  • paddleocr:OCR识别表格结构
  • pdf2image:将PDF页面转换为图像
  • beautifulsoup4:解析HTML
  • numpy:数组处理

安装命令如下:

pip install pandas paddleocr pdf2image beautifulsoup4 numpy

引入所需的库并设置一些警告和日志配置,以确保代码执行过程中不会被不必要的信息干扰:

import pandas as pd
from paddleocr import PPStructure, save_structure_res
from pdf2image import convert_from_path
from bs4 import BeautifulSoup
import warnings
import numpy as np
import logging
import os

warnings.filterwarnings("ignore")
logging.disable(logging.DEBUG)
logging.disable(logging.WARNING)

2.文件路径与阈值设置

定义PDF文件的路径和一些参数阈值,用于判断表格是否跨页:

path = 'E:/Jobcontent/data/测试/'
output_folder = "E:/table/ex/"
topthreshold = 0.2
dthreshold = 0.8

table_engine = PPStructure(show_log=True)

3.定义辅助函数

这些辅助函数用于提取PDF页面中的表格信息,并判断表格是否跨页。

  • top_bottom_table_info:获取页面中最上方表格的列数和坐标。
  • find_bottom_table_info:获取页面中最下方表格的列数和坐标。
  • is_continuation:判断表格是否跨页。
def top_bottom_table_info(table_result):
    top_table = None
    min_y = 0
    for table in table_result:
        if table['type'] == 'table':
            bbox = table['bbox']
            current_bottom_y = bbox[1]
            if top_table is None or current_bottom_y < min_y:
                top_table = table
                min_y = current_bottom_y

    if top_table is not None:
        soup = BeautifulSoup(top_table['res']['html'], 'html.parser')
        last_row = soup.find_all('tr')[-1]
        columns = last_row.find_all('td')
        top_row_columns = len(columns)
        top_xy = top_table['bbox']
        return top_row_columns, top_xy
    else:
        return None

def find_bottom_table_info(table_result):
    bottom_table = None
    bottom_y = 0
    for table in table_result:
        if table['type'] == 'table':
            bbox = table['bbox']
            current_bottom_y = bbox[3]
            if bottom_table is None or current_bottom_y > bottom_y:
                bottom_table = table
                bottom_y = current_bottom_y

    if bottom_table is not None:
        soup = BeautifulSoup(bottom_table['res']['html'], 'html.parser')
        last_row = soup.find_all('tr')[0]
        columns = last_row.find_all('td')
        last_row_columns = len(columns)
        bottom_xy = bottom_table['bbox']
        return last_row_columns, bottom_xy
    else:
        return None

def is_continuation(top_row_columns, last_row_columns, bottom_xy, top_xy, page_height, dthreshold=0.8, topthreshold=0.2):
    if top_row_columns != last_row_columns:
        return False
    is_last_table_at_bottom = bottom_xy[3] > dthreshold * page_height
    is_first_table_at_top = top_xy[1] < topthreshold * page_height
    return is_last_table_at_bottom and is_first_table_at_top

4.处理PDF文件

读取PDF文件并提取每页的表格信息。对于跨页的表格,提取其列数和坐标,并将结果合并。

  1. 获取PDF文件列表:获取指定路径下所有以“.pdf”结尾的文件。
  2. 逐个处理PDF文件:对于每个PDF文件,初始化一个列表来存储跨页表格信息。
  3. 将PDF页面转换为图像:将PDF文件的每一页转换为图像,并逐页处理。
  4. 提取表格信息:使用table_engine函数从每个页面图像中提取表格信息,并保存结构化结果。
  5. 检测跨页表格:检查当前页的最后一行和下一页的第一行的列数是否相同,如果相同,则记录跨页表格的信息。
  6. 合并跨页表格:对于检测到的跨页表格,读取跨页的两部分表格,合并后保存为CSV文件。
  7. 完成提取:在处理完所有PDF文件后,打印“表格提取完成”的消息。
pdf_files = [f for f in os.listdir(path) if f.endswith('.pdf')]
print(pdf_files)

for pdf_file in pdf_files:
    cross_page_tables = []
    pdf_path = os.path.join(path, pdf_file)
    images = convert_from_path(pdf_path, dpi=200)
    print('正在提取表格,请耐心等待...')
    for page_number, image in enumerate(images):
        table_result = table_engine(np.array(image))
        save_structure_res(table_result, output_folder, f'{page_number+1}')

        _, page_height = image.size
        last_row_columns, bottom_xy = find_bottom_table_info(table_result)
        if page_number+1 < len(images):
            table_result_end = table_engine(np.array(images[page_number+1]))
            top_row_columns, top_xy = top_bottom_table_info(table_result_end)

            if is_continuation(top_row_columns, last_row_columns, bottom_xy, top_xy, page_height):
                cross_page_tables.append((bottom_xy, top_xy, page_number+1, page_number+2))
                print(f"{pdf_file} 的表格在第 {page_number+1} 页和第 {page_number+2} 页之间跨页,并且最后一行和下一页的第一行列数相同")

    if cross_page_tables:
        for (bottom_xy, top_xy, start_page, end_page) in cross_page_tables:
            output_folder_s = output_folder + f'{start_page}/'
            output_folder_t = output_folder + f'{end_page}/'
            file_s = f'{bottom_xy}'+'_0'+'.xlsx'
            file_t = f'{top_xy}'+'_0'+'.xlsx'
            s_path = os.path.join(output_folder_s, file_s)
            e_path = os.path.join(output_folder_t, file_t)
            table_result_start =pd.read_excel(s_path, header=None)
            table_result_end = pd.read_excel(e_path, header=None)
            merged_table = pd.concat([table_result_start, table_result_end], ignore_index=True)
            output_path = os.path.join(output_folder, f'{pdf_file}_merged_{start_page}_{end_page}.csv')
            merged_table.to_csv(output_path, index=False)

print('表格提取完成')

5.总结

通过上述代码,可以实现对扫描版PDF文件中跨页表格的检测与合并,并将结果保存为CSV文件。该方法对提升PDF表格处理的自动化程度和效率具有重要意义。

上一篇:安装WindowsTerminal并设置默认以管理员身份运行启动终端