OvisOCR2 批量处理扫描PDF时如何保持版面顺序

文章导读
OvisOCR2 在处理批量扫描 PDF 时出现版面顺序错乱,通常不一定是模型本身不识别文字,而是调用方式没有区分“页面边界”和“版面阅读顺序”。整份 PDF 一次提交时,识别器容易把多页内容当成一个连续打印流,导致输出顺序和纸张阅读顺序不一致。解决思路可以放在三个层面:调用参数是否区分单页、分页策略是否保留页码、输出坐标是否参与排序。
📋 目录
  1. 用单页文档确认基础识别顺序
  2. 批量调用时逐页提交并记录页码
  3. 检查输出是否包含坐标信息
  4. 利用坐标或区块编号重排结果
  5. 用两份长文档验证最终顺序
A A

OvisOCR2 在处理批量扫描 PDF 时出现版面顺序错乱,通常不一定是模型本身不识别文字,而是调用方式没有区分“页面边界”和“版面阅读顺序”。整份 PDF 一次提交时,识别器容易把多页内容当成一个连续打印流,导致输出顺序和纸张阅读顺序不一致。解决思路可以放在三个层面:调用参数是否区分单页、分页策略是否保留页码、输出坐标是否参与排序。

若单页内区块顺序正确,错乱主要来自多页拼接。先逐页提交并记录页码,再检查输出是否携带坐标字段;若携带,按从上到下、从左到右的规则重排,最后用5页和10页的扫描PDF验证。此方法不依赖模型自带的顺序识别能力,只修正调用与排序流程。

用单页文档确认基础识别顺序

先准备一页上下左右有明显区块的扫描文档,比如左上角一个标题块,右上角一个日期块,左下角一段正文,右下角一个表格。调用OvisOCR2对这一页做识别,记录输出文本的顺序。按正常阅读顺序,输出顺序应该是左上→右上→左下→右下;如果输出顺序完全相反或随机,说明模型本身的区块顺序就不稳定,后续必须依赖坐标排序。

批量调用时逐页提交并记录页码

一次提交整份 PDF 时,模型会按打印顺序(即页面物理顺序)输出内容,但很多扫描 PDF 的页面内容是双栏、表格、跨页标题,打印顺序并不等于阅读顺序。为了避免这种拼接干扰,最直接的做法是先把 PDF 按页拆分,逐页调用 OvisOCR2,并将每一页的识别结果和页码一起保存。

OvisOCR2 批量处理扫描PDF时如何保持版面顺序
from PyPDF2 import PdfReader<br>import io<br><br>reader = PdfReader("scan.pdf")<br>page_results = []<br><br>for page_num, page in enumerate(reader.pages, start=1):<br>    # 将页面转换为图片字节流(具体转换方式取决于你的环境)<br>    page_bytes = page_to_image_bytes(page)  # 需自行实现<br>    result = ovis_ocr2_process(page_bytes)  # 替换为OvisOCR2实际调用<br>    page_results.append({<br>        "page": page_num,<br>        "content": result<br>    })

上述代码中 page_to_image_bytes 需要你根据实际渲染库补充,OvisOCR2 的调用参数也以你自己的 SDK 或 HTTP 接口为准。关键是:每一页独立提交,页码与结果绑定,为后续检查提供基础。

检查输出是否包含坐标信息

拿到一页的识别结果后,打印原始输出,观察是否包含坐标字段。坐标字段常见的名字有 bbox、left/top、width/height、x/y 轴数组,也可能在 OCR 返回的 paragraph 对象里。取值范围一般就是页面的像素坐标或 PDF 点坐标,例如左上角为 (0,0),宽度和高度在 0 到页面尺寸之间。如果输出只有纯文本,没有坐标信息,那么要在调用参数中尝试开启“带坐标输出”或“bounding box”选项,具体参数以实际 SDK 支持为准。

import json<br>print(json.dumps(result, ensure_ascii=False, indent=2))

利用坐标或区块编号重排结果

当输出块携带坐标时,可以按阅读顺序重新排序:通常阅读顺序是从上到下,每行从左到右。所以先按 Y 坐标从大到小排序(屏幕坐标 Y 轴向下,所以 Y 值小的在上),再把 Y 值相近的块按 X 坐标从小到大排序。这里需要定义一个“行”的容差,比如同一个标题行的 Y 坐标可能略有浮动。

OvisOCR2 批量处理扫描PDF时如何保持版面顺序
def sort_by_layout(blocks, y_tolerance=10):<br>    # blocks: [{"x": int, "y": int, "text": str}]<br>    blocks.sort(key=lambda b: b["y"])<br>    rows = []<br>    current_row = [blocks[0]]<br>    for b in blocks[1:]:<br>        if abs(b["y"] - current_row[0]["y"]) <= y_tolerance:<br>            current_row.append(b)<br>        else:<br>            rows.append(sorted(current_row, key=lambda b: b["x"]))<br>            current_row = [b]<br>    rows.append(sorted(current_row, key=lambda b: b["x"]))<br>    ordered = [b["text"] for row in rows for b in row]<br>    return "\n".join(ordered)

这个函数假设 blocks 非空,并且坐标键是 x 和 y,如果你的输出坐标字段名不同,需要同步改名。y_tolerance 根据实际行距调整,通常取 10 到 20 像素。

用两份长文档验证最终顺序

修改后的流程不能只在一页上有效,建议准备一份5页和一份10页的扫描PDF,分别跑通“逐页提交 → 坐标排序 → 按页拼接”的完整流程。逐页核对每一页的文本顺序是否与原文一致,重点看标题、表格、页脚是否错位。记录结果时可以做一个简单清单:每一页是否“顺序正确”,如果有错位,是发生在区块级还是行内。如果5页文档全部正确,10页文档出现跨页顺序错误,问题通常出在页码拼接,而不是坐标排序;如果单页内仍有错位,需要调整排序函数中的y_tolerance值。

OvisOCR2 批量处理扫描PDF时如何保持版面顺序

验证表格可以这样记录:

  • 5页文档:第1页顺序正确,第2页顺序正确,第3页顶部两行错位(行内顺序),第4页正确,第5页正确。
  • 10页文档:第1页正确,第2页正确,第3页正确,第4页表格列顺序错位(区块级),第5页正确,其余页面全部正确。

注意,以上仅是一个记录格式示例,不是固定出现的错误。最终以你实际跑出来的结果为准。若出现错误,回到前面的步骤确认是否每页都用了坐标排序,以及页码范围是否在拼接时被重新排序。