如何计算文本行多边形的中心线或基线?
文本行Polygon的基线/中心线计算方案
核心思路
历史文档的文本行Polygon通常是水平(或轻微倾斜)的细长形状,直接用几何中心(shapely.centroid)会因边缘不规则偏离实际基准,需针对性提取边缘或中线:
1. 提取基线(文本底部对齐线)
场景1:标准四边形文本行
若Polygon顶点按左上→右上→右下→左下闭合,直接取底部两个顶点连线:
from shapely.geometry import Polygon, LineString # 示例坐标(左上、右上、右下、左下) poly_coords = [(12, 65), (145, 65), (145, 42), (12, 42)] poly = Polygon(poly_coords) # 提取底部边缘作为基线 baseline = LineString([poly_coords[2], poly_coords[3]]) print("基线坐标:", list(baseline.coords))
场景2:不规则/倾斜文本行
先计算最小外接矩形(MBR),再取MBR的底部边缘:
from shapely.geometry import Polygon, LineString poly = Polygon(your_irregular_poly_coords) # 获取旋转后的最小外接矩形 mbr = poly.minimum_rotated_rectangle mbr_coords = list(mbr.exterior.coords) # 筛选y值最小的两个点(底部边缘) sorted_points = sorted(mbr_coords, key=lambda p: p[1]) baseline = LineString(sorted_points[:2])
2. 计算中心线(垂直中线)
通过上下边缘的y值均值生成水平中线:
from shapely.geometry import Polygon, LineString poly = Polygon(your_poly_coords) # 提取所有顶点的x、y范围 xs = [p[0] for p in poly.exterior.coords] ys = [p[1] for p in poly.exterior.coords] min_x, max_x = min(xs), max(xs) min_y, max_y = min(ys), max(ys) mid_y = (min_y + max_y) / 2 # 生成水平中心线 center_line = LineString([(min_x, mid_y), (max_x, mid_y)]) print("中心线坐标:", list(center_line.coords))
3. 倾斜文本行的骨架化提取
针对手写/严重倾斜的文本行,用骨架提取获取中心骨架:
import numpy as np from shapely.geometry import LineString from skimage.morphology import skeletonize from skimage.draw import polygon2mask poly = Polygon(your_poly_coords) xs = [p[0] for p in poly.exterior.coords] ys = [p[1] for p in poly.exterior.coords] min_x, max_x = min(xs), max(xs) min_y, max_y = min(ys), max(ys) # 转换为二进制掩码 width = int(max_x - min_x + 1) height = int(max_y - min_y + 1) rel_coords = [(x - min_x, y - min_y) for x, y in poly.exterior.coords] mask = polygon2mask((height, width), rel_coords).astype(np.uint8) # 骨架提取 skeleton = skeletonize(mask) # 提取骨架中最长的水平线段作为中心线 y_coords, x_coords = np.where(skeleton) abs_points = [(x + min_x, y + min_y) for x, y in zip(x_coords, y_coords)] # 按y值分组,取点数最多的y组生成线段 from collections import defaultdict y_groups = defaultdict(list) for x, y in abs_points: y_groups[y].append(x) max_count = max(len(xs) for xs in y_groups.values()) best_y = [y for y, xs in y_groups.items() if len(xs) == max_count][0] best_xs = y_groups[best_y] center_line = LineString([(min(best_xs), best_y), (max(best_xs), best_y)])
问题原因说明
- shapely.centroid不可靠:几何中心会受Polygon局部不规则(如字符突出)影响,偏离文本行的实际基准线
- 自行代码得到上线:大概率是误取了y值最大的顶部顶点(需确认Polygon顶点闭合顺序是否为左上→右上→右下→左下)
内容的提问来源于stack exchange,提问作者bsteo
相关产品推荐
相关产品推荐

