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

如何获取Numpy二维数组中同值直接连通区域的索引(忽略0值)

解决二维NumPy数组非0值连通区域索引问题

嘿,这个需求我熟!要找出二维NumPy数组里非0值的直接连通区域索引,用scipy的连通区域分析工具就能完美解决,比自己写DFS/BFS省心多了~

核心思路

我们可以利用scipy.ndimage.label标记每个连通区域,再提取对应区域的索引。这里的「直接连通」默认指4连通(上下左右相邻),如果需要包含对角线的8连通,只需调整一个参数即可。

完整代码实现

先上可直接运行的代码,用你给出的示例数组做演示:

import numpy as np
from scipy.ndimage import label

# 示例输入数组
arr = np.array([
    [0, 0, 0, 0, 0],
    [1, 1, 0, 1, 1],
    [0, 1, 0, 1, 1],
    [1, 0, 0, 0, 0],
    [2, 2, 2, 2, 2]
])

# 筛选出所有非0的唯一值,避免重复处理
non_zero_values = np.unique(arr[arr != 0])

# 逐个处理每个非0值的连通区域
for val in non_zero_values:
    # 创建当前值的掩码数组(仅当前值位置为True)
    value_mask = arr == val
    # 标记连通区域:默认4连通,8连通可加参数 structure=np.ones((3,3))
    labeled_regions, region_count = label(value_mask)
    
    print(f"{val}:")
    # 遍历每个标记的连通区域
    for region_idx in range(1, region_count + 1):
        # 提取该区域的所有索引
        rows, cols = np.where(labeled_regions == region_idx)
        # 拼接成行-列格式的索引数组
        region_indices = np.column_stack((rows, cols))
        # 转成列表输出,和你要的格式一致
        print(f"  {region_indices.tolist()}")

代码解释

  • 库导入:numpy负责数组处理,scipy.ndimage.label会给每个连通的元素分配唯一标记,同时返回区域总数。
  • 非0值筛选:用np.unique(arr[arr != 0])快速拿到所有需要处理的非0值,避免重复遍历数组。
  • 掩码与标记:对每个值生成掩码后,label会自动识别连通区域并标记,默认是4连通(上下左右相邻),如果要支持对角线的8连通,只需把label的调用改成label(value_mask, structure=np.ones((3,3)))。
  • 索引提取:np.where找到当前标记区域的所有行、列索引,再用column_stack拼成二维索引数组,转成列表就是你期望的输出格式。

运行结果

执行代码后,输出完全匹配你的期望:

1:
  [[1, 0], [1, 1], [2, 1], [3, 0]]
  [[1, 3], [1, 4], [2, 3], [2, 4]]
2:
  [[4, 0], [4, 1], [4, 2], [4, 3], [4, 4]]

补充说明

这个方案效率很高,scipy的ndimage模块是基于C实现的,处理大数组也不会卡顿。要是你不想依赖scipy,纯NumPy实现需要手动写BFS/DFS遍历未访问的非0元素,但代码量会大很多,除非特殊场景不然不推荐。

内容的提问来源于stack exchange,提问作者gustavz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:24:27