Python3下无需循环/列表推导式提取多轮廓包围矩形顶点的优化方案
无需循环提取多轮廓包围矩形顶点的numpy向量化实现
我有一个由多个轮廓点列表组成的列表,每个子列表对应一个图形的边界点,需要提取每个图形的包围矩形的四个顶点,格式为
[[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y]]。例如输入列表为[[[2,5],[3,4],[5,8],[5,6],[5,9]], [[11,14],[12,15],[16,17]], ... ],期望输出为[[[2,4],[2,9],[5,9],[5,4]], [[11,14], [11, 17], [16,17], [16,14]] ... ]。我已通过Python循环实现该功能,代码如下:cleaned_contours = list() for cur_cont in contours: min_x, min_y = cur_cont.min(axis=0).flatten() max_x, max_y = cur_cont.max(axis=0).flatten() cleaned_contours.append(np.array([[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y]]))现询问是否可无需循环或列表推导式完成该操作,使用Python3环境。
当然可以!借助numpy的向量化运算能力,我们可以完全摆脱循环,直接对整个数据集进行批量处理,效率还会更高。具体步骤如下:
实现代码
import numpy as np # 假设你的输入contours是Python列表,先转换为三维numpy数组(如果已经是数组可跳过这步) contours_np = np.array(contours) # 批量计算每个轮廓的最小、最大坐标(沿点数维度axis=1计算) min_vals = contours_np.min(axis=1) # 形状为(N, 2),N是轮廓数量 max_vals = contours_np.max(axis=1) # 形状为(N, 2) # 批量构造每个轮廓的四个包围矩形顶点 vertex1 = min_vals # [min_x, min_y] vertex2 = np.stack([min_vals[:, 0], max_vals[:, 1]], axis=1) # [min_x, max_y] vertex3 = max_vals # [max_x, max_y] vertex4 = np.stack([max_vals[:, 0], min_vals[:, 1]], axis=1) # [max_x, min_y] # 将四个顶点按顺序堆叠,得到最终结果(形状为(N, 4, 2)) cleaned_contours = np.stack([vertex1, vertex2, vertex3, vertex4], axis=1)
原理说明
- 数组转换:先把输入的列表转成三维numpy数组,这样才能利用numpy的批量计算能力;
- 批量极值计算:通过
min(axis=1)和max(axis=1)直接对所有轮廓的点计算x、y方向的极值,一步得到所有轮廓的最小/最大坐标; - 顶点构造:用
np.stack将对应的极值组合成每个顶点,最后再把四个顶点按要求的顺序堆叠起来,得到每个轮廓的包围矩形顶点数组。
这种方式完全没有循环或列表推导式,而且当轮廓数量很大时,向量化运算的效率会比Python循环高几个数量级。
内容的提问来源于stack exchange,提问作者Akash Kumar
相关产品推荐
相关产品推荐

