# PDF处理模块重构说明 ## 📦 模块结构 PDF处理功能已重构为4个模块,便于维护和理解: ``` ocr_utils/ ├── pdf_utils.py # 主入口 - 高级API和向后兼容包装 ├── pdf_coordinate_transform.py # 坐标转换功能 ├── pdf_text_extraction.py # 文本提取功能 ├── pdf_image_rendering.py # 图像渲染功能 └── pdf_README.md # 本文档 ``` ## 🔧 各模块功能 ### 1. pdf_utils.py (主入口,~400行) **作用**: 高级API和统一入口,保持向后兼容性 **主要类**: `PDFUtils` **核心功能**: - `load_and_classify_document()`: 加载文档(PDF/图片)并分类 - `merge_cross_page_tables()`: 跨页表格合并(TODO) - 所有子模块函数的重新导出(向后兼容) **使用示例**: ```python from ocr_utils.pdf_utils import PDFUtils # 加载PDF并分类 images, pdf_type, pdf_doc, renderer = PDFUtils.load_and_classify_document( document_path=Path("test.pdf"), dpi=200, page_range="1-5", renderer="fitz" ) ``` ### 2. pdf_coordinate_transform.py (~250行) **作用**: PDF坐标系与图像坐标系的转换 **核心函数**: - `pdf_rotation_to_image_rotation()`: **PDF旋转角度转换为图片旋转角度** - `transform_bbox_for_rotation_fitz()`: fitz引擎的完整几何坐标变换 - `transform_bbox_for_rotation_pypdfium2()`: pypdfium2引擎的坐标值交换 **坐标系说明**: - **PDF坐标系**: 左下角原点 (0,0),X向右,Y向上 - **图像坐标系**: 左上角原点 (0,0),X向右,Y向下 **旋转定义(重要)**: - **PDF rotation**: 0/90/180/270度(**顺时针旋转**,PDF规范) - **图片rotation**: 0/90/180/270度(**逆时针旋转**,图像处理标准) - **对外API统一返回图片rotation**(逆时针定义) **旋转转换映射**: | PDF Rotation (顺时针) | 图片 Rotation (逆时针) | |---------------------|---------------------| | 0° | 0° | | 90° | 270° | | 180° | 180° | | 270° | 90° | **关键区别**: | 特性 | fitz | pypdfium2 | |------|------|-----------| | 输入坐标系 | PDF原始坐标系 | 已旋转的坐标系(但bbox顺序错误) | | 变换类型 | 几何空间变换 | 坐标值交换(修正min/max) | | 复杂度 | 高(涉及旋转公式) | 低(只是交换) | **使用示例**: ```python from ocr_utils.pdf_coordinate_transform import transform_bbox_for_rotation_fitz # fitz引擎: 完整几何变换 img_bbox = transform_bbox_for_rotation_fitz( bbox=[100, 50, 200, 100], rotation=90, pdf_width=595, pdf_height=842, scale=2.778 ) ``` ### 3. pdf_text_extraction.py (~450行) **作用**: 从PDF提取文本,支持rotation处理 **核心函数**: - `extract_text_from_pdf()`: 从指定区域提取文本(自动检测引擎) - `extract_all_text_blocks()`: 提取页面所有文本块(自动检测引擎) - `detect_pdf_doc_type()`: 检测PDF文档类型(fitz/pypdfium2) - `bbox_overlap()`: 检查bbox重叠 **支持引擎**: - **pypdfium2**: MinerU标准引擎 - **fitz (PyMuPDF)**: 轻量级替代引擎 **使用示例**: ```python from ocr_utils.pdf_text_extraction import extract_all_text_blocks # 提取所有文本块(自动应用rotation变换) text_blocks, rotation = extract_all_text_blocks( pdf_doc=pdf_doc, page_idx=0, scale=2.778 ) # 返回格式: # text_blocks = [ # {'text': 'Hello', 'bbox': [x1, y1, x2, y2], 'origin_bbox': [...]}, # ... # ] # rotation = 270 # 图片旋转角度:0/90/180/270(逆时针) # # 注意:返回的是图片旋转定义(逆时针),不是PDF rotation(顺时针) ``` **⚠️ 重要说明**: - `rotation` 返回值采用**图片旋转定义**(逆时针),不是PDF rotation(顺时针) - PDF rotation 90° → 返回 270°(图片需要逆时针旋转270°) - PDF rotation 270° → 返回 90°(图片需要逆时针旋转90°) ### 4. pdf_image_rendering.py (~300行) **作用**: PDF页面渲染为图像 **核心函数**: - `load_images_from_pdf_unified()`: 统一的PDF图像加载接口 - `load_images_pypdfium2()`: 使用pypdfium2渲染 - `load_images_fitz()`: 使用fitz渲染 **渲染引擎对比**: | 特性 | pypdfium2 | fitz | |------|-----------|------| | 渲染引擎 | Chrome PDFium | MuPDF | | 多进程加速 | ✅ (非Windows) | ❌ | | 超时控制 | ✅ | ❌ | | 尺寸限制 | 3500px | 4500px | | 超限处理 | 动态调整scale | 降到72 DPI | | MinerU标准 | ✅ | ❌ | **使用示例**: ```python from ocr_utils.pdf_image_rendering import load_images_from_pdf_unified # 使用pypdfium2(推荐) images, doc = load_images_from_pdf_unified( pdf_bytes=pdf_bytes, dpi=200, renderer="pypdfium2", threads=4 ) # 使用fitz images, doc = load_images_from_pdf_unified( pdf_bytes=pdf_bytes, dpi=200, renderer="fitz" ) # 返回格式: # images = [ # {'img_pil': PIL.Image, 'scale': 2.778}, # ... # ] ``` ## 🔄 向后兼容性 **所有原有代码无需修改!** `PDFUtils`类保留了所有原有方法作为包装函数,内部调用新模块的功能: ```python # 旧代码继续工作 from ocr_utils.pdf_utils import PDFUtils # 所有这些方法仍然可用: PDFUtils.extract_text_from_pdf(...) PDFUtils.extract_all_text_blocks(...) PDFUtils.load_images_from_pdf_unified(...) PDFUtils._transform_bbox_for_rotation_fitz(...) # ... 等等 ``` ## 📝 最佳实践 ### 1. **新代码**: 直接导入子模块 ```python # 推荐: 直接从子模块导入 from ocr_utils.pdf_text_extraction import extract_all_text_blocks from ocr_utils.pdf_coordinate_transform import transform_bbox_for_rotation_fitz text_blocks, rotation = extract_all_text_blocks(pdf_doc, 0, 2.778) ``` ### 2. **旧代码**: 继续使用PDFUtils ```python # 兼容: 通过PDFUtils类使用 from ocr_utils.pdf_utils import PDFUtils text_blocks, rotation = PDFUtils.extract_all_text_blocks(pdf_doc, 0, 2.778) ``` ### 3. **渲染引擎选择** ```python # 生产环境推荐: pypdfium2 (MinerU标准) renderer = "pypdfium2" # 多进程加速,更好的细节保留 # 开发/测试: fitz (简单轻量) renderer = "fitz" # 无需额外依赖,单进程 ``` ## 🎯 重构优势 1. **代码组织**: 从单个984行文件 → 4个模块,每个200-450行 2. **职责清晰**: 坐标变换、文本提取、图像渲染各自独立 3. **易于测试**: 各模块可独立测试 4. **向后兼容**: 现有代码无需修改 5. **易于扩展**: 新功能可加入对应模块,不影响其他部分 ## ✅ 测试验证 重构后通过完整测试验证: - ✅ 所有8个rotation测试通过 (4种rotation × 2种引擎) - ✅ fitz引擎: rotation 0°/90°/180°/270° 全部正确 - ✅ pypdfium2引擎: rotation 0°/90°/180°/270° 全部正确 - ✅ 坐标都在图像边界内 - ✅ 向后兼容性验证通过 测试命令: ```bash cd ocr_tools/universal_doc_parser/tests python test_pdf_rotation.py ``` ## 📚 相关文档 - [MinerU文档](https://github.com/opendatalab/MinerU) - [PyMuPDF文档](https://pymupdf.readthedocs.io/) - [pypdfium2文档](https://pypdfium2.readthedocs.io/) ## 🔧 维护指南 ### 添加新功能 根据功能类型选择合适的模块: 1. **坐标转换相关** → `pdf_coordinate_transform.py` 2. **文本提取相关** → `pdf_text_extraction.py` 3. **图像渲染相关** → `pdf_image_rendering.py` 4. **高级API/工作流** → `pdf_utils.py` ### 修改现有功能 1. 在对应子模块中修改实现 2. 如果改变了函数签名,需在`pdf_utils.py`中更新包装函数 3. 运行测试验证: `python test_pdf_rotation.py` --- **重构日期**: 2026-01-05 **重构原因**: pdf_utils.py文件过大(984行),难以维护 **重构目标**: 按功能层次拆分,提高可维护性,保持向后兼容性