PaddleOCR实现批量pdf文件或图像的文本识别

PaddleOCR实现批量识别

本文实现pdf文件或者图片上的文本识别,并输出全部文本信息。在此基础上,可基于文本正则匹配等方法实现具体信息的提取。

输入:包含pdf、png的文件夹

输出:md、excel文件,包含每个文件的识别结果

输出示例(pdf):

Step1: 环境配置

shell 复制代码
### 环境搭建-linux-conda
conda create -n paddle_ocr python=3.9 -y
conda activate paddle_ocr

pip install numpy==1.26.4
python -m pip install paddlepaddle-gpu -i https://repo.huaweicloud.com/repository/pypi/simple/ 

pip install paddleocr==2.7.3
pip install pymupdf # 用于快速将PDF转图片
pip install pandas openpyxl tqdm
conda install cudnn=8.9.2.26 cudatoolkit=11.8 -c conda-forge -y

Step2:OCR识别文本

shell 复制代码
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CONDA_PREFIX/lib

# 加入环境中
mkdir -p $CONDA_PREFIX/etc/conda/activate.d
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CONDA_PREFIX/lib' > $CONDA_PREFIX/etc/conda/activate.d/env_vars.sh

# 执行
python batch_TextOCR.py --input_dir pdf_files --input_type pdf --output_format xlsx --use_gpu

# usage: batch_TextOCR.py [-h] --input_dir INPUT_DIR [--input_type {pdf,image,all}] [--output_format {xlsx,md}] [--use_gpu]

batch_TextOCR.py具体代码为:

python 复制代码
import os
import argparse
import fitz  # PyMuPDF
import cv2
import numpy as np
import pandas as pd
from paddleocr import PaddleOCR
from tqdm import tqdm
import logging

# 关闭 Paddle 的部分调试日志
logging.getLogger("ppocr").setLevel(logging.WARNING)

def parse_args():
    """
    解析命令行参数
    """
    parser = argparse.ArgumentParser(description="PaddleOCR 批量识别工具")

    # 1. 输入目录
    parser.add_argument('--input_dir', type=str, required=True, help='输入文件的文件夹路径')

    # 2. 输入格式 (默认为 all)
    parser.add_argument('--input_type', type=str, default='all', choices=['pdf', 'image', 'all'],
                        help='指定要处理的文件类型: pdf, image, 或 all (全部)')

    # 3. 输出格式
    parser.add_argument('--output_format', type=str, default='xlsx', choices=['xlsx', 'md'],
                        help='输出文件格式: xlsx (Excel) 或 md (Markdown)')

    # 其他配置
    parser.add_argument('--use_gpu', action='store_true', help='是否使用 GPU 加速 (默认不使用,加上此参数则使用)')

    return parser.parse_args()

def init_ocr(use_gpu):
    """
    初始化 OCR 引擎
    """
    print(f"正在初始化 OCR 引擎 (GPU: {use_gpu})...")
    # 为了兼容性,显式设置 use_gpu
    try:
        ocr = PaddleOCR(use_angle_cls=True, lang="ch", use_gpu=use_gpu, show_log=False)
    except Exception:
        # 如果旧版本不支持 show_log,尝试去掉该参数
        ocr = PaddleOCR(use_angle_cls=True, lang="ch", use_gpu=use_gpu)
    return ocr

def pdf_to_imgs(pdf_path):
    """
    将 PDF 转换为图像列表 (numpy 格式)
    """
    doc = fitz.open(pdf_path)
    images = []
    for page in doc:
        # 放大 2 倍以提高识别率
        pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
        img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, pix.n)

        if pix.n == 4:
            img_array = cv2.cvtColor(img_array, cv2.COLOR_RGBA2RGB)
        else:
            img_array = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
        images.append(img_array)
    return images

def get_file_list(input_dir, input_type):
    """
    根据参数筛选文件
    """
    if not os.path.exists(input_dir):
        raise FileNotFoundError(f"目录不存在: {input_dir}")

    all_files = os.listdir(input_dir)
    valid_files = []

    img_exts = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff')
    pdf_exts = ('.pdf',)

    for f in all_files:
        ext = os.path.splitext(f)[1].lower()

        if input_type == 'pdf' and ext in pdf_exts:
            valid_files.append(f)
        elif input_type == 'image' and ext in img_exts:
            valid_files.append(f)
        elif input_type == 'all':
            if ext in img_exts or ext in pdf_exts:
                valid_files.append(f)

    return sorted(valid_files)

