# Layout后处理：大面积文本块转表格

## 📋 功能说明

当Layout检测将大面积的表格区域误识别为文本框时，可以通过后处理自动将其转换为表格类型。

## 🎯 使用场景

### 典型问题

从 `page_022.json` 可以看到：
- 一个很大的文本框（bbox: [226, 288, 1495, 1685]）
- 包含了多个表格的内容（账龄分析、主要单位往来、存货等）
- 但被识别为 `type: "text"`，而不是 `type: "table"`

### 解决方案

通过后处理规则，自动将满足条件的大文本块转换为表格：
- ✅ 面积占比超过阈值（默认25%）
- ✅ 宽度和高度都超过一定比例（避免细长条）
- ✅ 页面中没有其他表格（避免误判）

## ⚙️ 配置选项

### 配置文件示例

```yaml
# layout后处理配置
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%）
```

### 参数说明

| 参数 | 类型 | 默认值 | 说明 |
|-----|------|--------|------|
| `convert_large_text_to_table` | bool | `true` | 是否启用文本转表格功能 |
| `min_text_area_ratio` | float | `0.25` | 最小面积占比（0-1），文本块面积需占页面25%以上 |
| `min_text_width_ratio` | float | `0.4` | 最小宽度占比（0-1），文本块宽度需占页面40%以上 |
| `min_text_height_ratio` | float | `0.3` | 最小高度占比（0-1），文本块高度需占页面30%以上 |

## 🔍 判断规则

### 1. 面积占比判断

```python
area_ratio = text_block_area / page_area
if area_ratio >= min_text_area_ratio:  # 默认 >= 0.25
    # 满足面积条件
```

**示例**：
- 页面尺寸：2338 × 1654 = 3,867,052 像素²
- 文本块：1207 × 1397 = 1,686,179 像素²
- 面积占比：1,686,179 / 3,867,052 = **43.6%** ✅ 满足条件

### 2. 尺寸比例判断

```python
width_ratio = text_block_width / page_width
height_ratio = text_block_height / page_height

if (width_ratio >= min_text_width_ratio and 
    height_ratio >= min_text_height_ratio):
    # 满足尺寸条件
```

**示例**：
- 页面宽度：1654px，文本块宽度：1269px → 宽度占比：**76.7%** ✅
- 页面高度：2338px，文本块高度：1397px → 高度占比：**59.8%** ✅

### 3. 表格冲突检查

```python
has_table = any(
    item.get('category', '').lower() in ['table', 'table_body']
    for item in layout_results
)

if has_table:
    # 页面已有表格，不进行转换（避免误判）
    return layout_results
```

**逻辑**：
- 如果页面中已经有表格元素，说明Layout检测正常工作
- 此时不进行转换，避免将普通文本误判为表格

## 📊 转换效果

### 转换前

```json
{
  "bbox": [226, 288, 1495, 1685],
  "category": "text",
  "text": "1、账龄分析\n账龄 期末余额\n1年以内 178,051,695.35\n..."
}
```

### 转换后

```json
{
  "bbox": [226, 288, 1495, 1685],
  "category": "table",
  "original_category": "text",  // 保留原始类别
  "text": "1、账龄分析\n账龄 期末余额\n1年以内 178,051,695.35\n..."
}
```

## 🎯 调优建议

### 场景1：财务报表（多表格）

```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%高度
```

### 场景2：密集表格（小表格多）

```yaml
layout:
  convert_large_text_to_table: true
  min_text_area_ratio: 0.15      # 降低到15%（更敏感）
  min_text_width_ratio: 0.3      # 降低到30%
  min_text_height_ratio: 0.2     # 降低到20%
```

### 场景3：宽松检测（避免误判）

```yaml
layout:
  convert_large_text_to_table: true
  min_text_area_ratio: 0.35      # 提高到35%（更严格）
  min_text_width_ratio: 0.5      # 提高到50%
  min_text_height_ratio: 0.4     # 提高到40%
```

