Browse Source

feat: implement page-level OCR and Span-Block matching strategy to enhance text extraction accuracy, allowing for improved processing of various document types and better handling of overlapping spans

zhch158_admin 5 days ago
parent
commit
aeea003eaf
1 changed files with 97 additions and 40 deletions
  1. 97 40
      zhch/universal_doc_parser/模型统一框架.md

+ 97 - 40
zhch/universal_doc_parser/模型统一框架.md

@@ -32,66 +32,90 @@ graph TB
     B -->|数字原生PDF| D
     C1 --> D[Layout 检测<br/>去重叠框]
     
-    D --> E{元素分类}
+    D --> E[整页 OCR<br/>获取所有 text spans]
+    E --> F[Span-Block 匹配<br/>SpanMatcher]
+    F --> G{元素分类}
     
-    E --> F[文本类]
-    E --> G[表格类]
-    E --> H[图片类]
-    E --> I[公式类]
-    E --> J[丢弃类]
+    G --> H[文本类]
+    G --> I[表格类]
+    G --> J[图片类]
+    G --> K[公式类]
+    G --> L[丢弃类]
     
     subgraph 文本处理
-        F --> F1{PDF类型?}
-        F1 -->|扫描件| F2[OCR 检测+识别]
-        F1 -->|数字PDF| F3[PDF 字符提取]
-        F3 --> F4{成功?}
-        F4 -->|否| F2
-        F4 -->|是| F5[文本结果]
-        F2 --> F5
+        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 表格处理
-        G --> G1[OCR 检测<br/>获取文本框坐标]
-        G --> G2[VLM 结构识别<br/>返回 HTML]
-        G1 --> G3[坐标匹配<br/>TableCellMatcher]
-        G2 --> G3
-        G3 --> G4[带坐标的表格]
+        I --> I1[OCR 检测<br/>获取文本框坐标]
+        I --> I2[VLM 结构识别<br/>返回 HTML]
+        I1 --> I3[坐标匹配<br/>TableCellMatcher]
+        I2 --> I3
+        I3 --> I4[带坐标的表格]
     end
     
     subgraph 图片处理
-        H --> H1[裁剪保存]
+        J --> J1[裁剪保存]
     end
     
     subgraph 公式处理
-        I --> I1[VLM 识别<br/>返回 LaTeX]
+        K --> K1[VLM 识别<br/>返回 LaTeX]
     end
     
     subgraph 丢弃元素
-        J --> J1[OCR 提取文本<br/>保留备用]
+        L --> L1{有匹配的spans?}
+        L1 -->|是| L2[合并 spans 文本]
+        L1 -->|否| L3[裁剪区域 OCR]
+        L2 --> L4[保留备用]
+        L3 --> L4
     end
     
-    F5 --> K[合并所有结果]
-    G4 --> K
-    H1 --> K
-    I1 --> K
-    J1 --> K
+    H7 --> M[合并所有结果]
+    I4 --> M
+    J1 --> M
+    K1 --> M
+    L4 --> M
     
-    K --> L[按阅读顺序排序]
-    L --> M[坐标转换回原图]
-    M --> N[合并跨页表格]
-    N --> O[金额数字标准化]
-    O --> P[多格式输出]
+    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 等 | OCR 或 PDF 提取 |
+| **文本类** | 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 | OCR 提取备用 |
+| **丢弃类** | abandon, discarded | 优先使用匹配的 spans,否则裁剪 OCR |
 
 ---
 
@@ -109,15 +133,39 @@ graph TB
 
 | PDF 类型 | 文字块处理 | 表格处理 |
 |---------|-----------|---------|
-| **扫描件/图片** | OCR 检测 + 识别 | OCR 检测(坐标) + VLM(结构) |
-| **数字原生 PDF** | PDF 字符提取(失败时 OCR 补充) | OCR 检测(坐标) + VLM(结构) |
+| **扫描件/图片** | 整页 OCR → Span 匹配 | OCR 检测(坐标) + VLM(结构) |
+| **数字原生 PDF** | 整页 OCR → Span 匹配 / PDF 字符提取 | OCR 检测(坐标) + VLM(结构) |
 
 **关键点**:
-- 数字原生 PDF 的文字块可直接提取,坐标更精确
+- **整页 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`
+
 ---
 
 ## 目录结构
@@ -134,7 +182,7 @@ universal_doc_parser/
 │   ├── pipeline_manager_v2.py          # 主流水线管理器 ⭐
 │   ├── element_processors.py           # 元素处理器(文本、表格、图片等)
 │   ├── coordinate_utils.py             # 坐标转换工具
-│   ├── layout_utils.py                 # 布局处理工具(排序、去重)
+│   ├── layout_utils.py                 # 布局处理工具(排序、去重、SpanMatcher
 │   ├── pdf_utils.py                    # PDF 处理工具
 │   ├── config_manager.py               # 配置管理
 │   └── model_factory.py                # 模型工厂
@@ -338,19 +386,28 @@ layout_detection:
 - PDF 分类(扫描件/数字原生)
 - 页面方向识别
 - Layout 检测与去重
+- **整页 OCR + Span-Block 匹配** ⭐
 - 元素分类处理
 - 阅读顺序排序
 - 坐标转换
 
-### 2. ElementProcessors (`element_processors.py`)
+### 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()` - 文本处理
+- `process_text_element()` - 文本处理(支持 pre_matched_spans)
 - `process_table_element()` - 表格处理(VLM + OCR 坐标匹配)
 - `process_image_element()` - 图片处理
 - `process_equation_element()` - 公式处理
 - `process_code_element()` - 代码处理
-- `process_discard_element()` - 丢弃元素处理
+- `process_discard_element()` - 丢弃元素处理(支持 pre_matched_spans)
 
 ### 3. OutputFormatterV2 (`output_formatter_v2.py`)