|
|
@@ -0,0 +1,79 @@
|
|
|
+
|
|
|
+## 产生空行/空列的情况
|
|
|
+```@ocr_platform/ocr_tools/universal_doc_parser/models/adapters/wired_table/grid_recovery.py:466 recover_grid_structure什么情况会产生空行或空列?
|
|
|
+```
|
|
|
+
|
|
|
+### 1. 网格线检测产生的额外分割线
|
|
|
+```352:380:ocr_platform/ocr_tools/universal_doc_parser/models/adapters/wired_table/grid_recovery.py
|
|
|
+ def recover_grid_structure(bboxes: List[List[float]]) -> List[Dict]:
|
|
|
+ # ...
|
|
|
+ # 1. 识别行分割线 (Y轴)
|
|
|
+ y_coords = []
|
|
|
+ for b in bboxes:
|
|
|
+ y_coords.append(b[1]) # top
|
|
|
+ y_coords.append(b[3]) # bottom
|
|
|
+
|
|
|
+ row_dividers = GridRecovery.find_grid_lines(y_coords, tolerance=5, min_support=2)
|
|
|
+```
|
|
|
+
|
|
|
+- 问题:`find_grid_lines` 收集所有单元格的 top/bottom(或 left/right)坐标,聚类后生成网格线。
|
|
|
+- 如果某些位置有 ≥2 个坐标对齐(满足 `min_support=2`),就会产生一条网格线。
|
|
|
+- 结果:可能产生比实际行/列更多的网格线,从而产生空的行区间或列区间。
|
|
|
+
|
|
|
+### 2. 单元格匹配时未覆盖某些行/列区间
|
|
|
+```411:428:ocr_platform/ocr_tools/universal_doc_parser/models/adapters/wired_table/grid_recovery.py
|
|
|
+ # 匹配行
|
|
|
+ matched_rows = []
|
|
|
+ for r in row_intervals:
|
|
|
+ inter_top = max(b_top, r["top"])
|
|
|
+ inter_bottom = min(b_bottom, r["bottom"])
|
|
|
+ inter_h = max(0, inter_bottom - inter_top)
|
|
|
+
|
|
|
+ if r["height"] > 0 and (inter_h / r["height"] > 0.5 or inter_h / b_h > 0.5):
|
|
|
+ matched_rows.append(r["index"])
|
|
|
+```
|
|
|
+
|
|
|
+- 问题:匹配条件为 `inter_h / r["height"] > 0.5` 或 `inter_h / b_h > 0.5`。
|
|
|
+- 如果某个行/列区间很小,且没有单元格满足该条件,该区间就不会被匹配。
|
|
|
+- 结果:该行/列区间没有单元格的起始位置,成为空行/空列。
|
|
|
+
|
|
|
+### 3. rowspan/colspan 跨越的间隙行/列
|
|
|
+```500:504:ocr_platform/ocr_tools/universal_doc_parser/models/adapters/wired_table/grid_recovery.py
|
|
|
+ for cell in cells:
|
|
|
+ if cell["row"] < max_row:
|
|
|
+ row_occupied[cell["row"]] = True # 只标记起始行
|
|
|
+ if cell["col"] < max_col:
|
|
|
+ col_occupied[cell["col"]] = True # 只标记起始列
|
|
|
+```
|
|
|
+
|
|
|
+- 问题:`compress_grid` 只标记单元格的起始行/列(`cell["row"]` 和 `cell["col"]`)。
|
|
|
+- 如果一个单元格跨越多个行/列(rowspan/colspan > 1),中间的行/列如果没有其他单元格起始,就不会被标记为占用。
|
|
|
+- 结果:这些中间行/列成为空行/空列。
|
|
|
+
|
|
|
+### 4. 表格边缘的额外网格线
|
|
|
+- 如果表格边缘的单元格边界对齐形成网格线,但该行/列区间内没有单元格,也会产生空行/空列。
|
|
|
+
|
|
|
+## 示例场景
|
|
|
+
|
|
|
+假设有以下单元格:
|
|
|
+- Cell A: row=0, rowspan=3(跨越行 0, 1, 2)
|
|
|
+- Cell B: row=3, rowspan=1(只在行 3)
|
|
|
+
|
|
|
+如果网格线检测产生了行 0, 1, 2, 3, 4 的分割线:
|
|
|
+- 行 0: 被 Cell A 占用(起始)
|
|
|
+- 行 1: 被 Cell A 跨越,但没有单元格起始 → 空行
|
|
|
+- 行 2: 被 Cell A 跨越,但没有单元格起始 → 空行
|
|
|
+- 行 3: 被 Cell B 占用(起始)
|
|
|
+- 行 4: 没有单元格 → 空行
|
|
|
+
|
|
|
+`compress_grid` 会移除这些空行,最终得到紧凑的网格。
|
|
|
+
|
|
|
+## 总结
|
|
|
+
|
|
|
+空行/空列主要来自:
|
|
|
+1. 网格线检测产生的额外分割线
|
|
|
+2. 单元格匹配条件未覆盖某些区间
|
|
|
+3. rowspan/colspan 跨越的中间行/列
|
|
|
+4. 表格边缘的额外网格线
|
|
|
+
|
|
|
+`compress_grid` 会移除这些空行/空列,确保最终网格紧凑。
|