已知文本块的左上角和右下角坐标,如何定位右上角的文本框?
解决方案
- 第一步:先做行聚类,把垂直方向重叠度足够高的文本块归为同一行
具体判断规则:对任意两个Word对象,计算垂直方向的重叠高度 =
min(a.bottom_right[1], b.bottom_right[1]) - max(a.top_left[1], b.top_left[1]),如果重叠高度 >min(a高度, b高度) * 0.6(阈值可根据实际场景调整,一般取0.5~0.7),则判定为同一行。
你遇到的MLO和3PH,4W垂直重叠度为0,会被直接分到不同行,不会出现跨行按x排序的问题。
- 第二步:对所有行按行的平均y坐标(或行内所有文本块最小top_left.y值)从小到大排序,得到从上到下的行顺序。
- 第三步:同一行内的所有文本块按top_left.x从小到大排序,得到从左到右的文本顺序,直接拼接即可得到正确的行文本。
快速实现简化方案
如果不想实现聚类逻辑,可直接对排序key做加权处理:
把y坐标的权重放大,远大于x坐标的最大差值,排序key设置为 (word.top_left[1] // 行高阈值, word.top_left[0]),其中行高阈值可以取所有文本块平均高度的0.7倍,即可实现先按近似行分组、再按x排序的效果。
提取红色框内容补充逻辑
如果已经获取红色框的坐标,可先做初步过滤:保留中心点落在红色框内、或与红色框交并比>0.3的Word对象,再做上述排序逻辑即可。
示例代码(Python)
# 先计算所有文本块的平均高度 heights = [w.bottom_right[1] - w.top_left[1] for w in word_list] avg_height = sum(heights) / len(heights) line_threshold = avg_height * 0.6 # 行聚类 lines = [] for word in word_list: added = False for line in lines: sample = line[0] overlap_y = min(word.bottom_right[1], sample.bottom_right[1]) - max(word.top_left[1], sample.top_left[1]) if overlap_y > line_threshold: line.append(word) added = True break if not added: lines.append([word]) # 行排序 + 行内排序 lines.sort(key=lambda l: min(w.top_left[1] for w in l)) result = [] for line in lines: line.sort(key=lambda w: w.top_left[0]) # 拼接行文本 line_text = ' '.join([w.text for w in line]) result.append(line_text)
内容的提问来源于stack exchange,提问作者Tau n Ro
相关产品推荐
相关产品推荐

