OvisOCR2 在处理批量扫描 PDF 时出现版面顺序错乱,通常不一定是模型本身不识别文字,而是调用方式没有区分“页面边界”和“版面阅读顺序”。整份 PDF 一次提交时,识别器容易把多页内容当成一个连续打印流,导致输出顺序和纸张阅读顺序不一致。解决思路可以放在三个层面:调用参数是否区分单页、分页策略是否保留页码、输出坐标是否参与排序。
若单页内区块顺序正确,错乱主要来自多页拼接。先逐页提交并记录页码,再检查输出是否携带坐标字段;若携带,按从上到下、从左到右的规则重排,最后用5页和10页的扫描PDF验证。此方法不依赖模型自带的顺序识别能力,只修正调用与排序流程。
用单页文档确认基础识别顺序
先准备一页上下左右有明显区块的扫描文档,比如左上角一个标题块,右上角一个日期块,左下角一段正文,右下角一个表格。调用OvisOCR2对这一页做识别,记录输出文本的顺序。按正常阅读顺序,输出顺序应该是左上→右上→左下→右下;如果输出顺序完全相反或随机,说明模型本身的区块顺序就不稳定,后续必须依赖坐标排序。
批量调用时逐页提交并记录页码
一次提交整份 PDF 时,模型会按打印顺序(即页面物理顺序)输出内容,但很多扫描 PDF 的页面内容是双栏、表格、跨页标题,打印顺序并不等于阅读顺序。为了避免这种拼接干扰,最直接的做法是先把 PDF 按页拆分,逐页调用 OvisOCR2,并将每一页的识别结果和页码一起保存。
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 坐标可能略有浮动。
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值。
验证表格可以这样记录:
- 5页文档:第1页顺序正确,第2页顺序正确,第3页顶部两行错位(行内顺序),第4页正确,第5页正确。
- 10页文档:第1页正确,第2页正确,第3页正确,第4页表格列顺序错位(区块级),第5页正确,其余页面全部正确。
注意,以上仅是一个记录格式示例,不是固定出现的错误。最终以你实际跑出来的结果为准。若出现错误,回到前面的步骤确认是否每页都用了坐标排序,以及页码范围是否在拼接时被重新排序。