Files
OCR/openspec/changes/extract-table-cell-boxes/specs/ocr-processing/spec.md
egg 801ee9c4b6 feat: create extract-table-cell-boxes proposal and archive old proposal
- Archive unify-image-scaling proposal to archive/2025-11-28
- Create new extract-table-cell-boxes proposal for supplementing PPStructureV3
  with direct SLANeXt model calls to extract table cell bounding boxes
- Add debug logging to pp_structure_enhanced.py for table cell boxes investigation
- Discovered that PPStructureV3 high-level API filters out cell bbox data,
  but paddlex.create_model() can directly invoke underlying models

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 12:15:06 +08:00

133 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Spec: OCR Processing - Table Cell Boxes Extraction
## Overview
在 OCR Track 處理表格時,補充調用 PaddleX 底層 SLANeXt 模型,獲取每個 cell 的座標信息。
## Requirements
### 1. 模型管理
#### 1.1 模型緩存
```python
class PPStructureEnhanced:
def __init__(self, structure_engine):
self.structure_engine = structure_engine
# 底層模型緩存
self._table_cls_model = None
self._wired_table_model = None
self._wireless_table_model = None
```
#### 1.2 延遲載入
- 模型只在首次需要時載入
- 使用 `paddlex.create_model()` API
- 模型配置從 settings 讀取
### 2. Cell Boxes 提取流程
#### 2.1 處理條件
`mapped_type == ElementType.TABLE` 且有有效的 `block_bbox` 時觸發。
#### 2.2 處理步驟
```
1. 裁切表格圖片
- 從原始圖片中根據 block_bbox 裁切
- 確保邊界不超出圖片範圍
2. 判斷表格類型 (可選)
- 調用 PP-LCNet_x1_0_table_cls
- 獲取 wired/wireless 分類結果
- 或直接使用 PPStructureV3 內部的分類結果
3. 調用對應 SLANeXt 模型
- wired → SLANeXt_wired
- wireless → SLANeXt_wireless
4. 提取 cell boxes
- 從 result.json['res']['bbox'] 獲取
- 格式: [[x1,y1,x2,y2,x3,y3,x4,y4], ...]
5. 座標轉換
- 將相對座標轉為全域座標
- global_box = [box[i] + offset for each point]
- offset = (table_x, table_y) from block_bbox
6. 存入 element
- element['cell_boxes'] = processed_boxes
- element['cell_boxes_format'] = 'polygon_8'
```
### 3. 數據格式
#### 3.1 Cell Boxes 結構
```python
element = {
'element_id': 'pp3_0_3',
'type': ElementType.TABLE,
'bbox': [84, 269, 1174, 1508], # 表格整體 bbox
'content': '<html>...</html>', # HTML 內容
'cell_boxes': [ # 新增cell 座標
[95, 273, 776, 274, 759, 326, 94, 325], # cell 0 (全域座標)
[119, 296, 575, 295, 560, 399, 117, 401], # cell 1
# ...
],
'cell_boxes_format': 'polygon_8', # 座標格式說明
'table_type': 'wired', # 可選:表格類型
}
```
#### 3.2 座標格式
- `polygon_8`: 8 點多邊形 `[x1,y1,x2,y2,x3,y3,x4,y4]`
- 順序:左上 → 右上 → 右下 → 左下
### 4. 錯誤處理
#### 4.1 失敗情況
- 模型載入失敗
- 圖片裁切失敗
- 預測返回空結果
#### 4.2 處理方式
- 記錄警告日誌
- 繼續處理element 不包含 cell_boxes
- 不影響原有 HTML 提取流程
### 5. 配置項
```python
# config.py
class Settings:
# 是否啟用 cell boxes 提取
enable_table_cell_boxes_extraction: bool = True
# 表格結構識別模型 (已存在)
wired_table_model_name: str = "SLANeXt_wired"
wireless_table_model_name: str = "SLANeXt_wireless"
```
## Implementation Notes
### 模型共享
PPStructureV3 內部已載入了這些模型,但高層 API 不暴露。
直接使用 `paddlex.create_model()` 會重新載入模型。
考慮是否可以訪問 PPStructureV3 內部的模型實例(經測試:不可行)。
### 性能優化
- 模型實例緩存在 PPStructureEnhanced 中
- 避免每次處理表格都重新載入模型
- 考慮在內存緊張時釋放緩存
### 座標縮放
如果圖片在 Layout 分析前經過縮放ScalingInfo
cell boxes 座標也需要相應縮放回原始座標系。
## Test Cases
1. **有線表格**:確認 cell boxes 提取正確
2. **無線表格**:確認模型選擇和提取正確
3. **複雜表格**:跨行跨列的表格
4. **小表格**cell 數量少的簡單表格
5. **錯誤處理**:無效 bbox、模型失敗等情況