# 金融文档处理统一框架 参考 MinerU 实现的模型统一框架,针对金融场景设计。 ## 支持场景 | 场景类型 | 特点 | 表格形式 | |---------|------|---------| | **银行交易流水** | 单栏列表形式,无合并单元格 | 有线表格 / 无线表格 | | **财务报表** | 多栏列表形式,有合并单元格,表头复杂 | 有线表格 / 无线表格 | ## 模型选择 | 模型类型 | 推荐模型 | 说明 | |---------|---------|------| | **版式检测** | Docling Layout / DocLayout-YOLO | HuggingFace 或 MinerU 模型 | | **文字识别** | PaddleOCR (PyTorch) | 效果好,支持角度校正 | | **表格结构识别** | MinerU VLM / PaddleOCR-VL | VLM 返回 HTML 结构 | | **公式识别** | MinerU VLM | 返回 LaTeX | | **方向识别** | PP-LCNet | 沿用 MinerU 实现 | | **单元格坐标匹配** | TableCellMatcher | OCR 检测框与 VLM 结构匹配 | --- ## 处理流程 ```mermaid graph TB A[输入 PDF/图片] --> B{PDF 分类} B -->|扫描件/图片| C1[页面方向识别
PP-LCNet] B -->|数字原生PDF| D C1 --> D[Layout 检测
去重叠框] D --> E[整页 OCR
获取所有 text spans] E --> F[Span-Block 匹配
SpanMatcher] F --> G{元素分类} G --> H[文本类] G --> I[表格类] G --> J[图片类] G --> K[公式类] G --> L[丢弃类] subgraph 文本处理 H --> H1{有匹配的spans?} H1 -->|是| H2[合并 spans 文本] H1 -->|否| H3{PDF类型?} H3 -->|数字PDF| H4[PDF 字符提取] H4 --> H5{成功?} H5 -->|否| H6[裁剪区域 OCR] H5 -->|是| H7[文本结果] H3 -->|扫描件| H6 H6 --> H7 H2 --> H7 end subgraph 表格处理 I --> I1[OCR 检测
获取文本框坐标] I --> I2[VLM 结构识别
返回 HTML] I1 --> I3[坐标匹配
TableCellMatcher] I2 --> I3 I3 --> I4[带坐标的表格] end subgraph 图片处理 J --> J1[裁剪保存] end subgraph 公式处理 K --> K1[VLM 识别
返回 LaTeX] end subgraph 丢弃元素 L --> L1{有匹配的spans?} L1 -->|是| L2[合并 spans 文本] L1 -->|否| L3[裁剪区域 OCR] L2 --> L4[保留备用] L3 --> L4 end H7 --> M[合并所有结果] I4 --> M J1 --> M K1 --> M L4 --> M M --> N[按阅读顺序排序] N --> O[坐标转换回原图] O --> P[合并跨页表格] P --> Q[金额数字标准化] Q --> R[多格式输出] ``` ### 关键改进:整页 OCR + Span 匹配 参考 MinerU 的处理方式,新流程采用 **整页 OCR → Span-Block 匹配** 策略: 1. **整页 OCR**:先对整个页面进行 OCR,获取所有 text spans(包含坐标和文本) 2. **Span 去重**:移除高 IoU 重叠的 spans,保留置信度高的 3. **Span-Block 匹配**:将 OCR spans 按重叠比例匹配到对应的 layout blocks 4. **文本合并**:将匹配到同一 block 的 spans 按阅读顺序合并 **优势**: - ✅ 避免裁剪小图 OCR 失败的问题 - ✅ OCR 可以利用更多上下文信息 - ✅ 坐标更精确(整页坐标系) - ✅ 与 MinerU 处理方式一致 ### 元素分类说明 | 元素类别 | 包含类型 | 处理方式 | |---------|---------|---------| | **文本类** | text, title, header, footer, ref_text, table_caption, image_caption 等 | 优先使用匹配的 spans,否则 PDF 提取或裁剪 OCR | | **表格类** | table, table_body | OCR 坐标 + VLM 结构 | | **图片类** | image, image_body, figure | 裁剪保存 | | **公式类** | interline_equation, equation | VLM 识别 | | **丢弃类** | abandon, discarded | 优先使用匹配的 spans,否则裁剪 OCR | --- ## 方向识别策略 | 处理阶段 | 方向识别 | 建议 | |---------|---------|------| | **页面级** | PP-LCNet | 可配置,扫描件开启,数字PDF关闭 | | **表格区域** | - | 可选,VLM 有一定容忍度,OCR 自带角度校正 | | **文本区域** | - | 不需要,OCR 自带校正 | --- ## Layout 后处理 ### 大面积文本块转表格 当Layout检测将大面积的表格区域误识别为文本框时,可以通过后处理自动转换: **判断规则**: - 面积占比:占页面面积超过阈值(默认25%) - 尺寸比例:宽度和高度都超过一定比例(避免细长条) - 表格冲突:如果页面已有表格,不进行转换(避免误判) **配置示例**: ```yaml layout: convert_large_text_to_table: true # 是否启用 min_text_area_ratio: 0.25 # 最小面积占比(25%) min_text_width_ratio: 0.4 # 最小宽度占比(40%) min_text_height_ratio: 0.3 # 最小高度占比(30%) ``` 详细说明请参考:`Layout后处理-文本转表格.md` --- ## OCR 使用策略 | PDF 类型 | 文字块处理 | 表格处理 | |---------|-----------|---------| | **扫描件/图片** | 整页 OCR → Span 匹配 | OCR 检测(坐标) + VLM(结构) | | **数字原生 PDF** | 整页 OCR → Span 匹配 / PDF 字符提取 | OCR 检测(坐标) + VLM(结构) | **关键点**: - **整页 OCR 优先**:先对整页进行 OCR,再将结果匹配到 layout blocks - 数字原生 PDF 在 spans 匹配失败时,会尝试 PDF 字符提取 - **表格处理无论 PDF 类型都需要 OCR 检测**,用于获取单元格内文本的精确坐标 - VLM 只返回表格结构(HTML),不返回单元格坐标,需要与 OCR 检测结果匹配 - 当前实现仅使用 VLM(MinerU VLM 或 PaddleOCR-VL)进行表格结构识别 ### OCR 参数配置 **默认参数(已优化,参考PPStructureV3)**: - `det_threshold`: 0.6(检测框置信度阈值,提高可减少噪声框) - `unclip_ratio`: 1.5(检测框扩展比例,降低可提高框精确度) - `enable_merge_det_boxes`: False(是否合并检测框,表格场景建议False) **配置示例**: ```yaml ocr: det_threshold: 0.6 # 检测阈值(0.3-0.7,越高越严格) unclip_ratio: 1.5 # 扩展比例(1.3-1.8,越低越精确) enable_merge_det_boxes: false # 合并框(表格场景建议false) language: ch # 语言(ch/ch_lite/en等) ``` **参数调优建议**: - **表格密集场景**:`det_threshold=0.6`, `enable_merge_det_boxes=false` - **文本稀疏场景**:`det_threshold=0.4`, `enable_merge_det_boxes=true` - **扫描件质量差**:`det_threshold=0.3`, `unclip_ratio=1.8` 详细分析请参考:`OCR识别差异分析与改进方案.md` --- ## 目录结构 ``` universal_doc_parser/ ├── config/ # 配置文件 │ ├── bank_statement_yusys_v2.yaml # 银行流水配置(Docling + PaddleOCR-VL) │ ├── bank_statement_mineru_v2.yaml # 银行流水配置(MinerU layout + MinerU VLM) │ ├── bank_statement_mineru_vl.yaml # 银行流水配置(MinerU VLM) │ └── bank_statement_paddle_vl.yaml # 银行流水配置(PaddleOCR-VL) │ ├── core/ # 核心处理模块 │ ├── pipeline_manager_v2.py # 主流水线管理器 ⭐ │ ├── element_processors.py # 元素处理器(文本、表格、图片等) │ ├── coordinate_utils.py # 坐标转换工具 │ ├── layout_utils.py # 布局处理工具(排序、去重、SpanMatcher)⭐ │ ├── pdf_utils.py # PDF 处理工具 │ ├── config_manager.py # 配置管理 │ └── model_factory.py # 模型工厂 │ ├── models/ # 模型适配器 │ └── adapters/ │ ├── base.py # 适配器基类 │ ├── mineru_adapter.py # MinerU 适配器 │ ├── paddle_vl_adapter.py # PaddleOCR-VL 适配器 │ ├── paddle_layout_detector.py # PaddleX RT-DETR 布局检测器 │ └── docling_layout_adapter.py # Docling 布局检测器 ⭐ │ ├── utils/ # 输出工具模块 │ ├── output_formatter_v2.py # 统一输出格式化器 ⭐ │ ├── json_formatters.py # JSON 格式化(middle.json, page.json) │ ├── markdown_generator.py # Markdown 生成器 │ ├── html_generator.py # HTML 生成器 │ ├── visualization_utils.py # 可视化工具(layout/OCR 图片) │ └── normalize_financial_numbers.py # 金额数字标准化 │ ├── main_v2.py # 命令行入口 ⭐ └── 模型统一框架.md # 本文档 ``` --- ## 使用方法 ### 命令行 ```bash # 处理单个 PDF 文件 python main_v2.py -i document.pdf -c config/bank_statement_yusys_v2.yaml # 处理图片目录 python main_v2.py -i ./images/ -c config/bank_statement_yusys_v2.yaml # 开启 debug 模式(输出可视化图片) python main_v2.py -i doc.pdf -c config/bank_statement_yusys_v2.yaml --debug # 指定输出目录 python main_v2.py -i doc.pdf -c config/bank_statement_yusys_v2.yaml -o ./my_output/ ``` ### Python API ```python from core.pipeline_manager_v2 import EnhancedDocPipeline from utils import OutputFormatterV2 # 初始化流水线 with EnhancedDocPipeline("config/bank_statement_yusys_v2.yaml") as pipeline: # 处理文档 results = pipeline.process_document("document.pdf") # 保存结果 formatter = OutputFormatterV2("./output") output_paths = formatter.save_results(results, { 'save_json': True, 'save_markdown': True, 'save_html': True, 'save_layout_image': True, # debug 'save_ocr_image': True, # debug 'normalize_numbers': True, # 金额标准化 }) ``` --- ## 输出文件说明 | 输出文件 | 说明 | |---------|------| | `{doc}_middle.json` | MinerU 标准格式 JSON | | `{doc}_page_001.json` | 每页独立 JSON(包含单元格坐标) | | `{doc}.md` | 完整文档 Markdown | | `{doc}_page_001.md` | 每页独立 Markdown(带坐标注释) | | `tables/*.html` | 表格 HTML 文件(带 data-bbox 坐标) | | `images/` | 提取的图片元素 | | `{doc}_page_001_layout.png` | Layout 可视化图片(debug 模式) | | `{doc}_page_001_ocr.png` | OCR 可视化图片(debug 模式) | | `*_original.*` | 标准化前的原始文件(如有修改) | --- ## 配置说明 配置文件采用 YAML 格式,主要配置项: ```yaml # 场景名称 scene_name: "bank_statement" # 输入配置 input: supported_formats: [".pdf", ".png", ".jpg", ".jpeg"] dpi: 200 # PDF 转图片的 DPI # 预处理(方向识别) preprocessor: module: "mineru" orientation_classifier: enabled: true # 扫描件自动开启 # 版式检测 layout_detection: module: "docling" # 可选: "mineru", "paddle", "docling" model_name: "docling-layout-old" model_dir: "ds4sd/docling-layout-old" # HuggingFace 模型仓库 device: "cpu" conf: 0.3 # VL 识别(表格、公式) vl_recognition: module: "paddle" # 可选: "mineru", "paddle" backend: "http-client" server_url: "http://xxx:8110" table_recognition: return_cells_coordinate: true # OCR 识别 ocr_recognition: module: "mineru" language: "ch" # 输出配置 output: create_subdir: false # 是否创建子目录 save_json: true save_markdown: true save_html: true save_layout_image: false # debug 模式开启 save_ocr_image: false # debug 模式开启 normalize_numbers: true # 金额数字标准化 ``` --- ## 支持的布局检测器 ### 1. Docling Layout (推荐) 基于 HuggingFace transformers 的 RT-DETR 模型。 ```yaml layout_detection: module: "docling" model_name: "docling-layout-old" model_dir: "ds4sd/docling-layout-old" ``` 支持的模型: - `ds4sd/docling-layout-old` - `ds4sd/docling-layout-heron` - `ds4sd/docling-layout-egret-medium` - `ds4sd/docling-layout-egret-large` ### 2. PaddleX RT-DETR (ONNX) 基于 ONNX Runtime 的 PaddleX 布局检测器。 ```yaml layout_detection: module: "paddle" model_name: "RT-DETR-H_layout_17cls" model_dir: "/path/to/RT-DETR-H_layout_17cls.onnx" ``` ### 3. MinerU DocLayout-YOLO MinerU 内置的布局检测模型。 ```yaml layout_detection: module: "mineru" model_name: "layout" ``` --- ## 类别映射 所有布局检测器的输出都会统一映射到 MinerU/EnhancedDocPipeline 类别体系: | 类别分类 | 包含类别 | |---------|---------| | **文本类** (TEXT) | text, title, header, footer, page_number, ref_text, page_footnote, aside_text, ocr_text | | **表格类** (TABLE) | table, table_body, table_caption, table_footnote | | **图片类** (IMAGE) | image, image_body, figure, image_caption, image_footnote | | **公式类** (EQUATION) | interline_equation, inline_equation, equation | | **代码类** (CODE) | code, code_body, code_caption, algorithm | | **丢弃类** (DISCARD) | abandon, discarded | --- ## 核心组件 ### 1. EnhancedDocPipeline (`pipeline_manager_v2.py`) 主流水线管理器,实现完整处理流程: - PDF 分类(扫描件/数字原生) - 页面方向识别 - Layout 检测与去重 - **整页 OCR + Span-Block 匹配** ⭐ - 元素分类处理 - 阅读顺序排序 - 坐标转换 ### 2. SpanMatcher (`layout_utils.py`) OCR Span 与 Layout Block 匹配器,参考 MinerU 实现: - `match_spans_to_blocks()` - 将 spans 匹配到对应的 blocks - `merge_spans_to_text()` - 将多个 spans 合并为文本 - `remove_duplicate_spans()` - 去除重复 spans - `poly_to_bbox()` - 多边形坐标转 bbox ### 3. ElementProcessors (`element_processors.py`) 元素处理器,处理不同类型的元素: - `process_text_element()` - 文本处理(支持 pre_matched_spans) - `process_table_element()` - 表格处理(VLM + OCR 坐标匹配) - `process_image_element()` - 图片处理 - `process_equation_element()` - 公式处理 - `process_code_element()` - 代码处理 - `process_discard_element()` - 丢弃元素处理(支持 pre_matched_spans) ### 3. OutputFormatterV2 (`output_formatter_v2.py`) 统一输出格式化器: - MinerU 标准 middle.json 格式 - 每页独立 JSON(含单元格坐标) - Markdown 输出(完整版 + 按页) - 表格 HTML(带 data-bbox 属性) - 可视化图片(Layout/OCR) - 金额数字标准化 ### 4. TableCellMatcher (来自 `merger`) 表格单元格坐标匹配器: - 使用动态规划进行行内单元格匹配 - 将 OCR 检测框与 VLM 表格结构匹配 - 输出带坐标的增强 HTML --- ## 依赖说明 ### MinerU 组件 - `mineru.utils.pdf_image_tools` - PDF 图像处理 - `mineru.utils.pdf_text_tool` - PDF 文本提取 - `mineru.utils.boxbase` - 边界框计算 - `mineru.model.ocr` - OCR 模型 - `mineru.model.ori_cls` - 方向分类模型 ### Merger 组件(来自 ocr_verify) - `merger.table_cell_matcher.TableCellMatcher` - 单元格坐标匹配 - `merger.text_matcher.TextMatcher` - 文本匹配 ### 其他依赖 - transformers - Docling 模型加载 - huggingface_hub - 模型下载 - onnxruntime - ONNX 模型推理 - Pillow - 图像处理 - NumPy - 数值计算 - BeautifulSoup4 - HTML 解析 - PyYAML - 配置文件解析 - loguru - 日志 --- ## 安装 merger 模块 ```bash # 1. 进入 ocr_verify 目录 cd /Users/zhch158/workspace/repository.git/ocr_verify # 2. 安装 merger 模块(可编辑模式) pip uninstall -y merger && pip install -e . # 3. 验证安装 python3 -c "from merger.table_cell_matcher import TableCellMatcher; print('✅ 安装成功')" ``` 完成后,在任何 Python 文件中都可以直接导入: ```python from merger.table_cell_matcher import TableCellMatcher from merger.text_matcher import TextMatcher from merger.bbox_extractor import BBoxExtractor ``` --- ## 项目结构 ``` /Users/zhch158/workspace/repository.git/ ├── ocr_verify/ # 源项目 │ ├── setup.py # 安装配置 │ └── merger/ # 表格匹配模块 │ ├── table_cell_matcher.py # 表格单元格匹配 │ ├── text_matcher.py # 文本匹配 │ └── bbox_extractor.py # 边界框提取 │ └── MinerU/ # 目标项目 └── zhch/ └── universal_doc_parser/ # 金融文档处理框架 ├── core/ # 核心处理模块 ├── models/adapters/ # 模型适配器 ├── utils/ # 输出工具 └── config/ # 配置文件 ```