如何基于真实自然阅读顺序对OCR识别的bbox进行排序?
基于Bounding Box的OCR文本自然阅读顺序排序方案
问题背景
- 已完成文档OCR识别,获得每个单词的bbox坐标(x0、y0、x1、y1)及单词内容
- OCR默认按创作者预期的“左上到右下”顺序返回结果,但存在两类排序错误:
- 多列文本被拆分为独立块:比如两列事件列表,本该按「年份→对应条目」的逻辑顺序(如1999 → Item 1 → 2000 → Item 2...)返回,但实际会把年份列和条目列分开,返回顺序变成所有年份在前、所有条目在后,完全打乱逻辑
- 倾斜文档排序失效:默认规则认为bbox位置越高(y值越小)越靠前,若文档逆时针倾斜,一行末尾的单词y值会比开头单词更小,导致被错误排到该行最前面
现有尝试与局限
- 曾尝试计算每个bbox到文档中点的距离作为排序指标,不仅效果差,逻辑也过于复杂
- 可行思路:通过bbox推断文本行(设置阈值适配倾斜文本),将每个bbox分配到对应行后,再按x轴位置从左到右排序,但尚未实现
- 架构限制:无法在解析前对文档进行去倾斜处理,只能通过已有的bbox信息完成排序推断
当前代码
def read_pdf(source_path: str, **kw) -> dict: pages = fitz.open(source_path) data = {} for page_number, page in enumerate(tqdm(pages), start=1): text_blocks = page.get_text('words') data[page_number] = text_blocks return data def calculate_distances_to_order_bboxes(document: list) -> dict: min_x, min_y = min([min(bbox[0], bbox[2]) for bbox in document]), min([min(bbox[1], bbox[3]) for bbox in document]) max_x, max_y = max([max(bbox[0], bbox[2]) for bbox in document]), max([max(bbox[1], bbox[3]) for bbox in document]) document_mid_point_x, document_mid_point_y = (min_x + max_x) / 2, (min_y + max_y) / 2 calculations_dict = {} enum_id = 0 multiplier = 1 for x0, y0, x1, y1, word, block_no, line_no, word_no in document: bbox_mid_x, bbox_mid_y = (x0 + x1) / 2, (y0 + y1) / 2 dist_to_mid_x, dist_to_mid_y = document_mid_point_x - bbox_mid_x, document_mid_point_y - bbox_mid_y if dist_to_mid_x < 0: multiplier += 0.2 if dist_to_mid_y < 0: multiplier += 1 dist_to_mid = (sqrt(dist_to_mid_x**2 + dist_to_mid_y**2)) * multiplier calculations_dict[enum_id] = { 'word': word, 'x0': x0, 'y0': y0, 'x1': x1, 'y1': y1, 'bbox_mid_x': bbox_mid_x, 'bbox_mid_y': bbox_mid_y, 'dist_to_mid_x': dist_to_mid_x, 'dist_to_mid_y': dist_to_mid_y, 'dist_to_mid': dist_to_mid } enum_id += 1 return calculations_dict import fitz from tqdm import tqdm from math import sqrt data = read_pdf(source_path_to_pdf) document = data[0] calculations_dict = calculate_distances_to_order_bboxes(document)
内容的提问来源于stack exchange,提问作者qoob
相关产品推荐
相关产品推荐

