如何从二进制3D numpy数组中提取并分离点团(Blob)?
问题
我有一个形状为(260,311,260)的NumPy数组,其中值为1的元素代表8个电极,其余为0(空白区域)。我需要检测并分离这些点团(Blob),最终得到8个同形状的数组,每个数组仅包含一个电极。
我尝试过以下方法但遇到瓶颈:
- 用
np.nonzero提取值为1的元素,但后续分离步骤无法推进 - 尝试
skimage.feature.blob_log,但无法适配当前的NumPy数组 - 试过Kmeans聚类,但需要适配可变数量的电极,无法固定聚类数
以下是提取非零元素后绘制3D点云的代码:
fig = plt.figure(figsize=(6, 6)) ax = fig.add_subplot(111, projection='3d') ax.scatter(all_coordinates[0], all_coordinates[1], all_coordinates[2], linewidths=1, alpha=.7, edgecolor='k', s = 200, c=all_coordinates[0]) ax.view_init(elev=0, azim=0) plt.show()

真奇怪,居然没有简单的函数能直接分离这些点团?
解决方案
用skimage.measure.label和skimage.measure.regionprops就能完美解决这个问题——这是专门针对3D(或2D)连通区域分割的工具,能自动识别所有独立的点团,无需提前指定数量:
为什么之前的方法不适用?
np.nonzero只能提取坐标,但无法区分不同连通的点团skimage.feature.blob_log是针对形状规则(如圆形)的Blob检测,不适合任意形状的连通电极点团- Kmeans需要提前指定聚类数,无法自适应电极数量的变化
步骤说明
- 标记连通区域:
label函数会给每个独立的连通点团分配唯一的标签值,背景(0)保持为0 - 提取每个区域:遍历每个标签,生成仅包含当前标签对应点团的数组
代码实现
import numpy as np from skimage import measure # 假设你的电极数组名为electrodes_data labeled_array, num_regions = measure.label(electrodes_data, connectivity=3, return_num=True) # connectivity=3表示3D空间中的连通(上下左右前后相邻都算连通) # 生成每个电极对应的数组 electrode_arrays = [] for label in range(1, num_regions + 1): # 创建和原数组同形状的全0数组 single_electrode = np.zeros_like(electrodes_data) # 将当前标签对应的位置设为1 single_electrode[labeled_array == label] = 1 electrode_arrays.append(single_electrode) # 现在electrode_arrays就是包含所有独立电极的数组列表,数量等于num_regions
核心优势
- 自动识别点团数量:不管是8个还是其他数量的电极,
return_num会返回实际检测到的连通区域数 - 严格匹配原数组形状:每个生成的数组和输入数组完全同形,仅保留一个电极的1值
- 3D连通性适配:
connectivity=3专门处理3D空间的相邻判断,确保同一个电极的所有点被归为一个区域
内容的提问来源于stack exchange,提问作者Petru Isan
相关产品推荐
相关产品推荐

