You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计Numpy二维布尔数组中连通True块的大小?是否有现成库函数?

高效解决布尔数组连通块大小标记问题

你担心递归在大规模数据下的效率问题完全合理——纯Python递归不仅容易碰到栈溢出,而且数组操作的速度确实跟不上大规模数据的需求。这里有个非常高效的解决方案,用scipy库中的ndimage模块,它底层是C实现的,处理这类连通域问题速度快得多。

核心思路:连通区域标记 + 大小映射

我们可以分三步完成需求:

  1. 对布尔数组进行连通块标记:给每个连通的True区域分配唯一的标签
  2. 计算每个标签对应的连通块大小
  3. 将标签矩阵替换为对应的大小矩阵

代码示例(针对你的例子)

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:42:22