### 场景4：关闭功能

```yaml
layout:
  convert_large_text_to_table: false  # 完全关闭
```

## ⚠️ 注意事项

### 1. **误判风险**

- **风险**：可能将大段普通文本误判为表格
- **缓解**：通过面积和尺寸比例阈值控制
- **建议**：根据实际文档类型调整阈值

### 2. **已有表格检查**

- **逻辑**：如果页面已有表格，不进行转换
- **原因**：说明Layout检测正常工作，不需要后处理
- **例外**：如果Layout检测完全失败，可能无法检测到表格

### 3. **转换时机**

- **位置**：在Layout检测之后，元素分类之前
- **顺序**：
  1. Layout检测
  2. 重叠框去重
  3. **文本转表格（后处理）** ← 这里
  4. 元素分类
  5. 元素处理

### 4. **保留原始信息**

- 转换后的元素会保留 `original_category` 字段
- 便于调试和追溯转换历史

## 🔧 代码实现

### 核心函数

```python
@staticmethod
def convert_large_text_to_table(
    layout_results: List[Dict[str, Any]],
    image_shape: Tuple[int, int],
    min_area_ratio: float = 0.25,
    min_width_ratio: float = 0.4,
    min_height_ratio: float = 0.3
) -> List[Dict[str, Any]]:
    """
    将大面积的文本块转换为表格
    
    判断规则：
    1. 面积占比：占页面面积超过 min_area_ratio（默认25%）
    2. 尺寸比例：宽度和高度都超过一定比例（避免细长条）
    3. 不与其他表格重叠：如果已有表格，不转换
    """
    # 实现逻辑...
```

### 调用位置

```python
# 在 pipeline_manager_v2.py 中
# 2.6 将大面积文本块转换为表格（后处理）
if layout_results:
    convert_large_text = self.config.get('layout', {}).get('convert_large_text_to_table', True)
    if convert_large_text:
        image_shape = (detection_image.shape[0], detection_image.shape[1])
        layout_results = LayoutUtils.convert_large_text_to_table(
            layout_results,
            image_shape,
            min_area_ratio=self.config.get('layout', {}).get('min_text_area_ratio', 0.25),
            min_width_ratio=self.config.get('layout', {}).get('min_text_width_ratio', 0.4),
            min_height_ratio=self.config.get('layout', {}).get('min_text_height_ratio', 0.3)
        )
```

## 📈 效果评估

### 转换前的问题

- ❌ 大表格被识别为文本
- ❌ 无法使用VLM进行表格结构识别
- ❌ 表格内容无法正确提取

### 转换后的改进

- ✅ 大表格被正确识别为表格类型
- ✅ 可以使用VLM进行表格结构识别
- ✅ 表格内容可以正确提取和处理

## 🎯 最佳实践

1. **默认启用**：对于财务报表等包含大表格的文档，建议启用
2. **阈值调优**：根据实际文档类型调整阈值
3. **监控日志**：查看转换日志，确认转换效果
4. **验证结果**：检查转换后的表格是否正确处理

## 📝 日志输出

转换时会输出详细日志：

```
🔄 Converted large text block to table: area=43.6%, size=76.7%×59.8%, bbox=[226, 288, 1495, 1685]
✅ Converted 1 large text block(s) to table(s)
```

## 🔄 与其他功能的关系

### 与VLM表格识别

- 转换后的表格会进入VLM处理流程
- VLM会识别表格结构（HTML格式）
- OCR会提取单元格文本和坐标

### 与跨页表格合并

- 转换后的表格可以参与跨页合并
- 需要确保转换后的表格类型正确

### 与元素分类

- 转换在元素分类之前进行
- 转换后的表格会被正确分类到 `TABLE_BODY_CATEGORIES`

## 📚 相关文档

- [模型统一框架.md](./模型统一框架.md) - 整体架构说明
- [OCR识别差异分析与改进方案.md](./OCR识别差异分析与改进方案.md) - OCR优化说明

