Python实现2D平面页面OCR识别框从上到下、从左到右排序
OCR识别框从上到下、从左到右排序实现方案
坐标预处理
首先基于每个识别框的四个顶点坐标,计算三个核心特征值,避免原始顶点顺序混乱带来的计算误差:
- 垂直中心坐标
y_center:四个顶点y坐标的平均值,用来表征识别框的垂直位置 - 左边界坐标
x_left:四个顶点x坐标的最小值,用来表征识别框的水平位置 - 框高度
box_h:四个顶点y坐标的最大值减最小值,用来判断多个识别框是否属于同一行
分组逻辑(识别同属一行的识别框)
横版文档场景下,同一行的识别框垂直中心差异不会超过行高的一半,可按以下步骤分组:
- 先将所有识别框按
y_center从小到大做初步排序 - 初始化第一个行分组,把排序后的第一个识别框放入分组,记录当前行的基准垂直中心为该框的
y_center,同时记录当前行的平均高度 - 遍历剩下的识别框:
- 若当前框的
y_center与当前行基准垂直中心的差值小于当前行平均高度的1/2(阈值可根据文档倾斜程度微调,倾斜越大阈值可适当上调),则将其归入当前行,同时更新当前行的平均高度 - 若差值超过阈值,则新建一个行分组,将当前框放入新分组,更新当前行基准和平均高度
- 若当前框的
最终排序
- 所有行分组按行基准垂直中心从小到大排序,实现从上到下的顺序
- 每个行分组内的识别框按
x_left从小到大排序,实现同一行从左到右的顺序 - 按行顺序拼接所有行内的识别框,即可得到符合阅读顺序的识别框序列
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
相关产品推荐
相关产品推荐