def save_to_excel(data, output_path):
    """保存为 Excel"""
    df = pd.DataFrame(data)
    df.to_excel(output_path, index=False)
    print(f"Excel 文件已保存至: {output_path}")

def save_to_markdown(data, output_path):
    """保存为 Markdown"""
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(f"# OCR 识别结果报告\n\n")
        f.write(f"> 生成时间: {pd.Timestamp.now()}\n\n")

        current_file = None
        for row in data:
            filename = row['文件名']
            page = row.get('页码/图片', '')
            content = row['识别内容']

            if filename != current_file:
                if current_file: f.write("---\n\n")
                f.write(f"# 📄 {filename}\n\n")
                current_file = filename

            if page:
                f.write(f"### {page}\n\n")

            f.write(f"```text\n{content}\n```\n\n")

    print(f"Markdown 文件已保存至: {output_path}")

def main():
    args = parse_args()

    # 1. 获取文件列表
    try:
        files = get_file_list(args.input_dir, args.input_type)
    except Exception as e:
        print(f"错误: {e}")
        return

    if not files:
        print("未找到符合条件的文件。")
        return

    print(f"共找到 {len(files)} 个文件,准备处理...")

    # 2. 初始化 OCR
    ocr = init_ocr(args.use_gpu)
    results_data = []

    # 3. 开始处理
    for file_name in tqdm(files, desc="处理进度"):
        file_path = os.path.join(args.input_dir, file_name)
        ext = os.path.splitext(file_name)[1].lower()

        try:
            # 准备待处理的图片列表
            process_queue = [] # [(页码标识, 图片对象)]

            if ext == '.pdf':
                imgs = pdf_to_imgs(file_path)
                for idx, img in enumerate(imgs):
                    process_queue.append((f"第 {idx+1} 页", img))
            else:
                # 图像文件
                img = cv2.imread(file_path)
                if img is not None:
                    process_queue.append(("全图", img))

            # 遍历队列进行 OCR
            for label, img_obj in process_queue:
                result = ocr.ocr(img_obj, cls=True)

                content = ""
                if result and result[0]:
                    text_lines = [line[1][0] for line in result[0]]
                    content = "\n".join(text_lines)

                results_data.append({
                    "文件名": file_name,
                    "页码/图片": label,
                    "识别内容": content
                })

        except Exception as e:
            print(f"\n处理文件 {file_name} 失败: {e}")

    # 4. 导出结果
    if not results_data:
        print("没有识别到任何结果。")
        return

    # 生成输出文件名 (基于输入目录名 + 时间戳)
    dir_name = os.path.basename(os.path.normpath(args.input_dir))
    timestamp = pd.Timestamp.now().strftime("%Y%m%d_%H%M")
    output_filename = f"{dir_name}_识别结果_{timestamp}.{args.output_format}"
    output_path = os.path.join(args.input_dir, output_filename) # 默认保存在输入目录下

    if args.output_format == 'xlsx':
        save_to_excel(results_data, output_path)
    else:
        save_to_markdown(results_data, output_path)

if __name__ == "__main__":
    main()
相关推荐
开开心心_Every2 小时前
视频无损压缩工具:大幅减小体积并保持画质
游戏·微信·pdf·excel·音视频·语音识别·tornado
进阶的猿猴3 小时前
java中实现markdown转为pdf
java·pdf·markdown
开开心心_Every3 小时前
安卓语音转文字工具:免费支持实时转换视频
python·游戏·微信·django·pdf·excel·语音识别
解压专家6664 小时前
Kred PDF阅读进阶:不止能打开,更能高效用
pdf
神舟之光4 小时前
调用阿里云的通义千问大模型实现将pdf文件解析为excel表格(java实现)
pdf
s09071364 小时前
【完美解决】Win11安装Adobe Reader后无法预览PDF文件(保留Adobe打开,恢复微软预览)
microsoft·pdf·adobe reader·pdf预览失效
miaobinfei4 小时前
pdf转word,图片文字转word(使用OCR工具)
pdf·ocr·word
一城烟雨_5 小时前
vue3实现将HTML导出为pdf,HTML转换为文件流
vue.js·pdf
乐迁~1 天前
如何使用html2canvas和jsPDF库来解决PDF导出时分页内容截断问题(下--表格行截断处理)
pdf·js