登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

OCR 表格跨页时如何合并同一列字段

来源:17golang原创

时间:2026-09-15 06:14:16 145浏览 收藏

我第一次处理跨页 OCR 表格时,最容易误判的是“每一页识别得都对,合并后自然也会对”。实际情况正好相反:OCR 往往按页返回表格,下一页会重新识别表头,跨页的长文本还可能被切成两个单元格。要合并同一列字段,核心不是把两段字符串拼起来,而是先确认它们属于同一张表,再用稳定的列位和行关系重建记录。

可靠的做法是保留页码、行列坐标、单元格跨度和置信度;先做“同表判断”,再做列位归一化,最后过滤重复表头并对跨页断行做单独标记。
要点速览
  • 页面相邻不等于同一张表,表头签名和横向范围要一起判断。
  • 统一列位时使用列锚点,不要用每页 OCR 返回数组的下标硬拼。
  • 合并后检查列数、表头次数、行序和低置信度单元格。

为什么每页识别正确,合并后却会错列

表格识别结果通常带有页面归属和单元格几何信息。以常见布局接口为例,表格单元格会提供 rowIndex、columnIndex,有的还会提供 rowSpan、columnSpan。它们描述的是“本页表格中的位置”,不是整份 PDF 的全局行号。若直接把第 2 页的第 0 行接到第 1 页的最后一行,重复表头会被当成数据;若按数组顺序拼接,某个漏检单元格又会让后续列整体右移。

OCR 页面片段中的页码、重复表头、列锚点、跨页断行和单元格边界关系示意
图1:OCR 页面片段与跨页边界的静态关系示意,重点看重复表头和列锚点如何影响同一列判断。

先把每页结果整理成统一中间结构,至少保存这些字段:

字段作用缺失时的风险
page定位原始页无法回溯错位来源
rowIndex / columnIndex表达页内网格位置无法建立列位
rowSpan / columnSpan保留合并单元格语义长字段可能被错误拆散
bounding box比较横向范围与列锚点只能依赖脆弱的文本顺序

先判断下一页是不是同一张表

我会把“同表判断”单独做成一个结果,而不是在遍历页面时顺手决定。相邻页只是候选条件,至少再比较四项:列数量是否接近、表格左右边界是否接近、表头文本签名是否相同或为空、下一页顶部是否紧接上一页的表格区域。若页面中间出现新的标题、合计行或明显不同的列模式,就应该结束当前表。

重复表头不要简单按固定字符串删除。更稳的是把表头单元格归一化后生成签名,例如去空白、统一全角半角,再比较列位和文本。表头签名相同且位于下一页顶部时,标记为 repeat_header;签名不同但列锚点相同的行,可能是多级表头,应保留并交给业务规则判断。

先统一列位,再合并同一列字段

列位归一化的关键是“横向位置优先、页内索引兜底”。可以取第一页稳定表头或高置信度数据行的 x 中心点作为列锚点,然后将后续单元格分配到最近的锚点。分配时要设置最大距离;超过阈值的单元格不要强行塞进某列,而是进入待复核集合。

def merge_pages(page_tables, max_x_distance=24):
    # 先按页码保留表格边界,避免把不同表格直接串在一起。
    schema = build_column_schema(page_tables[0])
    merged_rows = []

    for table in page_tables:
        # 重复表头只跳过当前行,不删除正文中的同名字段。
        for row in table.rows:
            if is_repeated_header(row, schema):
                continue

            # 依据单元格中心点映射到统一列位,不能只使用 columnIndex。
            cells = map_cells_to_schema(row.cells, schema, max_x_distance)
            if cells.unmatched:
                # 记录页码和原坐标,留给人工或规则二次判断。
                row.review_reason = "column-anchor-mismatch"
            merged_rows.append(cells)

    # 只在列数、表头次数和行序检查通过后输出业务记录。
    return validate_and_mark(merged_rows, schema)
统一表格域中列模式、行记录、单元格跨度与校验清单的 OCR 跨页合并关系示意
图2:统一表格域的静态数据结构示意,展示列位归一化后如何承接跨页行并保留跨度信息。

跨页断行要和普通新行区分开。可以使用“上一页最后一行的目标列未闭合、下一页首行横向位置匹配、两段文本拼接后符合字段类型”三个信号。只有满足规则时才合并文本,并保留 continued_from_page 之类的来源标记;金额、日期和编号字段不要因为看起来能拼接就自动合并。

合并结果怎样验证

验证不需要重新识别整份文件,抽取跨页边界附近的样本即可。第一项检查每条记录的列数是否等于统一列模式;第二项统计重复表头是否只出现在页面顶部且未进入数据;第三项比较页末和页首的行序,确认没有跳行或重复;第四项检查低置信度与未匹配列,确保它们被标记而不是静默丢失。

如果使用支持表格结构的文档 AI 服务,还要确认返回的是结构化单元格而不是只有纯文本。服务文档通常会明确页面、表格、单元格及跨度字段的层级;跨页表格是否自动聚合则取决于具体模型,不能把某一产品的行为当成通用 OCR 规则。

常见问题

只比较相邻页可以吗?

不建议。中间可能插入脚注、合计页或新的表格;相邻关系只能生成候选,列模式和表头签名才是主要证据。

没有 bounding box 还能合并吗?

可以先用 columnIndex 和表头文本做保守合并,但要把置信度降级。没有几何信息时,不应自动处理列数变化和复杂合并单元格。

重复表头应该全部删除吗?

只删除被判定为页面续表表头的行。多级表头、业务字段名和正文中恰好相同的文本,应保留原始行并交给规则判断。

跨页 OCR 的难点不在“把文本拼到一起”,而在保存页面证据后重建表格语义。把同表判断、列位归一化、断行处理和结果校验拆开,后续换 OCR 引擎时也只需要适配输入层。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>