|
@@ -2,6 +2,32 @@
|
|
|
|
|
|
|
|
参考 MinerU 实现的模型统一框架,针对金融场景设计。
|
|
参考 MinerU 实现的模型统一框架,针对金融场景设计。
|
|
|
|
|
|
|
|
|
|
+## 核心设计理念
|
|
|
|
|
+
|
|
|
|
|
+### 1. 模块化与可替换性
|
|
|
|
|
+框架采用**模块化设计**,各处理节点可根据不同场景灵活替换:
|
|
|
|
|
+- **方向识别**:支持多种模型(PP-LCNet、PDF rotation等)
|
|
|
|
|
+- **Layout检测**:支持 Docling、MinerU、Paddle、DiT 等多种检测器
|
|
|
|
|
+- **OCR识别**:支持 PaddleOCR
|
|
|
|
|
+- **表格识别**:支持 UNet(有线表格)、VLM(无线表格)等多种方案
|
|
|
|
|
+- **公式识别**:支持 MinerU VLM、PaddleOCR-VL 等
|
|
|
|
|
+
|
|
|
|
|
+通过配置文件(YAML)即可切换不同的模型组合,无需修改代码。
|
|
|
|
|
+
|
|
|
|
|
+### 2. 统一输出格式
|
|
|
|
|
+无论使用何种模型组合,**输出格式统一**,确保下游处理的一致性:
|
|
|
|
|
+- **统一内部描述结构**:`middle.json`(MinerU 标准格式)
|
|
|
|
|
+- **增强版格式**:`enhanced.json`(包含更多元数据)
|
|
|
|
|
+- **多格式输出**:JSON、Markdown、HTML 等
|
|
|
|
|
+- **坐标统一**:所有坐标统一转换回原图坐标系
|
|
|
|
|
+
|
|
|
|
|
+### 3. 场景适配
|
|
|
|
|
+针对不同业务场景(银行流水、财务报表等),提供预配置的配置文件:
|
|
|
|
|
+- 银行流水场景:`bank_statement_*.yaml`
|
|
|
|
|
+- 财务报表场景:可自定义配置
|
|
|
|
|
+- 支持有线/无线表格自动分类
|
|
|
|
|
+- 支持文字PDF和扫描件混合处理
|
|
|
|
|
+
|
|
|
## 支持场景
|
|
## 支持场景
|
|
|
|
|
|
|
|
| 场景类型 | 特点 | 表格形式 |
|
|
| 场景类型 | 特点 | 表格形式 |
|
|
@@ -16,7 +42,8 @@
|
|
|
| **方向分类** | PP-LCNet_x1_0_doc_ori | paddle onnx格式的模型 |
|
|
| **方向分类** | PP-LCNet_x1_0_doc_ori | paddle onnx格式的模型 |
|
|
|
| **版式检测** | Docling Layout / DocLayout-YOLO | Docling 或 MinerU 模型 |
|
|
| **版式检测** | Docling Layout / DocLayout-YOLO | Docling 或 MinerU 模型 |
|
|
|
| **文字识别** | PaddleOCR (PyTorch) | 效果好,支持角度校正 |
|
|
| **文字识别** | PaddleOCR (PyTorch) | 效果好,支持角度校正 |
|
|
|
-| **表格结构识别** | MinerU VLM / PaddleOCR-VL / UNET 有线表格 | VLM 返回 HTML 结构 |
|
|
|
|
|
|
|
+| **表格分类** | PaddleTableClsModel | 自动区分有线/无线表格 ⭐ 新增 |
|
|
|
|
|
+| **表格结构识别** | MinerU VLM / PaddleOCR-VL / UNET 有线表格 | VLM 返回 HTML 结构,UNet 返回单元格坐标 |
|
|
|
| **公式识别** | MinerU VLM | 返回 LaTeX |
|
|
| **公式识别** | MinerU VLM | 返回 LaTeX |
|
|
|
| **单元格坐标匹配** | TableCellMatcher | OCR 检测框与 VLM 结构匹配 |
|
|
| **单元格坐标匹配** | TableCellMatcher | OCR 检测框与 VLM 结构匹配 |
|
|
|
|
|
|
|
@@ -24,48 +51,47 @@
|
|
|
|
|
|
|
|
## 处理流程
|
|
## 处理流程
|
|
|
|
|
|
|
|
-### 主流程图
|
|
|
|
|
|
|
+### 主流程图(简化版)
|
|
|
|
|
+
|
|
|
|
|
+主流程采用**模块化设计**,各处理节点可根据场景配置替换:
|
|
|
|
|
|
|
|
```mermaid
|
|
```mermaid
|
|
|
graph TB
|
|
graph TB
|
|
|
- A[输入 PDF/图片] --> B[加载文档并分类]
|
|
|
|
|
-
|
|
|
|
|
- B --> C{文档类型?}
|
|
|
|
|
- C -->|PDF| D[PDF分类: 扫描件/数字原生]
|
|
|
|
|
- C -->|图片目录| E[加载所有图片]
|
|
|
|
|
-
|
|
|
|
|
- D --> F[处理每一页]
|
|
|
|
|
- E --> F
|
|
|
|
|
-
|
|
|
|
|
- F --> G[页面方向识别<br/>仅扫描件]
|
|
|
|
|
- G --> H[Layout 检测]
|
|
|
|
|
-
|
|
|
|
|
- H --> I[去重重叠框]
|
|
|
|
|
- I --> J{大文本块转表格?}
|
|
|
|
|
- J -->|启用| K[后处理转换]
|
|
|
|
|
- J -->|否| L
|
|
|
|
|
- K --> L[整页 OCR<br/>获取所有 text spans]
|
|
|
|
|
-
|
|
|
|
|
- L --> M[Span 去重与排序]
|
|
|
|
|
- M --> N[Span-Block 匹配<br/>SpanMatcher]
|
|
|
|
|
|
|
+ A[输入 PDF/图片] --> B[文档加载与分类]
|
|
|
|
|
|
|
|
- N --> O[元素分类]
|
|
|
|
|
- O --> P[处理各类元素]
|
|
|
|
|
|
|
+ B --> C[逐页处理<br/>详见单页处理流程]
|
|
|
|
|
|
|
|
- P --> Q[按阅读顺序排序]
|
|
|
|
|
- Q --> R[坐标转换回原图]
|
|
|
|
|
|
|
+ C --> D[跨页表格合并]
|
|
|
|
|
|
|
|
- R --> S{所有页处理完?}
|
|
|
|
|
- S -->|否| F
|
|
|
|
|
- S -->|是| T[跨页表格合并]
|
|
|
|
|
|
|
+ D --> E[统一输出格式<br/>JSON/Markdown/HTML]
|
|
|
|
|
|
|
|
- T --> U[输出结果]
|
|
|
|
|
|
|
+ style C fill:#e1f5ff
|
|
|
|
|
+ style E fill:#fff4e1
|
|
|
|
|
|
|
|
- style L fill:#e1f5ff
|
|
|
|
|
- style N fill:#e1f5ff
|
|
|
|
|
- style P fill:#fff4e1
|
|
|
|
|
|
|
+ classDef replaceable fill:#ffe1e1,stroke:#ff0000,stroke-width:2px
|
|
|
|
|
+ class B,C,D replaceable
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
+**关键特性**:
|
|
|
|
|
+- ✅ **模块化设计**:各处理节点可独立替换(见下方"可替换组件")
|
|
|
|
|
+- ✅ **统一输出格式**:无论使用何种模型组合,输出格式统一(见"输出格式说明")
|
|
|
|
|
+- ✅ **单页处理流程**:详见下方详细流程图
|
|
|
|
|
+
|
|
|
|
|
+**可替换组件**:
|
|
|
|
|
+- **方向识别**:PP-LCNet(扫描件) / PDF rotation(文字PDF)
|
|
|
|
|
+- **Layout检测**:Docling / MinerU / Paddle / DiT
|
|
|
|
|
+- **OCR识别**:PaddleOCR / MinerU OCR
|
|
|
|
|
+- **表格分类**:PaddleTableClsModel(可选)
|
|
|
|
|
+- **表格识别**:UNet(有线) / VLM(无线:MinerU VLM / PaddleOCR-VL)
|
|
|
|
|
+- **公式识别**:MinerU VLM / PaddleOCR-VL
|
|
|
|
|
+
|
|
|
|
|
+**统一输出格式**:
|
|
|
|
|
+- `{doc}_middle.json`:MinerU 标准格式(统一内部描述结构)
|
|
|
|
|
+- `{doc}_enhanced.json`:增强版格式(包含更多元数据)
|
|
|
|
|
+- `{doc}_page_XXX.json`:每页独立 JSON(包含单元格坐标)
|
|
|
|
|
+- `{doc}.md` / `{doc}_page_XXX.md`:Markdown 格式
|
|
|
|
|
+- `tables/*.html`:表格 HTML(带 data-bbox 坐标)
|
|
|
|
|
+
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
### 单页处理详细流程
|
|
### 单页处理详细流程
|
|
@@ -75,17 +101,28 @@ graph TB
|
|
|
A[输入:页面图像] --> B{PDF类型?}
|
|
A[输入:页面图像] --> B{PDF类型?}
|
|
|
|
|
|
|
|
B -->|扫描件| C[页面方向识别<br/>PP-LCNet]
|
|
B -->|扫描件| C[页面方向识别<br/>PP-LCNet]
|
|
|
- B -->|数字PDF| D
|
|
|
|
|
|
|
+ B -->|文字PDF| C1[获取PDF页面rotation<br/>转换为rotate_angle并旋转图像]
|
|
|
C --> D[Layout 检测<br/>Docling/MinerU/DiT]
|
|
C --> D[Layout 检测<br/>Docling/MinerU/DiT]
|
|
|
|
|
+ C1 --> D
|
|
|
|
|
|
|
|
D --> E[去重重叠框<br/>IoU过滤]
|
|
D --> E[去重重叠框<br/>IoU过滤]
|
|
|
E --> F{大文本块转表格?}
|
|
E --> F{大文本块转表格?}
|
|
|
|
|
|
|
|
F -->|是| G[面积占比判断<br/>转换为table类型]
|
|
F -->|是| G[面积占比判断<br/>转换为table类型]
|
|
|
F -->|否| H
|
|
F -->|否| H
|
|
|
- G --> H[整页 OCR<br/>获取所有 text spans]
|
|
|
|
|
|
|
+ G --> H
|
|
|
|
|
+
|
|
|
|
|
+ H --> H1{PDF类型?}
|
|
|
|
|
+ H1 -->|扫描件| H2[整页 OCR<br/>获取所有 text spans]
|
|
|
|
|
+ H1 -->|文字PDF| H3[PDF文本提取<br/>extract_all_text_blocks]
|
|
|
|
|
|
|
|
- H --> I[Span 去重<br/>IoU过滤]
|
|
|
|
|
|
|
+ H3 --> H4{页面类型检测}
|
|
|
|
|
+ H4 -->|文字页| H5[使用PDF提取结果]
|
|
|
|
|
+ H4 -->|扫描页| H2
|
|
|
|
|
+ H3 -->|提取失败| H2
|
|
|
|
|
+
|
|
|
|
|
+ H2 --> I[Span 去重<br/>IoU过滤]
|
|
|
|
|
+ H5 --> I
|
|
|
I --> J[Span 排序<br/>从上到下、从左到右]
|
|
I --> J[Span 排序<br/>从上到下、从左到右]
|
|
|
J --> K[Span-Block 匹配<br/>overlap_threshold=0.5]
|
|
J --> K[Span-Block 匹配<br/>overlap_threshold=0.5]
|
|
|
|
|
|
|
@@ -115,7 +152,8 @@ graph TB
|
|
|
S --> T[按阅读顺序排序]
|
|
S --> T[按阅读顺序排序]
|
|
|
T --> U[坐标转换回原图]
|
|
T --> U[坐标转换回原图]
|
|
|
|
|
|
|
|
- style H fill:#e1f5ff
|
|
|
|
|
|
|
+ style H2 fill:#e1f5ff
|
|
|
|
|
+ style H3 fill:#e1f5ff
|
|
|
style K fill:#e1f5ff
|
|
style K fill:#e1f5ff
|
|
|
style L fill:#fff4e1
|
|
style L fill:#fff4e1
|
|
|
style L1 fill:#fff4e1
|
|
style L1 fill:#fff4e1
|
|
@@ -126,37 +164,68 @@ graph TB
|
|
|
style L6 fill:#fff4e1
|
|
style L6 fill:#fff4e1
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-### 关键改进:整页 OCR + Span 匹配
|
|
|
|
|
|
|
+### 关键改进:整页 OCR/PDF提取 + Span 匹配
|
|
|
|
|
+
|
|
|
|
|
+参考 MinerU 的处理方式,新流程采用 **整页文本提取 → Span-Block 匹配** 策略:
|
|
|
|
|
+
|
|
|
|
|
+**处理路径**:
|
|
|
|
|
|
|
|
-参考 MinerU 的处理方式,新流程采用 **整页 OCR → Span-Block 匹配** 策略:
|
|
|
|
|
|
|
+1. **扫描件/图片**:
|
|
|
|
|
+ - **整页 OCR**:先对整个页面进行 OCR,获取所有 text spans(包含坐标和文本)
|
|
|
|
|
+ - 获取所有 OCR spans
|
|
|
|
|
|
|
|
-1. **整页 OCR**:先对整个页面进行 OCR,获取所有 text spans(包含坐标和文本)
|
|
|
|
|
-2. **Span 去重**:移除高 IoU 重叠的 spans,保留置信度高的
|
|
|
|
|
-3. **Span 排序**:按坐标排序(从上到下,从左到右),方便人工检查缺失字符
|
|
|
|
|
-4. **Span-Block 匹配**:将 OCR spans 按重叠比例(默认0.5)匹配到对应的 layout blocks
|
|
|
|
|
-5. **文本合并**:将匹配到同一 block 的 spans 按阅读顺序合并
|
|
|
|
|
|
|
+2. **文字PDF**:
|
|
|
|
|
+ - **PDF文本提取**:从PDF直接提取文本块(`extract_all_text_blocks`)
|
|
|
|
|
+ - **页面类型检测**:检测该页是否为扫描页(`detect_page_type`)
|
|
|
|
|
+ - 如果是文字页:使用PDF提取结果
|
|
|
|
|
+ - 如果是扫描页:fallback到OCR
|
|
|
|
|
+ - **提取失败时**:自动fallback到OCR
|
|
|
|
|
+
|
|
|
|
|
+**后续处理(统一)**:
|
|
|
|
|
+
|
|
|
|
|
+3. **Span 去重**:移除高 IoU 重叠的 spans,保留置信度高的
|
|
|
|
|
+4. **Span 排序**:按坐标排序(从上到下,从左到右),方便人工检查缺失字符
|
|
|
|
|
+5. **Span-Block 匹配**:将 spans 按重叠比例(默认0.5)匹配到对应的 layout blocks
|
|
|
|
|
+6. **文本合并**:将匹配到同一 block 的 spans 按阅读顺序合并
|
|
|
|
|
|
|
|
**优势**:
|
|
**优势**:
|
|
|
- ✅ 避免裁剪小图 OCR 失败的问题
|
|
- ✅ 避免裁剪小图 OCR 失败的问题
|
|
|
- ✅ OCR 可以利用更多上下文信息
|
|
- ✅ OCR 可以利用更多上下文信息
|
|
|
- ✅ 坐标更精确(整页坐标系)
|
|
- ✅ 坐标更精确(整页坐标系)
|
|
|
- ✅ 减少重复 OCR 调用,提高效率
|
|
- ✅ 减少重复 OCR 调用,提高效率
|
|
|
|
|
+- ✅ **文字PDF优先使用PDF文本提取**,准确率更高,速度更快
|
|
|
|
|
+- ✅ **自动fallback机制**:PDF提取失败或检测到扫描页时自动使用OCR
|
|
|
- ✅ 与 MinerU 处理方式一致
|
|
- ✅ 与 MinerU 处理方式一致
|
|
|
|
|
|
|
|
**代码实现**:
|
|
**代码实现**:
|
|
|
```python
|
|
```python
|
|
|
-# 1. 整页 OCR
|
|
|
|
|
-all_ocr_spans = self.ocr_recognizer.recognize_text(detection_image)
|
|
|
|
|
|
|
+# 1. 根据PDF类型选择文本提取方式
|
|
|
|
|
+if pdf_type == 'txt' and pdf_doc is not None:
|
|
|
|
|
+ # 文字PDF:从PDF提取文本块
|
|
|
|
|
+ actual_page_type = PDFUtils.detect_page_type(pdf_doc, page_idx)
|
|
|
|
|
+ if actual_page_type == 'txt':
|
|
|
|
|
+ all_text_spans, rotation = PDFUtils.extract_all_text_blocks(
|
|
|
|
|
+ pdf_doc, page_idx, scale=scale, return_upright_coords=True
|
|
|
|
|
+ )
|
|
|
|
|
+ all_text_spans = self._convert_pdf_blocks_to_spans(
|
|
|
|
|
+ all_text_spans, detection_image.shape
|
|
|
|
|
+ )
|
|
|
|
|
+ else:
|
|
|
|
|
+ # 扫描页,使用OCR
|
|
|
|
|
+ all_text_spans = self.ocr_recognizer.recognize_text(detection_image)
|
|
|
|
|
+else:
|
|
|
|
|
+ # 扫描件:整页 OCR
|
|
|
|
|
+ all_text_spans = self.ocr_recognizer.recognize_text(detection_image)
|
|
|
|
|
|
|
|
# 2. 去除重复 spans
|
|
# 2. 去除重复 spans
|
|
|
-all_ocr_spans = SpanMatcher.remove_duplicate_spans(all_ocr_spans)
|
|
|
|
|
|
|
+all_text_spans = SpanMatcher.remove_duplicate_spans(all_text_spans)
|
|
|
|
|
|
|
|
# 3. 按坐标排序
|
|
# 3. 按坐标排序
|
|
|
-all_ocr_spans = self._sort_spans_by_position(all_ocr_spans)
|
|
|
|
|
|
|
+all_text_spans = self._sort_spans_by_position(all_text_spans)
|
|
|
|
|
|
|
|
-# 4. 将 OCR spans 匹配到 layout blocks
|
|
|
|
|
|
|
+# 4. 将 spans 匹配到 layout blocks
|
|
|
matched_spans = SpanMatcher.match_spans_to_blocks(
|
|
matched_spans = SpanMatcher.match_spans_to_blocks(
|
|
|
- all_ocr_spans, layout_results, overlap_threshold=0.5
|
|
|
|
|
|
|
+ all_text_spans, layout_results, overlap_threshold=0.5
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
# 5. 在元素处理时使用预匹配的 spans
|
|
# 5. 在元素处理时使用预匹配的 spans
|
|
@@ -172,6 +241,8 @@ element = self.element_processors.process_text_element(
|
|
|
|
|
|
|
|
表格处理支持两种路径:**有线表格(UNET)** 和 **无线表格(VLM)**
|
|
表格处理支持两种路径:**有线表格(UNET)** 和 **无线表格(VLM)**
|
|
|
|
|
|
|
|
|
|
+**新增功能**:支持自动表格分类,根据表格类型自动选择识别器
|
|
|
|
|
+
|
|
|
```mermaid
|
|
```mermaid
|
|
|
graph TB
|
|
graph TB
|
|
|
A[表格区域] --> B[表格 OCR 预处理]
|
|
A[表格区域] --> B[表格 OCR 预处理]
|
|
@@ -186,23 +257,31 @@ graph TB
|
|
|
B5 --> B6
|
|
B5 --> B6
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
- B6 --> C{使用有线表格?}
|
|
|
|
|
|
|
+ B6 --> C{启用表格分类?}
|
|
|
|
|
+
|
|
|
|
|
+ C -->|是| C1[表格分类器<br/>PaddleTableClsModel]
|
|
|
|
|
+ C1 --> C2{分类结果?}
|
|
|
|
|
+ C2 -->|wired| D[UNet 有线表格路径]
|
|
|
|
|
+ C2 -->|wireless| E[VLM 无线表格路径]
|
|
|
|
|
|
|
|
- C -->|是| D[UNet 有线表格路径]
|
|
|
|
|
- C -->|否| E[VLM 无线表格路径]
|
|
|
|
|
|
|
+ C -->|否| C3{手动配置?}
|
|
|
|
|
+ C3 -->|use_wired_unet=true| D
|
|
|
|
|
+ C3 -->|否| E
|
|
|
|
|
|
|
|
subgraph 有线表格路径
|
|
subgraph 有线表格路径
|
|
|
D --> D1[UNet 检测表格线<br/>横线 + 竖线]
|
|
D --> D1[UNet 检测表格线<br/>横线 + 竖线]
|
|
|
D1 --> D2{启用倾斜矫正?}
|
|
D1 --> D2{启用倾斜矫正?}
|
|
|
- D2 -->|是| D3[Hough变换检测角度<br/>矫正图片和OCR坐标]
|
|
|
|
|
|
|
+ D2 -->|是| D3[基于Mask检测倾斜角度<br/>Hough变换 + 矫正图片和OCR坐标]
|
|
|
D2 -->|否| D4
|
|
D2 -->|否| D4
|
|
|
D3 --> D4[网格恢复<br/>grid_recovery.py]
|
|
D3 --> D4[网格恢复<br/>grid_recovery.py]
|
|
|
- D4 --> D5[边缘过滤<br/>edge_margin=padding×upscale×1.2]
|
|
|
|
|
|
|
+ D4 --> D4a[连通域提取单元格<br/>OCR边缘补偿]
|
|
|
|
|
+ D4a --> D5[边缘过滤<br/>edge_margin=padding×upscale×1.2]
|
|
|
D5 --> D6[文本填充<br/>text_filling.py]
|
|
D5 --> D6[文本填充<br/>text_filling.py]
|
|
|
- D6 --> D7[生成HTML<br/>data-bbox属性]
|
|
|
|
|
- D7 --> D8{识别成功?}
|
|
|
|
|
- D8 -->|否| E[自动Fallback到VLM]
|
|
|
|
|
- D8 -->|是| F
|
|
|
|
|
|
|
+ D6 --> D7[二次OCR修正<br/>单元格裁剪OCR]
|
|
|
|
|
+ D7 --> D8[生成HTML<br/>data-bbox属性]
|
|
|
|
|
+ D8 --> D9{识别成功?}
|
|
|
|
|
+ D9 -->|否| E[自动Fallback到VLM]
|
|
|
|
|
+ D9 -->|是| F
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
subgraph 无线表格路径
|
|
subgraph 无线表格路径
|
|
@@ -221,6 +300,26 @@ graph TB
|
|
|
style E1 fill:#fff4e1
|
|
style E1 fill:#fff4e1
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
+#### 表格分类(可选)
|
|
|
|
|
+
|
|
|
|
|
+**配置项**:`table_classification.enabled: true`
|
|
|
|
|
+
|
|
|
|
|
+启用后,系统会自动对每个表格进行分类,判断是有线表格还是无线表格:
|
|
|
|
|
+
|
|
|
|
|
+1. **分类模型**:使用 MinerU 的 `PaddleTableClsModel`
|
|
|
|
|
+2. **分类结果**:
|
|
|
|
|
+ - `wired`:有线表格(带边框)→ 使用 UNet 识别
|
|
|
|
|
+ - `wireless`:无线表格(无边框)→ 使用 VLM 识别
|
|
|
|
|
+3. **辅助判断**:使用线条检测辅助判断
|
|
|
|
|
+ - 只有横线或只有竖线 → 强制判断为无线表格
|
|
|
|
|
+ - 无线条 → 判断为无线表格
|
|
|
|
|
+4. **置信度阈值**:`confidence_threshold: 0.5`(可配置)
|
|
|
|
|
+
|
|
|
|
|
+**优势**:
|
|
|
|
|
+- ✅ 自动选择最优识别器,无需手动配置
|
|
|
|
|
+- ✅ 提高识别准确率(有线表格用UNet,无线表格用VLM)
|
|
|
|
|
+- ✅ 支持混合场景(同一文档中同时存在有线/无线表格)
|
|
|
|
|
+
|
|
|
#### 表格OCR预处理(共享逻辑)
|
|
#### 表格OCR预处理(共享逻辑)
|
|
|
|
|
|
|
|
无论使用哪种表格识别方法,都需要先进行OCR预处理:
|
|
无论使用哪种表格识别方法,都需要先进行OCR预处理:
|
|
@@ -228,7 +327,7 @@ graph TB
|
|
|
1. **裁剪表格区域**:添加 `padding=10px` 保护边缘内容
|
|
1. **裁剪表格区域**:添加 `padding=10px` 保护边缘内容
|
|
|
2. **表格方向检测**:使用 PP-LCNet 检测并矫正表格方向
|
|
2. **表格方向检测**:使用 PP-LCNet 检测并矫正表格方向
|
|
|
3. **收集OCR框**:
|
|
3. **收集OCR框**:
|
|
|
- - **优先**:使用整页OCR结果中与表格区域重叠的spans
|
|
|
|
|
|
|
+ - **优先**:使用整页OCR结果中与表格区域重叠的spans(仅当表格未旋转时)
|
|
|
- **兜底**:对裁剪后的表格区域单独OCR
|
|
- **兜底**:对裁剪后的表格区域单独OCR
|
|
|
4. **坐标转换**:将坐标从原图转换到裁剪后的表格图像坐标系
|
|
4. **坐标转换**:将坐标从原图转换到裁剪后的表格图像坐标系
|
|
|
|
|
|
|
@@ -236,6 +335,7 @@ graph TB
|
|
|
- padding=10px 在原图坐标系中
|
|
- padding=10px 在原图坐标系中
|
|
|
- 表格图像的 (0,0) 对应原图的 (bbox[0]-padding, bbox[1]-padding)
|
|
- 表格图像的 (0,0) 对应原图的 (bbox[0]-padding, bbox[1]-padding)
|
|
|
- UNet处理时会放大 upscale_ratio≈3.333 倍
|
|
- UNet处理时会放大 upscale_ratio≈3.333 倍
|
|
|
|
|
+- **文字PDF支持**:对于文字PDF(`pdf_type='txt'`),会传递 `pdf_type` 参数,支持PDF字符提取作为OCR补充
|
|
|
|
|
|
|
|
#### 有线表格识别流程(UNET)
|
|
#### 有线表格识别流程(UNET)
|
|
|
|
|
|
|
@@ -248,13 +348,15 @@ graph TB
|
|
|
- 坐标在放大后的图像坐标系(upscale≈3.333倍)
|
|
- 坐标在放大后的图像坐标系(upscale≈3.333倍)
|
|
|
|
|
|
|
|
2. **倾斜检测与矫正**(可选,`enable_deskew: true`):
|
|
2. **倾斜检测与矫正**(可选,`enable_deskew: true`):
|
|
|
- - 使用 Hough 变换检测表格线倾斜角度
|
|
|
|
|
|
|
+ - **基于Mask的倾斜检测**:使用UNet检测的横线mask进行Hough变换,检测倾斜角度
|
|
|
- 坐标系:Y轴向下,逆时针旋转为正角度
|
|
- 坐标系:Y轴向下,逆时针旋转为正角度
|
|
|
- 矫正逻辑:`correction_angle = -detected_angle`(反向旋转)
|
|
- 矫正逻辑:`correction_angle = -detected_angle`(反向旋转)
|
|
|
- 同步更新表格图像和OCR框坐标
|
|
- 同步更新表格图像和OCR框坐标
|
|
|
|
|
+ - 矫正后重新运行UNet,确保mask与矫正后的图像对齐
|
|
|
|
|
|
|
|
3. **网格恢复**(`grid_recovery.py`):
|
|
3. **网格恢复**(`grid_recovery.py`):
|
|
|
- - 提取唯一的行线和列线坐标
|
|
|
|
|
|
|
+ - **连通域提取**:使用连通域法提取单元格(替代投影法)
|
|
|
|
|
+ - **OCR边缘补偿**:使用OCR框信息补偿边缘单元格,提高边缘单元格识别准确率
|
|
|
- **边缘过滤**:过滤padding区域的噪声线条
|
|
- **边缘过滤**:过滤padding区域的噪声线条
|
|
|
```python
|
|
```python
|
|
|
edge_margin = int(crop_padding × upscale × 1.2) # 例如:10 × 3.333 × 1.2 = 40px
|
|
edge_margin = int(crop_padding × upscale × 1.2) # 例如:10 × 3.333 × 1.2 = 40px
|
|
@@ -263,30 +365,50 @@ graph TB
|
|
|
- 生成单元格网格
|
|
- 生成单元格网格
|
|
|
|
|
|
|
|
4. **文本填充**(`text_filling.py`):
|
|
4. **文本填充**(`text_filling.py`):
|
|
|
- - 计算OCR框与单元格的IoU
|
|
|
|
|
|
|
+ - 计算OCR框与单元格的中心点匹配
|
|
|
- 匹配OCR文本到对应单元格
|
|
- 匹配OCR文本到对应单元格
|
|
|
- 支持置信度过滤(`ocr_conf_threshold`)
|
|
- 支持置信度过滤(`ocr_conf_threshold`)
|
|
|
|
|
|
|
|
-5. **HTML生成**:
|
|
|
|
|
|
|
+5. **二次OCR修正**(`text_filling.py`):
|
|
|
|
|
+ - **总是执行**,不区分PDF类型
|
|
|
|
|
+ - 对单元格进行裁剪OCR,补充或修正文本
|
|
|
|
|
+ - 处理空文本单元格、低置信度文本、OCR误合并等情况
|
|
|
|
|
+ - 对于文字PDF(`pdf_type='txt'`),空文本单元格不触发二次OCR,为了解决文字PDF中误合并问题
|
|
|
|
|
+
|
|
|
|
|
+6. **HTML生成**:
|
|
|
- 生成标准表格HTML
|
|
- 生成标准表格HTML
|
|
|
- 添加 `data-bbox` 属性记录单元格坐标
|
|
- 添加 `data-bbox` 属性记录单元格坐标
|
|
|
|
|
|
|
|
-6. **坐标逆转换**:
|
|
|
|
|
|
|
+7. **坐标逆转换**:
|
|
|
- 将所有坐标从裁剪+放大坐标系转换回原图坐标系
|
|
- 将所有坐标从裁剪+放大坐标系转换回原图坐标系
|
|
|
|
|
+ - 如果进行了倾斜矫正,需要逆向旋转坐标
|
|
|
|
|
|
|
|
-7. **自动Fallback**:
|
|
|
|
|
- - 如果有线识别失败(返回空HTML),自动切换到VLM识别
|
|
|
|
|
|
|
+8. **自动Fallback**:
|
|
|
|
|
+ - 如果有线识别失败(返回空HTML或空cells),自动切换到VLM识别
|
|
|
- 无需手动干预,确保识别鲁棒性
|
|
- 无需手动干预,确保识别鲁棒性
|
|
|
|
|
|
|
|
|
|
+**文字PDF支持**:
|
|
|
|
|
+- 支持传递 `pdf_type='txt'` 参数到有线表格识别器
|
|
|
|
|
+- 二次OCR修正,处理空文本单元格、低置信度文本、OCR误合并等情况
|
|
|
|
|
+- 对于文字PDF(`pdf_type='txt'`),空文本单元格不触发二次OCR,为了解决文字PDF中误合并问题
|
|
|
|
|
+
|
|
|
**关键配置**:
|
|
**关键配置**:
|
|
|
```yaml
|
|
```yaml
|
|
|
|
|
+# 表格分类配置(推荐启用)
|
|
|
|
|
+table_classification:
|
|
|
|
|
+ enabled: true # 启用自动表格分类
|
|
|
|
|
+ module: "paddle" # 使用 PaddleTableClsModel
|
|
|
|
|
+ confidence_threshold: 0.5 # 分类置信度阈值
|
|
|
|
|
+
|
|
|
|
|
+# 有线表格识别配置
|
|
|
table_recognition_wired:
|
|
table_recognition_wired:
|
|
|
use_wired_unet: true # 启用有线表格
|
|
use_wired_unet: true # 启用有线表格
|
|
|
upscale_ratio: 3.333 # 固定放大比例
|
|
upscale_ratio: 3.333 # 固定放大比例
|
|
|
- enable_deskew: true # 启用倾斜矫正
|
|
|
|
|
|
|
+ enable_deskew: true # 启用倾斜矫正(基于Mask检测)
|
|
|
row_threshold: 10 # 行合并阈值(像素)
|
|
row_threshold: 10 # 行合并阈值(像素)
|
|
|
col_threshold: 15 # 列合并阈值(像素)
|
|
col_threshold: 15 # 列合并阈值(像素)
|
|
|
ocr_conf_threshold: 0.8 # OCR置信度阈值
|
|
ocr_conf_threshold: 0.8 # OCR置信度阈值
|
|
|
|
|
+ use_custom_postprocess: true # 使用自定义后处理(支持OCR边缘补偿)
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
#### 无线表格识别流程(VLM)
|
|
#### 无线表格识别流程(VLM)
|
|
@@ -439,10 +561,15 @@ def process_text_element(
|
|
|
|
|
|
|
|
| 处理阶段 | 方向识别 | 建议 |
|
|
| 处理阶段 | 方向识别 | 建议 |
|
|
|
|---------|---------|------|
|
|
|---------|---------|------|
|
|
|
-| **页面级** | PP-LCNet | 可配置,扫描件开启,数字PDF关闭 |
|
|
|
|
|
|
|
+| **页面级** | 扫描件:PP-LCNet<br/>文字PDF:PDF rotation | 扫描件使用PP-LCNet模型识别<br/>文字PDF从PDF元数据获取rotation并旋转图像 |
|
|
|
| **表格区域** | - | 可选,VLM 有一定容忍度,OCR 自带角度校正 |
|
|
| **表格区域** | - | 可选,VLM 有一定容忍度,OCR 自带角度校正 |
|
|
|
| **文本区域** | - | 不需要,OCR 自带校正 |
|
|
| **文本区域** | - | 不需要,OCR 自带校正 |
|
|
|
|
|
|
|
|
|
|
+**文字PDF方向处理**:
|
|
|
|
|
+- 从PDF页面元数据获取 `rotation` 角度
|
|
|
|
|
+- 转换为统一的 `rotate_angle` 定义(图像需要逆时针旋转的角度)
|
|
|
|
|
+- 旋转图像为正视方向,确保后续Layout检测和文本提取的准确性
|
|
|
|
|
+
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
## Layout 后处理
|
|
## Layout 后处理
|
|
@@ -473,15 +600,21 @@ layout:
|
|
|
|
|
|
|
|
| PDF 类型 | 文字块处理 | 表格处理 |
|
|
| PDF 类型 | 文字块处理 | 表格处理 |
|
|
|
|---------|-----------|---------|
|
|
|---------|-----------|---------|
|
|
|
-| **扫描件/图片** | 整页 OCR → Span 匹配 | OCR 检测(坐标) + VLM(结构) |
|
|
|
|
|
-| **数字原生 PDF** | 整页 OCR → Span 匹配 / PDF 字符提取 | OCR 检测(坐标) + VLM(结构) |
|
|
|
|
|
|
|
+| **扫描件/图片** | 整页 OCR → Span 匹配 | OCR 检测(坐标) + 表格分类 → UNet/VLM(结构) |
|
|
|
|
|
+| **数字原生 PDF(文字PDF)** | 整页 OCR → Span 匹配 / PDF 字符提取 | OCR 检测(坐标) + 表格分类 → UNet/VLM(结构)<br/>+ 单元格OCR修正(PDF字符提取优先) |
|
|
|
|
|
|
|
|
**关键点**:
|
|
**关键点**:
|
|
|
- **整页 OCR 优先**:先对整页进行 OCR,再将结果匹配到 layout blocks
|
|
- **整页 OCR 优先**:先对整页进行 OCR,再将结果匹配到 layout blocks
|
|
|
- 数字原生 PDF 在 spans 匹配失败时,会尝试 PDF 字符提取
|
|
- 数字原生 PDF 在 spans 匹配失败时,会尝试 PDF 字符提取
|
|
|
- **表格处理无论 PDF 类型都需要 OCR 检测**,用于获取单元格内文本的精确坐标
|
|
- **表格处理无论 PDF 类型都需要 OCR 检测**,用于获取单元格内文本的精确坐标
|
|
|
-- VLM 只返回表格结构(HTML),不返回单元格坐标,需要与 OCR 检测结果匹配
|
|
|
|
|
-- 当前实现仅使用 VLM(MinerU VLM 或 PaddleOCR-VL)进行表格结构识别
|
|
|
|
|
|
|
+- **表格分类**:支持自动分类(有线/无线),自动选择最优识别器
|
|
|
|
|
+- **有线表格(UNet)**:
|
|
|
|
|
+ - 支持文字PDF,在二次OCR修正时优先使用PDF字符提取
|
|
|
|
|
+ - 支持OCR边缘补偿,提高边缘单元格识别准确率
|
|
|
|
|
+ - 识别失败时自动fallback到VLM
|
|
|
|
|
+- **无线表格(VLM)**:
|
|
|
|
|
+ - VLM 只返回表格结构(HTML),不返回单元格坐标
|
|
|
|
|
+ - 需要与 OCR 检测结果匹配(TableCellMatcher)
|
|
|
|
|
|
|
|
### OCR 参数配置
|
|
### OCR 参数配置
|
|
|
|
|
|
|
@@ -538,6 +671,9 @@ ocr:
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
universal_doc_parser/
|
|
universal_doc_parser/
|
|
|
|
|
+├── __init__.py
|
|
|
|
|
+├── main_v2.py # 命令行入口 ⭐
|
|
|
|
|
+│
|
|
|
├── config/ # 配置文件
|
|
├── config/ # 配置文件
|
|
|
│ ├── bank_statement_yusys_v2.yaml # 银行流水配置(Docling + PaddleOCR-VL)
|
|
│ ├── bank_statement_yusys_v2.yaml # 银行流水配置(Docling + PaddleOCR-VL)
|
|
|
│ ├── bank_statement_mineru_v2.yaml # 银行流水配置(MinerU layout + MinerU VLM)
|
|
│ ├── bank_statement_mineru_v2.yaml # 银行流水配置(MinerU layout + MinerU VLM)
|
|
@@ -557,15 +693,17 @@ universal_doc_parser/
|
|
|
│
|
|
│
|
|
|
├── models/ # 模型适配器
|
|
├── models/ # 模型适配器
|
|
|
│ └── adapters/
|
|
│ └── adapters/
|
|
|
|
|
+│ ├── __init__.py
|
|
|
│ ├── base.py # 适配器基类
|
|
│ ├── base.py # 适配器基类
|
|
|
│ ├── mineru_adapter.py # MinerU 适配器
|
|
│ ├── mineru_adapter.py # MinerU 适配器
|
|
|
│ ├── paddle_vl_adapter.py # PaddleOCR-VL 适配器
|
|
│ ├── paddle_vl_adapter.py # PaddleOCR-VL 适配器
|
|
|
│ ├── paddle_layout_detector.py # PaddleX RT-DETR 布局检测器
|
|
│ ├── paddle_layout_detector.py # PaddleX RT-DETR 布局检测器
|
|
|
|
|
+│ ├── paddle_table_classifier.py # Paddle表格分类器 ⭐ 新增
|
|
|
│ ├── docling_layout_adapter.py # Docling 布局检测器 ⭐
|
|
│ ├── docling_layout_adapter.py # Docling 布局检测器 ⭐
|
|
|
│ ├── dit_layout_adapter.py # DiT 布局检测器 ⭐ 新增
|
|
│ ├── dit_layout_adapter.py # DiT 布局检测器 ⭐ 新增
|
|
|
│ ├── mineru_wired_table.py # MinerU 有线表格识别器 ⭐ 新增
|
|
│ ├── mineru_wired_table.py # MinerU 有线表格识别器 ⭐ 新增
|
|
|
│ └── wired_table/ # 有线表格子模块 ⭐ 新增
|
|
│ └── wired_table/ # 有线表格子模块 ⭐ 新增
|
|
|
-│ ├── init.py
|
|
|
|
|
|
|
+│ ├── __init__.py
|
|
|
│ ├── debug_utils.py # 调试工具
|
|
│ ├── debug_utils.py # 调试工具
|
|
|
│ ├── ocr_formatter.py # OCR 格式转换
|
|
│ ├── ocr_formatter.py # OCR 格式转换
|
|
|
│ ├── skew_detection.py # 倾斜检测与矫正
|
|
│ ├── skew_detection.py # 倾斜检测与矫正
|
|
@@ -573,16 +711,31 @@ universal_doc_parser/
|
|
|
│ ├── text_filling.py # 文本填充
|
|
│ ├── text_filling.py # 文本填充
|
|
|
│ ├── html_generator.py # HTML 生成
|
|
│ ├── html_generator.py # HTML 生成
|
|
|
│ └── visualization.py # 可视化
|
|
│ └── visualization.py # 可视化
|
|
|
-│
|
|
|
|
|
|
|
+│
|
|
|
|
|
+├── dit_support/ # DiT 布局检测器支持模块 ⭐
|
|
|
|
|
+│ ├── configs/ # DiT 配置文件
|
|
|
|
|
+│ │ ├── Base-RCNN-FPN.yaml
|
|
|
|
|
+│ │ └── cascade/
|
|
|
|
|
+│ │ └── cascade_dit_large.yaml
|
|
|
|
|
+│ ├── ditod/ # DiT 模型实现
|
|
|
|
|
+│ │ ├── __init__.py
|
|
|
|
|
+│ │ ├── backbone.py
|
|
|
|
|
+│ │ ├── beit.py
|
|
|
|
|
+│ │ ├── config.py
|
|
|
|
|
+│ │ └── deit.py
|
|
|
|
|
+│ └── README.md
|
|
|
|
|
+│
|
|
|
├── utils/ # 输出工具模块(已迁移到 ocr_utils)⚠️
|
|
├── utils/ # 输出工具模块(已迁移到 ocr_utils)⚠️
|
|
|
-│ └── init.py # 仅作重新导出接口
|
|
|
|
|
-│
|
|
|
|
|
-├── tests/ # 测试模块
|
|
|
|
|
-│ ├── test_skew_correction.py # 倾斜矫正测试
|
|
|
|
|
-│ └── ...
|
|
|
|
|
-│
|
|
|
|
|
-├── main_v2.py # 命令行入口 ⭐
|
|
|
|
|
-└── 模型统一框架.md # 本文档
|
|
|
|
|
|
|
+│ └── __init__.py # 仅作重新导出接口
|
|
|
|
|
+│
|
|
|
|
|
+└── tests/ # 测试模块
|
|
|
|
|
+ ├── test_dit_layout_adapter.py # DiT 布局检测器测试
|
|
|
|
|
+ ├── test_doclayoutyolo.py # DocLayout-YOLO 测试
|
|
|
|
|
+ ├── test_layout_detector.py # 布局检测器测试
|
|
|
|
|
+ ├── test_pdf_rotation.py # PDF 旋转测试
|
|
|
|
|
+ ├── test_skew_correction.py # 倾斜矫正测试
|
|
|
|
|
+ ├── test_table_routing.py # 表格路由测试
|
|
|
|
|
+ └── *.png # 测试图片文件
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
---
|
|
---
|
|
@@ -609,7 +762,7 @@ python main_v2.py -i doc.pdf -c config/bank_statement_yusys_v2.yaml -o ./my_outp
|
|
|
|
|
|
|
|
```python
|
|
```python
|
|
|
from core.pipeline_manager_v2 import EnhancedDocPipeline
|
|
from core.pipeline_manager_v2 import EnhancedDocPipeline
|
|
|
-from utils import OutputFormatterV2
|
|
|
|
|
|
|
+from ocr_utils import OutputFormatterV2 # 从 ocr_utils 导入
|
|
|
|
|
|
|
|
# 初始化流水线
|
|
# 初始化流水线
|
|
|
with EnhancedDocPipeline("config/bank_statement_yusys_v2.yaml") as pipeline:
|
|
with EnhancedDocPipeline("config/bank_statement_yusys_v2.yaml") as pipeline:
|
|
@@ -650,31 +803,51 @@ python main_v2.py -i large_document.pdf -c config.yaml --streaming -o ./output
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 输出文件说明
|
|
|
|
|
-
|
|
|
|
|
-| 输出文件 | 说明 |
|
|
|
|
|
-|---------|------|
|
|
|
|
|
-| `{doc}_middle.json` | MinerU 标准格式 JSON |
|
|
|
|
|
-| `{doc}_enhanced.json` | 增强版 JSON(包含更多元数据)⭐ 新增 |
|
|
|
|
|
-| `{doc}_page_001.json` | 每页独立 JSON(包含单元格坐标) |
|
|
|
|
|
-| `{doc}_pdf_page_001.png` | PDF转换的页面图片 ⭐ 新增 |
|
|
|
|
|
-| `{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 模式) |
|
|
|
|
|
-| `{doc}_page_001_table_001_lines.png` | 有线表格线可视化 ⭐ 新增(wired debug) |
|
|
|
|
|
-| `{doc}_page_001_table_001_grid.png` | 有线表格网格结构 ⭐ 新增(wired debug) |
|
|
|
|
|
-| `{doc}_page_001_table_001_text.png` | 有线表格文本覆盖 ⭐ 新增(wired debug) |
|
|
|
|
|
-| `{doc}_page_001_table_001_components.png` | 有线表格连通域 ⭐ 新增(wired debug) |
|
|
|
|
|
-| `*_original.*` | 标准化前的原始文件(如有修改) |
|
|
|
|
|
|
|
+## 输出格式说明(统一描述格式)
|
|
|
|
|
+
|
|
|
|
|
+**核心原则**:无论使用何种模型组合,输出格式统一,确保下游处理的一致性。
|
|
|
|
|
+
|
|
|
|
|
+### 主要输出文件
|
|
|
|
|
+
|
|
|
|
|
+| 输出文件 | 格式说明 | 用途 |
|
|
|
|
|
+|---------|---------|------|
|
|
|
|
|
+| `{doc}_middle.json` | **MinerU 标准格式**(统一内部描述结构) | 标准输出,兼容 MinerU 生态 |
|
|
|
|
|
+| `{doc}_enhanced.json` | 增强版 JSON(包含更多元数据)⭐ | 包含识别方法、置信度等详细信息 |
|
|
|
|
|
+| `{doc}_page_001.json` | 每页独立 JSON(包含单元格坐标) | 按页输出,包含精确坐标信息 |
|
|
|
|
|
+| `{doc}.md` | 完整文档 Markdown | 人类可读格式 |
|
|
|
|
|
+| `{doc}_page_001.md` | 每页独立 Markdown(带坐标注释) | 按页 Markdown,便于检查 |
|
|
|
|
|
+| `tables/*.html` | 表格 HTML(带 `data-bbox` 坐标) | 表格结构化输出,包含单元格坐标 |
|
|
|
|
|
+| `images/` | 提取的图片元素 | 图片资源 |
|
|
|
|
|
+
|
|
|
|
|
+### 统一格式特点
|
|
|
|
|
+
|
|
|
|
|
+1. **坐标统一**:所有坐标统一转换回**原图坐标系**,确保一致性
|
|
|
|
|
+2. **结构统一**:无论使用何种识别方法,输出结构统一
|
|
|
|
|
+3. **元数据完整**:包含识别方法、置信度、处理时间等元数据
|
|
|
|
|
+4. **多格式支持**:同时输出 JSON、Markdown、HTML 等多种格式
|
|
|
|
|
+
|
|
|
|
|
+### 调试输出文件(可选)
|
|
|
|
|
+
|
|
|
|
|
+| 输出文件 | 说明 | 启用条件 |
|
|
|
|
|
+|---------|------|---------|
|
|
|
|
|
+| `{doc}_pdf_page_001.png` | PDF转换的页面图片 | `output.save_pdf_images: true` |
|
|
|
|
|
+| `{doc}_page_001_layout.png` | Layout 可视化图片 | `output.save_layout_image: true` |
|
|
|
|
|
+| `{doc}_page_001_ocr.png` | OCR 可视化图片 | `output.save_ocr_image: true` |
|
|
|
|
|
+| `{doc}_page_001_table_001_lines.png` | 有线表格线可视化 | `table_recognition_wired.debug_options.enabled: true` |
|
|
|
|
|
+| `{doc}_page_001_table_001_grid.png` | 有线表格网格结构 | `table_recognition_wired.debug_options.enabled: true` |
|
|
|
|
|
+| `{doc}_page_001_table_001_text.png` | 有线表格文本覆盖 | `table_recognition_wired.debug_options.enabled: true` |
|
|
|
|
|
+| `{doc}_page_001_table_001_components.png` | 有线表格连通域 | `table_recognition_wired.debug_options.enabled: true` |
|
|
|
|
|
+| `{doc}_page_001_table_001_paddle_table_lines.png` | 表格分类线条检测可视化 | `table_classification.debug_options.enabled: true` |
|
|
|
|
|
|
|
|
**有线表格调试输出说明**:
|
|
**有线表格调试输出说明**:
|
|
|
- 当配置 `table_recognition_wired.debug_options.enabled: true` 时,会生成详细的可视化图片
|
|
- 当配置 `table_recognition_wired.debug_options.enabled: true` 时,会生成详细的可视化图片
|
|
|
- 这些图片帮助理解表格识别的各个处理阶段(表格线提取、网格恢复、文本填充等)
|
|
- 这些图片帮助理解表格识别的各个处理阶段(表格线提取、网格恢复、文本填充等)
|
|
|
- 详细说明请参考:[有线表格识别技术文档.md](有线表格识别技术文档.md)
|
|
- 详细说明请参考:[有线表格识别技术文档.md](有线表格识别技术文档.md)
|
|
|
|
|
|
|
|
|
|
+**表格分类调试输出说明**:
|
|
|
|
|
+- 当配置 `table_classification.debug_options.enabled: true` 时,会生成表格线检测可视化图片
|
|
|
|
|
+- 用于理解分类器如何判断表格类型(有线/无线)
|
|
|
|
|
+
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
## 配置说明
|
|
## 配置说明
|
|
@@ -717,6 +890,31 @@ ocr_recognition:
|
|
|
module: "mineru"
|
|
module: "mineru"
|
|
|
language: "ch"
|
|
language: "ch"
|
|
|
|
|
|
|
|
|
|
+# 表格分类配置(自动区分有线/无线表格)
|
|
|
|
|
+table_classification:
|
|
|
|
|
+ enabled: true # 是否启用自动表格分类(默认关闭,使用手动配置)
|
|
|
|
|
+ module: "paddle" # 分类模型:paddle(MinerU PaddleTableClsModel)
|
|
|
|
|
+ confidence_threshold: 0.5 # 分类置信度阈值
|
|
|
|
|
+ batch_size: 16 # 批处理大小
|
|
|
|
|
+ debug_options:
|
|
|
|
|
+ enabled: false # 是否开启调试可视化输出
|
|
|
|
|
+ save_table_lines: true # 保存表格线可视化
|
|
|
|
|
+
|
|
|
|
|
+# 有线表格识别配置
|
|
|
|
|
+table_recognition_wired:
|
|
|
|
|
+ use_wired_unet: true # 是否启用有线表格识别
|
|
|
|
|
+ upscale_ratio: 3.333 # 放大比例
|
|
|
|
|
+ enable_deskew: true # 是否启用倾斜矫正
|
|
|
|
|
+ row_threshold: 10 # 行合并阈值(像素)
|
|
|
|
|
+ col_threshold: 15 # 列合并阈值(像素)
|
|
|
|
|
+ ocr_conf_threshold: 0.8 # OCR置信度阈值
|
|
|
|
|
+ debug_options:
|
|
|
|
|
+ enabled: false # 是否开启调试可视化输出
|
|
|
|
|
+ save_table_lines: true # 保存表格线可视化
|
|
|
|
|
+ save_connected_components: true # 保存连通域提取的单元格图
|
|
|
|
|
+ save_grid_structure: true # 保存逻辑网格结构
|
|
|
|
|
+ save_text_overlay: true # 保存文本填充覆盖图
|
|
|
|
|
+
|
|
|
# 输出配置
|
|
# 输出配置
|
|
|
output:
|
|
output:
|
|
|
create_subdir: false # 是否创建子目录
|
|
create_subdir: false # 是否创建子目录
|
|
@@ -730,9 +928,15 @@ output:
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 支持的布局检测器
|
|
|
|
|
|
|
+## 可替换组件说明
|
|
|
|
|
+
|
|
|
|
|
+框架采用**适配器模式**,各组件可根据场景灵活替换。通过修改配置文件即可切换,无需修改代码。
|
|
|
|
|
+
|
|
|
|
|
+### 布局检测器(Layout Detection)
|
|
|
|
|
|
|
|
-### 1. Docling Layout (推荐)
|
|
|
|
|
|
|
+支持多种布局检测模型,通过 `layout_detection.module` 配置切换:
|
|
|
|
|
+
|
|
|
|
|
+#### 1. Docling Layout (推荐)
|
|
|
|
|
|
|
|
基于 HuggingFace transformers 的 RT-DETR 模型。
|
|
基于 HuggingFace transformers 的 RT-DETR 模型。
|
|
|
|
|
|
|
@@ -749,7 +953,7 @@ layout_detection:
|
|
|
- `ds4sd/docling-layout-egret-medium`
|
|
- `ds4sd/docling-layout-egret-medium`
|
|
|
- `ds4sd/docling-layout-egret-large`
|
|
- `ds4sd/docling-layout-egret-large`
|
|
|
|
|
|
|
|
-### 2. PaddleX RT-DETR (ONNX)
|
|
|
|
|
|
|
+#### 2. PaddleX RT-DETR (ONNX)
|
|
|
|
|
|
|
|
基于 ONNX Runtime 的 PaddleX 布局检测器。
|
|
基于 ONNX Runtime 的 PaddleX 布局检测器。
|
|
|
|
|
|
|
@@ -760,7 +964,7 @@ layout_detection:
|
|
|
model_dir: "/path/to/RT-DETR-H_layout_17cls.onnx"
|
|
model_dir: "/path/to/RT-DETR-H_layout_17cls.onnx"
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-### 3. MinerU DocLayout-YOLO
|
|
|
|
|
|
|
+#### 3. MinerU DocLayout-YOLO
|
|
|
|
|
|
|
|
MinerU 内置的布局检测模型。
|
|
MinerU 内置的布局检测模型。
|
|
|
|
|
|
|
@@ -770,7 +974,7 @@ layout_detection:
|
|
|
model_name: "layout"
|
|
model_name: "layout"
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-### 4. DiT Layout (Document Image Transformer)
|
|
|
|
|
|
|
+#### 4. DiT Layout (Document Image Transformer)
|
|
|
|
|
|
|
|
基于 Detectron2 的 DiT 模型,在 PubLayNet 数据集上训练。
|
|
基于 Detectron2 的 DiT 模型,在 PubLayNet 数据集上训练。
|
|
|
|
|
|
|
@@ -782,18 +986,67 @@ layout_detection:
|
|
|
device: "cpu"
|
|
device: "cpu"
|
|
|
conf: 0.3
|
|
conf: 0.3
|
|
|
```
|
|
```
|
|
|
-支持类别:
|
|
|
|
|
|
|
|
|
|
-text:正文文本
|
|
|
|
|
-title:标题
|
|
|
|
|
-list:列表
|
|
|
|
|
-table:表格
|
|
|
|
|
-figure:图片/图表
|
|
|
|
|
-特点:
|
|
|
|
|
|
|
+**支持类别**:text、title、list、table、figure
|
|
|
|
|
|
|
|
-基于 Vision Transformer 架构
|
|
|
|
|
-适合学术文档和出版物
|
|
|
|
|
-需要 Detectron2 框架支持
|
|
|
|
|
|
|
+**特点**:基于 Vision Transformer 架构,适合学术文档和出版物
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### OCR识别器(OCR Recognition)
|
|
|
|
|
+
|
|
|
|
|
+通过 `ocr_recognition.module` 配置切换:
|
|
|
|
|
+
|
|
|
|
|
+- **MinerU OCR**:`module: "mineru"`
|
|
|
|
|
+- **PaddleOCR**:`module: "paddle"`(需配置模型路径)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 表格识别器(Table Recognition)
|
|
|
|
|
+
|
|
|
|
|
+#### 表格分类器(可选)
|
|
|
|
|
+
|
|
|
|
|
+通过 `table_classification.module` 配置:
|
|
|
|
|
+
|
|
|
|
|
+- **PaddleTableClsModel**:`module: "paddle"`(自动区分有线/无线表格)
|
|
|
|
|
+
|
|
|
|
|
+#### 有线表格识别
|
|
|
|
|
+
|
|
|
|
|
+通过 `table_recognition_wired.use_wired_unet` 配置:
|
|
|
|
|
+
|
|
|
|
|
+- **UNet 有线表格**:`use_wired_unet: true`(MinerU UNet模型)
|
|
|
|
|
+
|
|
|
|
|
+#### 无线表格识别
|
|
|
|
|
+
|
|
|
|
|
+通过 `vl_recognition.module` 配置:
|
|
|
|
|
+
|
|
|
|
|
+- **MinerU VLM**:`module: "mineru"`
|
|
|
|
|
+- **PaddleOCR-VL**:`module: "paddle"`(需配置服务地址)
|
|
|
|
|
+
|
|
|
|
|
+**后端支持**:
|
|
|
|
|
+- `backend: "http-client"`:HTTP 客户端
|
|
|
|
|
+- `backend: "vllm-engine"`:vLLM 引擎
|
|
|
|
|
+- `backend: "transformers"`:Transformers 库
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 公式识别器(Equation Recognition)
|
|
|
|
|
+
|
|
|
|
|
+通过 `vl_recognition.module` 配置(与无线表格共享):
|
|
|
|
|
+
|
|
|
|
|
+- **MinerU VLM**:`module: "mineru"`
|
|
|
|
|
+- **PaddleOCR-VL**:`module: "paddle"`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 方向识别器(Orientation Classification)
|
|
|
|
|
+
|
|
|
|
|
+- **扫描件**:PP-LCNet(`preprocessor.module: "mineru"`)
|
|
|
|
|
+- **文字PDF**:自动从PDF元数据获取rotation(无需配置)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+**配置示例**:见 `config/bank_statement_*.yaml` 文件
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
@@ -821,7 +1074,8 @@ figure:图片/图表
|
|
|
- 页面方向识别
|
|
- 页面方向识别
|
|
|
- Layout 检测与去重
|
|
- Layout 检测与去重
|
|
|
- **整页 OCR + Span-Block 匹配** ⭐
|
|
- **整页 OCR + Span-Block 匹配** ⭐
|
|
|
-- 元素分类处理
|
|
|
|
|
|
|
+- **表格自动分类**(可选)⭐ 新增
|
|
|
|
|
+- 元素分类处理(支持智能选择表格识别器)
|
|
|
- 阅读顺序排序
|
|
- 阅读顺序排序
|
|
|
- 坐标转换
|
|
- 坐标转换
|
|
|
|
|
|
|
@@ -837,15 +1091,33 @@ OCR Span 与 Layout Block 匹配器,参考 MinerU 实现:
|
|
|
|
|
|
|
|
元素处理器,处理不同类型的元素:
|
|
元素处理器,处理不同类型的元素:
|
|
|
- `process_text_element()` - 文本处理(支持 pre_matched_spans)
|
|
- `process_text_element()` - 文本处理(支持 pre_matched_spans)
|
|
|
-- `process_table_element()` - 表格处理(VLM + OCR 坐标匹配)
|
|
|
|
|
|
|
+- `process_table_element_wired()` - 有线表格处理(UNet + OCR 坐标匹配,支持文字PDF)
|
|
|
|
|
+- `process_table_element_vlm()` - 无线表格处理(VLM + OCR 坐标匹配)
|
|
|
- `process_image_element()` - 图片处理
|
|
- `process_image_element()` - 图片处理
|
|
|
- `process_equation_element()` - 公式处理
|
|
- `process_equation_element()` - 公式处理
|
|
|
- `process_code_element()` - 代码处理
|
|
- `process_code_element()` - 代码处理
|
|
|
- `process_discard_element()` - 丢弃元素处理(支持 pre_matched_spans)
|
|
- `process_discard_element()` - 丢弃元素处理(支持 pre_matched_spans)
|
|
|
|
|
|
|
|
-### 3. OutputFormatterV2 (`output_formatter_v2.py`)
|
|
|
|
|
|
|
+### 3.1. PaddleTableClassifier (`paddle_table_classifier.py`) ⭐ 新增
|
|
|
|
|
|
|
|
-统一输出格式化器:
|
|
|
|
|
|
|
+表格分类器,自动区分有线表格和无线表格:
|
|
|
|
|
+- `classify()` - 分类单个表格图像
|
|
|
|
|
+- `batch_classify()` - 批量分类表格图像
|
|
|
|
|
+- 使用 MinerU 的 `PaddleTableClsModel` 进行分类
|
|
|
|
|
+- 支持线条检测辅助判断(只有横线或竖线时强制判断为无线表格)
|
|
|
|
|
+
|
|
|
|
|
+### 3.1. PaddleTableClassifier (`paddle_table_classifier.py`) ⭐ 新增
|
|
|
|
|
+
|
|
|
|
|
+表格分类器,自动区分有线表格和无线表格:
|
|
|
|
|
+- `classify()` - 分类单个表格图像
|
|
|
|
|
+- `batch_classify()` - 批量分类表格图像
|
|
|
|
|
+- 使用 MinerU 的 `PaddleTableClsModel` 进行分类
|
|
|
|
|
+- 支持线条检测辅助判断(只有横线或竖线时强制判断为无线表格)
|
|
|
|
|
+- 输出分类结果:`wired`(有线表格)或 `wireless`(无线表格)
|
|
|
|
|
+
|
|
|
|
|
+### 4. OutputFormatterV2 (来自 `ocr_utils`)
|
|
|
|
|
+
|
|
|
|
|
+统一输出格式化器,位于 `ocr_utils` 包中:
|
|
|
- MinerU 标准 middle.json 格式
|
|
- MinerU 标准 middle.json 格式
|
|
|
- 每页独立 JSON(含单元格坐标)
|
|
- 每页独立 JSON(含单元格坐标)
|
|
|
- Markdown 输出(完整版 + 按页)
|
|
- Markdown 输出(完整版 + 按页)
|
|
@@ -853,7 +1125,12 @@ OCR Span 与 Layout Block 匹配器,参考 MinerU 实现:
|
|
|
- 可视化图片(Layout/OCR)
|
|
- 可视化图片(Layout/OCR)
|
|
|
- 金额数字标准化
|
|
- 金额数字标准化
|
|
|
|
|
|
|
|
-### 4. TableCellMatcher (来自 `merger`)
|
|
|
|
|
|
|
+**导入方式**:
|
|
|
|
|
+```python
|
|
|
|
|
+from ocr_utils import OutputFormatterV2
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 5. TableCellMatcher (来自 `merger`)
|
|
|
|
|
|
|
|
表格单元格坐标匹配器:
|
|
表格单元格坐标匹配器:
|
|
|
- 使用动态规划进行行内单元格匹配
|
|
- 使用动态规划进行行内单元格匹配
|
|
@@ -871,7 +1148,7 @@ OCR Span 与 Layout Block 匹配器,参考 MinerU 实现:
|
|
|
- `mineru.model.ocr` - OCR 模型
|
|
- `mineru.model.ocr` - OCR 模型
|
|
|
- `mineru.model.ori_cls` - 方向分类模型
|
|
- `mineru.model.ori_cls` - 方向分类模型
|
|
|
|
|
|
|
|
-### OCR Tools 组件(来自 ocr_tools.ocr_merger)⚠️
|
|
|
|
|
|
|
+### OCR Tools 组件(来自 `ocr_tools.ocr_merger`)⚠️
|
|
|
|
|
|
|
|
实际导入路径(**注意:不是 ocr_verify**):
|
|
实际导入路径(**注意:不是 ocr_verify**):
|
|
|
|
|
|
|
@@ -883,29 +1160,61 @@ from ocr_tools.ocr_merger import TableCellMatcher, TextMatcher
|
|
|
├── table_cell_matcher.py # 单元格坐标匹配
|
|
├── table_cell_matcher.py # 单元格坐标匹配
|
|
|
├── text_matcher.py # 文本匹配
|
|
├── text_matcher.py # 文本匹配
|
|
|
└── merger_core.py # 核心匹配算法
|
|
└── merger_core.py # 核心匹配算法
|
|
|
-````
|
|
|
|
|
-功能说明:
|
|
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**功能说明**:
|
|
|
|
|
+- `TableCellMatcher`:将 OCR 检测框与 VLM 表格结构匹配,使用动态规划算法
|
|
|
|
|
+- `TextMatcher`:文本相似度匹配工具
|
|
|
|
|
+
|
|
|
|
|
+### OCR Utils 工具包(`ocr_utils`)⭐
|
|
|
|
|
+
|
|
|
|
|
+**定位**:统一的OCR工具包,提供文档处理相关的工具函数,支持跨项目复用。
|
|
|
|
|
+
|
|
|
|
|
+**主要模块**:
|
|
|
|
|
|
|
|
-TableCellMatcher:将 OCR 检测框与 VLM 表格结构匹配,使用动态规划算法
|
|
|
|
|
-TextMatcher:文本相似度匹配工具
|
|
|
|
|
|
|
+| 模块 | 功能 | 说明 |
|
|
|
|
|
+|------|------|------|
|
|
|
|
|
+| `OutputFormatterV2` | 统一输出格式化器 | 生成 JSON、Markdown、HTML 等格式 |
|
|
|
|
|
+| `JSONFormatters` | JSON 格式化工具 | 格式化 MinerU 标准 JSON、增强 JSON 等 |
|
|
|
|
|
+| `MarkdownGenerator` | Markdown 生成器 | 生成完整文档和按页 Markdown |
|
|
|
|
|
+| `HTMLGenerator` | HTML 生成器 | 生成表格 HTML(带 data-bbox 坐标) |
|
|
|
|
|
+| `VisualizationUtils` | 可视化工具 | Layout、OCR 可视化图片生成 |
|
|
|
|
|
+| `normalize_financial_numbers` | 金额标准化 | 金融数字标准化(金额、百分比等) |
|
|
|
|
|
+| `PDFUtils` | PDF 处理工具 | PDF 文本提取、坐标转换等 |
|
|
|
|
|
+| `BBoxExtractor` | 边界框提取器 | 从 HTML 等格式提取边界框 |
|
|
|
|
|
+| `file_utils` | 文件处理工具 | 文件列表处理、PDF 转图片等 |
|
|
|
|
|
+| `image_utils` | 图像处理工具 | 图像解码、预处理、坐标转换等 |
|
|
|
|
|
+| `html_utils` | HTML 处理工具 | HTML 表格解析、图片处理等 |
|
|
|
|
|
+| `number_utils` | 数字解析工具 | 数字解析和标准化 |
|
|
|
|
|
|
|
|
-o工具模块(已迁移到 ocr_utils)⚠️
|
|
|
|
|
-输出工具已统一迁移到 ocr_utils 包,
|
|
|
|
|
|
|
+**导入示例**:
|
|
|
```python
|
|
```python
|
|
|
-# 从 ocr_utils 重新导出
|
|
|
|
|
|
|
+# 主要输出工具
|
|
|
from ocr_utils import (
|
|
from ocr_utils import (
|
|
|
- OutputFormatterV2, # 统一输出格式化器
|
|
|
|
|
- JSONFormatters, # JSON格式化
|
|
|
|
|
- MarkdownGenerator, # Markdown生成
|
|
|
|
|
- HTMLGenerator, # HTML生成
|
|
|
|
|
- VisualizationUtils, # 可视化工具
|
|
|
|
|
- normalize_financial_numbers, # 金额标准化
|
|
|
|
|
|
|
+ OutputFormatterV2, # 统一输出格式化器
|
|
|
|
|
+ JSONFormatters, # JSON格式化
|
|
|
|
|
+ MarkdownGenerator, # Markdown生成
|
|
|
|
|
+ HTMLGenerator, # HTML生成
|
|
|
|
|
+ VisualizationUtils, # 可视化工具
|
|
|
|
|
+ normalize_financial_numbers, # 金额标准化
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+# PDF 工具(延迟导入)
|
|
|
|
|
+from ocr_utils import PDFUtils, BBoxExtractor
|
|
|
|
|
+
|
|
|
|
|
+# 文件工具
|
|
|
|
|
+from ocr_utils import (
|
|
|
|
|
+ get_input_files,
|
|
|
|
|
+ convert_pdf_to_images,
|
|
|
|
|
+ parse_page_range
|
|
|
)
|
|
)
|
|
|
```
|
|
```
|
|
|
-优势:
|
|
|
|
|
- . 统一管理所有输出工具
|
|
|
|
|
- . 跨项目复用代码
|
|
|
|
|
- . 更好的版本控制
|
|
|
|
|
|
|
+
|
|
|
|
|
+**优势**:
|
|
|
|
|
+- ✅ **统一管理**:所有输出工具集中管理,避免代码重复
|
|
|
|
|
+- ✅ **跨项目复用**:可在多个 OCR 相关项目中复用
|
|
|
|
|
+- ✅ **版本控制**:独立版本管理,便于维护和升级
|
|
|
|
|
+- ✅ **延迟导入**:PDF 相关工具支持延迟导入,避免依赖问题
|
|
|
|
|
|
|
|
其他依赖
|
|
其他依赖
|
|
|
. transformers - Docling 模型加载
|
|
. transformers - Docling 模型加载
|