如何实现布尔数组中按最小长度合并True块的二进制闭运算?
解决方案
要实现将夹在两个长度达标(≥指定最小值)的连续True序列之间的单个False替换为True的需求,可以通过以下基于NumPy的高效方法实现——scipy.ndimage.binary_closing无法满足需求,因为它无法针对True序列长度做条件判断:
核心思路
- 识别数组中所有连续True块的起始、结束位置及长度;
- 筛选出相邻的、长度均达标的True块,且它们之间仅隔一个False的情况;
- 将这些符合条件的单个False位置设为True。
实现代码
import numpy as np def close(a, min_merge_size): # 处理空数组边界情况 if len(a) == 0: return a.copy() # 扩展数组,便于处理首尾的True块 extended_a = np.concatenate([[False], a, [False]]) # 计算差分,找出True块的起始和结束点 diff_a = np.diff(extended_a.astype(int)) starts = np.where(diff_a == 1)[0] # 每个True块的起始索引(对应原数组) ends = np.where(diff_a == -1)[0] # 每个True块的结束索引+1(对应原数组) block_lengths = ends - starts # 每个True块的长度 # 若不足两个True块,直接返回原数组 if len(block_lengths) < 2: return a.copy() # 矢量化筛选符合条件的gap:相邻块长度达标,且仅隔一个False valid_pairs = (block_lengths[:-1] >= min_merge_size) & \ (block_lengths[1:] >= min_merge_size) & \ (starts[1:] - ends[:-1] == 1) # 获取需要替换的False索引 fill_indices = ends[:-1][valid_pairs] # 生成结果数组 result = a.copy() result[fill_indices] = True return result
测试示例
a = np.array([True] *3 + [False] + [True] *4 + [False] *2 + [True] *2) closed_a = close(a, min_merge_size=2) print(closed_a) # 输出:array([ True, True, True, True, True, True, True, True, False, False, True, True])
为什么不用scipy.ndimage.binary_closing?
binary_closing的逻辑是先膨胀再腐蚀,仅基于结构元素的形状填充孔洞,无法判断两侧True序列的长度是否达标,也无法区分“单个False gap”和“多个False gap”,因此无法满足你的精确需求。
内容的提问来源于stack exchange,提问作者Jon Nir
相关产品推荐
相关产品推荐

