【问题标题】:Replace continuous 0s to 1s in an one-dimensional numpy array [duplicate]将一维 numpy 数组中的连续 0 替换为 1 [重复]
【发布时间】:2017-09-08 13:57:40
【问题描述】:

我有一个 1 和 0 的 Numpy 一维数组。例如

a = np.array([0,1,1,1,0,0,0,0,0,0,0,1,0,1,1,0,0,0,1,1,0,0])

如果连续 0 的长度小于阈值,我想将连续 0 替换为 1,让说 2。第一个和最后一个连续 0 将被排除。所以它会输出一个像这样的新数组

out: [0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0]

如果阈值为 4,则输出为

out: [0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0]

我所做的是计算每个段的长度 我从this answer得到了这个解决方案

segLengs = np.diff(np.flatnonzero(np.concatenate(([True], a[1:]!= a[:-1], [True] ))))

out: [1,3,7,1,1,2,3,2,2]

然后找到小于阈值的段

gaps = np.where(segLengs <= threshold)[0]
gapsNeedPadding = gaps[gaps % 2 == 0]

然后循环 gapsNeedPadding 数组

itertools.groupby 也可以完成这项工作,但会有点慢

有没有更有效的解决方案?我更喜欢矢量化解决方案。速度是我需要的。我已经有了一个缓慢的解决方案,它通过数组循环

更新

尝试了@divakar 在this question 中提供的解决方案,但是当阈值较大时,它似乎无法解决我的问题。

numpy_binary_closingbinary_closing 有不同的输出。此外,这两个函数都不会从边界 + 阈值关闭

我在下面的代码中有什么错误吗?

import numpy as np
from scipy.ndimage import binary_closing

def numpy_binary_closing(mask,threshold):

    # Define kernel
    K = np.ones(threshold)

    # Perform dilation and threshold at 1
    dil = np.convolve(mask, K, mode='same') >= 1

    # Perform erosion on the dilated mask array and threshold at given threshold
    dil_erd = np.convolve(dil, K, mode='same') >= threshold
    return dil_erd

threshold = 4
mask = np.random.rand(100) > 0.5

print(mask.astype(int))
out1 = numpy_binary_closing(mask, threshold)
out2 = binary_closing(mask, structure=np.ones(threshold))
print(out1.astype(int))
print(out2.astype(int))
print(np.allclose(out1,out2))

输出

[0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 1 0 0 0 1 1 0 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 0 1 0 1 0 0 0 1 1 1 0 1 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 1 0 1 1 1]

[0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 0]

[0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0]

False

【问题讨论】:

  • 为什么最后两个0s没有被替换?
  • @Ev.Kounis 第一个和最后一个连续 0 将被排除
  • 阈值是常数吗?
  • @DYZ 不是,可能是 2 到 100+
  • 记得注明您可能从中获取任何代码的任何其他帖子。对于这篇文章,该代码段:np.diff(np.f.. 看起来需要这样。

标签: python numpy


【解决方案1】:

在没有更好的主意的情况下:

for _ in range(threshold - 1):
    a |= np.roll(a, 1)

(此代码不处理尾随零。)

【讨论】:

  • 如果阈值为 3,则输出 Out[7]: array([0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1]) 似乎不起作用?
猜你喜欢
  • 2022-01-07
  • 2018-03-30
  • 2016-10-20
  • 2020-01-10
  • 1970-01-01
  • 2022-12-17
  • 2021-10-12
  • 2022-11-13
相关资源
最近更新 更多