فهرست منبع

feat: 删除冗余的表格单元格匹配算法文档

zhch158_admin 3 روز پیش
والد
کامیت
b89aafdc08
1فایلهای تغییر یافته به همراه0 افزوده شده و 102 حذف شده
  1. 0 102
      merger/Tablecells匹配-全局动态规划.md

+ 0 - 102
merger/Tablecells匹配-全局动态规划.md

@@ -1,102 +0,0 @@
-基于您提供的 table_cell_matcher.py 代码,`_match_html_rows_to_paddle_groups` 方法实现了一个**全局动态规划 (Global Dynamic Programming)** 算法。
-
-这个算法的核心目标是解决两个序列(HTML 表格行序列 vs PaddleOCR 文本行序列)的**非线性对齐**问题。
-
-以下是该算法的详细原理解析:
-
-### 1. 核心思想:为什么用动态规划?
-
-传统的“贪婪算法”是逐行匹配,如果第 1 行匹配错了,第 2 行就会基于错误的位置继续找,导致“一步错,步步错”。
-
-**动态规划 (DP)** 的思想是:**不急着做决定**。它会计算所有可能的匹配路径的得分,最后回溯找出一条**总分最高**的路径。即使中间某一行匹配分值较低,只要它能让整体结构最合理,DP 就会选择它。
-
-### 2. 算法状态定义
-
-在代码中,`dp` 矩阵定义如下:
-
-*   **维度**:`dp[n_html][n_paddle]`
-*   **含义**:`dp[i][j]` 表示 **“HTML 的前 `i` 行”** 成功匹配到了 **“Paddle 的前 `j` 组”** 时,所能获得的**最大累计得分**。
-*   **值**:
-    *   `-inf` (负无穷):表示此状态不可达(例如 HTML 第 5 行不可能匹配到 Paddle 第 1 组,因为顺序不对)。
-    *   `float`:表示当前的累计相似度分数。
-
-### 3. 算法执行流程
-
-#### 第一步:预计算 (Pre-computation)
-为了性能,代码预先计算了 Paddle 组的合并文本。
-*   `merged_cache[(j, k)]`:存储从 Paddle 第 `j` 组开始,合并 `k` 个组后的文本。
-*   这避免了在多重循环中反复进行字符串拼接。
-
-#### 第二步:初始化 (Initialization)
-处理 HTML 的第 0 行 (`i=0`)。
-*   尝试将 HTML 第 0 行匹配 Paddle 的第 `0` 到 `SEARCH_WINDOW` 组。
-*   允许合并 `1` 到 `MAX_MERGE` (4) 个 Paddle 组。
-*   **得分计算**:`相似度 - 跳过惩罚`。
-*   如果得分有效,填入 `dp[0][end_j]`。
-
-#### 第三步:状态转移 (State Transition) - 核心循环
-这是算法最复杂的部分,遍历每一行 HTML (`i` 从 1 到 N)。对于当前行,有两种选择:
-
-**选择 A:跳过当前 HTML 行 (The "Skip" Strategy)**
-*   **场景**:HTML 有这一行,但 OCR 漏识别了,或者 OCR 顺序错乱导致当前位置找不到对应的 OCR 组。
-*   **逻辑**:直接继承上一行的最佳状态,但扣除 `SKIP_HTML_PENALTY`。
-*   **代码**:
-    ```python
-    score_skip = dp[i-1][prev_j] - SKIP_HTML_PENALTY
-    if score_skip > dp[i][prev_j]:
-        dp[i][prev_j] = score_skip
-        path[(i, prev_j)] = (prev_j, prev_j + 1) # 标记未消耗新组
-    ```
-*   **作用**:防止“链条断裂”。即使这一行匹配失败,状态也能传递给下一行。
-
-**选择 B:匹配 Paddle 组 (The "Match" Strategy)**
-*   **场景**:正常匹配。
-*   **逻辑**:
-    1.  找到上一行所有有效的结束位置 `prev_j`。
-    2.  **Gap (跳过)**:允许跳过中间的一些 Paddle 组(可能是噪音或页眉),即 `start_j = prev_j + 1 + gap`。
-    3.  **Merge (合并)**:尝试将 `start_j` 开始的 `1` 到 `4` 个 Paddle 组视为一行。
-    4.  **计算得分**:
-        $$Score = Similarity(HTML\_Text, Paddle\_Text) - Gap\_Penalty - Length\_Penalty$$
-    5.  **转移方程**:
-        $$dp[i][end\_j] = \max(dp[i][end\_j], \ dp[i-1][prev\_j] + Score)$$
-*   **代码**:
-    ```python
-    total_score = prev_score + current_score
-    if total_score > dp[i][end_j]:
-        dp[i][end_j] = total_score
-        path[(i, end_j)] = (prev_j, start_j) # 记录路径
-    ```
-
-#### 第四步:回溯 (Backtracking)
-当填满 `dp` 表后,我们需要找出最优路径:
-1.  **找终点**:在最后一行 HTML (`n_html-1`) 中找到得分最高的 `j`。如果最后一行没匹配上,就往前找倒数第二行,以此类推。
-2.  **倒推**:利用 `path` 字典,从终点一步步回到起点。
-    *   `path[(i, j)]` 存储了 `(prev_j, start_j)`。
-    *   如果 `start_j <= j`:说明 HTML 行 `i` 对应了 Paddle 组 `[start_j, ..., j]`。
-    *   如果 `start_j > j`:说明 HTML 行 `i` 被跳过了(对应空列表)。
-
-#### 第五步:孤儿挽救 (Orphan Rescue)
-DP 找的是“主干路径”,可能会漏掉一些没能进入最优路径的 Paddle 组(Orphans)。
-*   **逻辑**:遍历所有未使用的 Paddle 组,看它在物理位置上(Y坐标)离哪个已匹配的组最近(上方或下方)。
-*   **归属**:将其强行合并到最近的 HTML 行中。这解决了 OCR 过度切分导致的小碎片丢失问题。
-
-### 4. 关键参数解析
-
-*   **`MAX_MERGE = 4`**:
-    *   允许一行 HTML 对应最多 4 行 OCR 文本。解决 OCR 将长表格行切分成多行的问题。
-*   **`SEARCH_WINDOW = 15`**:
-    *   允许 OCR 结果相对于 HTML 出现较大的位移或中间插入了大量噪音(如印章干扰)。
-*   **`SKIP_HTML_PENALTY = 0.3`**:
-    *   这是您之前遇到问题的关键修复。允许算法以 0.3 分的代价放弃一行 HTML,从而保全后续的匹配。
-*   **`SKIP_PADDLE_PENALTY = 0.1`**:
-    *   允许跳过 OCR 中的噪音行,但跳过越多扣分越多,倾向于连续匹配。
-
-### 5. 总结
-
-这个算法将表格行匹配问题转化为了一个**寻找最大权值路径**的图论问题。
-
-*   **节点**:`(HTML行索引, Paddle组索引)`
-*   **边**:匹配操作(得分)或跳过操作(罚分)。
-*   **目标**:找到从第 0 行到第 N 行的总分最高路线。
-
-这种方法极其鲁棒,能够同时处理:OCR 分行、OCR 漏行、OCR 噪音、HTML 空行以及轻微的顺序错乱问题。