如何实现sort_contours函数从右到左排序及多行文本读取?
解决方案:支持多行+右到左排序的sort_contours函数
原函数仅支持单一轴的排序逻辑,无法适配多行文本场景。要实现多行文本的右到左排序,需要先按行分组轮廓,再在每行内执行右到左排序,具体修改如下:
修改后的函数代码
import cv2 import numpy as np def sort_contours(cnts, method="right-to-left", multi_line=True, line_threshold_ratio=0.5): try: # 获取所有轮廓的外接矩形 boundingBoxes = [cv2.boundingRect(c) for c in cnts] # 先按y轴坐标排序,为行分组做准备 cnts_boxes_sorted_y = sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][1]) if not multi_line: # 不启用多行模式,沿用原单一维度排序逻辑 reverse = False i = 0 if method == "right-to-left" or method == "bottom-to-top": reverse = True if method == "top-to-bottom" or method == "bottom-to-top": i = 1 cnts_sorted, boxes_sorted = zip(*sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][i], reverse=reverse)) return cnts_sorted, boxes_sorted # 多行模式:先分组行,再每行内排序 grouped_rows = [] current_row = [cnts_boxes_sorted_y[0]] # 计算所有轮廓的平均高度,作为行分组的阈值依据 avg_height = np.mean([box[3] for _, box in cnts_boxes_sorted_y]) line_threshold = avg_height * line_threshold_ratio for cb in cnts_boxes_sorted_y[1:]: current_box = cb[1] prev_box = current_row[-1][1] # 通过y坐标差判断是否属于同一行 if abs(current_box[1] - prev_box[1]) < line_threshold: current_row.append(cb) else: grouped_rows.append(current_row) current_row = [cb] grouped_rows.append(current_row) # 对每行内的轮廓按指定方法排序 sorted_cnts = [] sorted_boxes = [] for row in grouped_rows: if method == "right-to-left": # 按x坐标降序实现右到左排序 row_sorted = sorted(row, key=lambda b: b[1][0], reverse=True) elif method == "left-to-right": row_sorted = sorted(row, key=lambda b: b[1][0]) elif method == "top-to-bottom": row_sorted = sorted(row, key=lambda b: b[1][1]) elif method == "bottom-to-top": row_sorted = sorted(row, key=lambda b: b[1][1], reverse=True) else: row_sorted = row cnts_row, boxes_row = zip(*row_sorted) sorted_cnts.extend(cnts_row) sorted_boxes.extend(boxes_row) return tuple(sorted_cnts), tuple(sorted_boxes) except Exception as e: print(f"Error: {str(e)}") return cnts, boundingBoxes
关键逻辑说明
- 行分组:通过计算轮廓外接矩形的y坐标差,结合平均高度的比例阈值,将同一行的轮廓归为一组,避免不同行的轮廓被错误排序。
- 多行内排序:对每个行组单独执行指定的排序方法,保证每行的文本顺序符合需求。
- 兼容原有功能:保留
multi_line参数,设为False时可回到原函数的单一轴排序逻辑,不影响原有代码的其他调用场景。
调用方式
保持原有调用形式即可,多行处理默认开启:
cnts, boundingBoxes_sorted = sort_contours(cnts, method="right-to-left") # 若需关闭多行模式,可显式指定 # cnts, boundingBoxes_sorted = sort_contours(cnts, method="right-to-left", multi_line=False)
注意事项
- 若行分组效果不佳,可调整
line_threshold_ratio参数(默认0.5):增大该值可将y坐标差更大的轮廓归为同一行,反之则分组更严格。 - 函数仅调整轮廓的排序顺序,不会修改轮廓本身,不会影响后续预测结果。
内容的提问来源于stack exchange,提问作者jumanah mutahhar
相关产品推荐
相关产品推荐

