unet表格识别-grid_recovery.md 3.5 KB

产生空行/空列的情况

1. 网格线检测产生的额外分割线

    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. 单元格匹配时未覆盖某些行/列区间

            # 匹配行
            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.5inter_h / b_h > 0.5
  • 如果某个行/列区间很小,且没有单元格满足该条件,该区间就不会被匹配。
  • 结果:该行/列区间没有单元格的起始位置,成为空行/空列。

3. rowspan/colspan 跨越的间隙行/列

        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 会移除这些空行/空列,确保最终网格紧凑。