如何统计Numpy二维布尔数组中连通True块的大小?是否有现成库函数?
高效解决布尔数组连通块大小标记问题
你担心递归在大规模数据下的效率问题完全合理——纯Python递归不仅容易碰到栈溢出,而且数组操作的速度确实跟不上大规模数据的需求。这里有个非常高效的解决方案,用scipy库中的ndimage模块,它底层是C实现的,处理这类连通域问题速度快得多。
核心思路:连通区域标记 + 大小映射
我们可以分三步完成需求:
- 对布尔数组进行连通块标记:给每个连通的True区域分配唯一的标签
- 计算每个标签对应的连通块大小
- 将标签矩阵替换为对应的大小矩阵
代码示例(针对你的例子)
import numpy as np from scipy import ndimage # 你的布尔矩阵(这里用1/0代替True/False,效果完全一致) input_arr = np.array([[1, 0, 0, 0], [0, 1, 1, 0], [0, 1, 0, 0], [0, 1, 0, 0]]) # 1. 标记连通块:默认是4连通(上下左右相邻),如需8连通可加structure参数 labeled_matrix, num_regions = ndimage.label(input_arr) # 2. 计算每个连通块的大小 region_sizes = ndimage.sum(input_arr, labeled_matrix, range(num_regions + 1)) # 3. 把标签替换成对应大小 result_matrix = region_sizes[labeled_matrix] print(result_matrix)
运行后输出就是你想要的:
[[1 0 0 0] [0 4 4 0] [0 4 0 0] [0 4 0 0]]
关键细节说明
- 连通性选择:默认是4连通(只考虑上下左右相邻),如果需要包含对角线的8连通,修改
label函数的参数:# 8连通的结构元素 structure = np.ones((3, 3), dtype=int) labeled_matrix, num_regions = ndimage.label(input_arr, structure=structure) - 布尔数组兼容性:如果你的输入是
True/False的布尔数组,直接传入即可,因为True会被视为1,False视为0,代码无需修改。 - 效率优势:
scipy.ndimage的函数都是底层优化过的,处理大规模矩阵(比如几千×几千的数组)时,速度比纯Python递归或循环快几个数量级,完全不用担心性能问题。
替代方案(如果不想用scipy)
如果你因为环境限制不能用scipy,也可以考虑skimage.measure模块中的label和regionprops,用法类似:
from skimage.measure import label, regionprops input_arr = np.array([[1, 0, 0, 0], [0, 1, 1, 0], [0, 1, 0, 0], [0, 1, 0, 0]]) labeled_matrix = label(input_arr) result_matrix = np.zeros_like(labeled_matrix) for prop in regionprops(labeled_matrix): result_matrix[labeled_matrix == prop.label] = prop.area print(result_matrix)
不过整体效率还是scipy.ndimage更高一些。
内容的提问来源于stack exchange,提问作者Rocky Li
相关产品推荐
相关产品推荐

