|
|
@@ -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`)
|
|
|
|