如何仅填充NumPy数组内部零值(保留外围零)
解决方案
要实现保留外围0、填充内部被1包围的0,核心思路是区分连通到数组边界的0区域和完全被1包裹的内部0区域,只将后者替换为1。以下提供两种实用的实现方法:
方法一:使用skimage的flood_fill(简洁直观)
import numpy as np from skimage.segmentation import flood_fill # 你的原始数组 arr = np.array([[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) # 复制数组避免修改原数据 result = arr.copy() # 从左上角的边界0开始,填充所有连通的0(包括外围及连通到外围的0) filled_map = flood_fill(result, (0, 0), 2) # 此时filled_map中值为0的部分就是完全被1包围的内部0,将其替换为1 result[filled_map == 0] = 1 print(result)
方法二:使用scipy的连通区域标记(更灵活)
如果需要更精细地控制连通规则(比如4连通/8连通),可以用连通区域分析:
import numpy as np from scipy.ndimage import label arr = np.array([[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) # 反转数组:原0变1,原1变0,方便后续找连通的0区域 inverted_arr = 1 - arr # 标记所有连通区域,np.ones((3,3))表示8连通(包含对角线相邻) labels, num_regions = label(inverted_arr, structure=np.ones((3,3))) # 找出所有接触数组边界的连通区域标签 boundary_regions = set() # 检查首尾行 for col in range(arr.shape[1]): boundary_regions.add(labels[0, col]) boundary_regions.add(labels[-1, col]) # 检查首尾列 for row in range(arr.shape[0]): boundary_regions.add(labels[row, 0]) boundary_regions.add(labels[row, -1]) # 复制原数组,将非边界的连通区域(内部0)替换为1 result = arr.copy() for region_id in range(1, num_regions + 1): if region_id not in boundary_regions: result[labels == region_id] = 1 print(result)
关键逻辑说明
两种方法本质都是:
- 识别出所有和数组边界连通的0区域,这些是需要保留的外围0;
- 剩余的0区域就是完全被1包围的内部0,将其替换为1即可。
内容的提问来源于stack exchange,提问作者Ana
相关产品推荐
相关产品推荐

