You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现2D平面页面OCR识别框从上到下、从左到右排序

OCR识别框从上到下、从左到右排序实现方案

坐标预处理

首先基于每个识别框的四个顶点坐标,计算三个核心特征值,避免原始顶点顺序混乱带来的计算误差:

  • 垂直中心坐标y_center:四个顶点y坐标的平均值,用来表征识别框的垂直位置
  • 左边界坐标x_left:四个顶点x坐标的最小值,用来表征识别框的水平位置
  • 框高度box_h:四个顶点y坐标的最大值减最小值,用来判断多个识别框是否属于同一行

分组逻辑(识别同属一行的识别框)

横版文档场景下,同一行的识别框垂直中心差异不会超过行高的一半,可按以下步骤分组:

  1. 先将所有识别框按y_center从小到大做初步排序
  2. 初始化第一个行分组,把排序后的第一个识别框放入分组,记录当前行的基准垂直中心为该框的y_center,同时记录当前行的平均高度
  3. 遍历剩下的识别框:
    • 若当前框的y_center与当前行基准垂直中心的差值小于当前行平均高度的1/2(阈值可根据文档倾斜程度微调,倾斜越大阈值可适当上调),则将其归入当前行,同时更新当前行的平均高度
    • 若差值超过阈值,则新建一个行分组,将当前框放入新分组,更新当前行基准和平均高度

最终排序

  1. 所有行分组按行基准垂直中心从小到大排序,实现从上到下的顺序
  2. 每个行分组内的识别框按x_left从小到大排序,实现同一行从左到右的顺序
  3. 按行顺序拼接所有行内的识别框,即可得到符合阅读顺序的识别框序列

Python 实现示例

def sort_ocr_boxes(boxes):
    # boxes输入格式: 每个元素为四个顶点的(x,y)列表,形如[[x1,y1],[x2,y2],[x3,y3],[x4,y4]]
    processed_boxes = []
    for box in boxes:
        xs = [p[0] for p in box]
        ys = [p[1] for p in box]
        y_center = sum(ys)/4
        x_left = min(xs)
        box_h = max(ys) - min(ys)
        processed_boxes.append((y_center, x_left, box_h, box))
    
    # 初步按垂直中心排序
    processed_boxes.sort(key=lambda x: x[0])
    
    # 分组
    rows = []
    current_row = [processed_boxes[0]]
    for box in processed_boxes[1:]:
        current_avg_h = sum([b[2] for b in current_row])/len(current_row)
        if abs(box[0] - current_row[0][0]) < current_avg_h * 0.5:
            current_row.append(box)
        else:
            rows.append(current_row)
            current_row = [box]
    rows.append(current_row)
    
    # 行内排序+结果拼接
    sorted_result = []
    for row in rows:
        row.sort(key=lambda x: x[1])
        sorted_result.extend([b[3] for b in row])
    return sorted_result

该方案适配常规横版印刷文档、带轻微倾斜的扫描文档、混合图文文档三类常见OCR场景,可根据实际业务需求调整同一行判断的阈值系数。

内容的提问来源于stack exchange,提问作者Syed Abdul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 12:39:02