OCR 已返回文字和矩形坐标后,双栏文章如果只按 y 坐标排序,会变成“左第一行、右第一行、左第二行、右第二行”。下面用六个虚构文字框重建“先左栏,再右栏”的阅读顺序,并列出需要人工复核的版面情况。
准备与运行
本文只使用人工构造的教学材料,没有把示例结果当作真实项目效果。以下代码在 Windows 的 Python 3.11 独立环境执行通过。先在空目录运行安装命令,再将完整代码保存为 demo.py,执行 python demo.py。

python --version # 只用 Python 标准库
识别与排序是两个步骤
示例中的 text、left、top、width、height 是已存在的文字框结果,不会重新识别图片。Tesseract 可输出包含文本和位置字段的 TSV;代码为了让步骤独立可跑,直接使用六条人工构造框。框坐标必须来自同一页和相同尺度,旋转、页码、空框先处理。
先打印只按 top、left 排序的顺序,它会交错两栏。随后取文字框中心 x,找最大的横向空隙作为左右栏分界,再分别按 top 排序。对普通双栏且栏间距明显的页面,这能给出可检查的候选顺序。
用版面例外限制自动结论
若存在跨两栏标题、表格、图片说明或页脚,仅凭最大 x 空隙就可能误分组。代码只对纯双栏正文给出候选;真实页面要先识别版面区域,并把跨栏框和低置信框交给人工核对。
核对时读重建后的句子是否连贯,并与原图逐行比照。顺序正确也不表示 OCR 字符无错;错字、漏字和表格结构是另外的问题。本文不会还原表格单元格。
完整代码
boxes = [
{"id":"L1","text":"左栏第一行","left":10,"top":10,"width":80,"height":12},
{"id":"R1","text":"右栏第一行","left":300,"top":10,"width":80,"height":12},
{"id":"L2","text":"左栏第二行","left":10,"top":30,"width":80,"height":12},
{"id":"R2","text":"右栏第二行","left":300,"top":30,"width":80,"height":12},
{"id":"L3","text":"左栏第三行","left":10,"top":50,"width":80,"height":12},
{"id":"R3","text":"右栏第三行","left":300,"top":50,"width":80,"height":12},
]
naive = sorted(boxes,key=lambda b:(b["top"],b["left"]))
print("naive_order",[b["id"] for b in naive])
centers = sorted(set(b["left"] + b["width"]/2 for b in boxes))
gaps = [(centers[i+1]-centers[i],i) for i in range(len(centers)-1)]
gap,index = max(gaps)
split = (centers[index]+centers[index+1])/2
left = sorted((b for b in boxes if b["left"]+b["width"]/2 < split),key=lambda b:b["top"])
right = sorted((b for b in boxes if b["left"]+b["width"]/2 >= split),key=lambda b:b["top"])
ordered = left + right
print("column_gap",gap,"split_x",split)
print("reading_order",[b["id"] for b in ordered])
print("reading_text","。".join(b["text"] for b in ordered))
assert [b["id"] for b in ordered] == ["L1","L2","L3","R1","R2","R3"]
运行结果与核对
下面是上述脚本在本地执行得到的输出;正式数据请按相同检查点复核。
naive_order ['L1', 'R1', 'L2', 'R2', 'L3', 'R3']
column_gap 290.0 split_x 195.0
reading_order ['L1', 'L2', 'L3', 'R1', 'R2', 'R3']
reading_text 左栏第一行。左栏第二行。左栏第三行。右栏第一行。右栏第二行。右栏第三行
核对 naive_order 为左右交错,reading_order 为 L1、L2、L3、R1、R2、R3;再逐行对照原图。真实 OCR 导出若跨栏标题的中心落在分界附近,应先识别标题区并人工调整,不可直接信任该排序。
适用边界
六个文字框完全虚构,代码只处理两栏、方向正常、坐标稳定的纯文字排版。它没有运行 OCR、识别表格或处理多页版面;最大间隔并非通用版面分析算法。
常见问题
能把 Tesseract TSV 直接丢进这段代码吗?
需先按页、段落或行合并词框,去掉空文本,再映射 left、top、width、height 字段;跨栏标题和表格仍要单独处理。
参考资料
以下官方资料已于 2026 年 10 月 1 日核对,分别用于确认文中接口或方法定义。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/31742.html