Numpy区域边界检测

3 投票
2 回答
1570 浏览
提问于 2025-04-17 23:32

给定一个一维数组:

A = [x,..,x,0,..,0,x,..,x,0,..,0,x,..,x,........]

其中:

x,..,x 代表任意数量的任意值

0,..,0 代表任意数量的零

我需要找到一个快速的算法来找出边界的索引,也就是:..,x,0,.. 和 ..,0,x..

这个问题似乎可以通过并行处理来解决,但这超出了我的经验,因为简单地遍历数组太慢了,因为数据量太大

谢谢

马丁

2 个回答

0

这段代码应该至少能把循环的操作放到Numpy的基本功能里去,虽然它会遍历数组三次:

A = 2*(rand(200000)>0.2)  # testing data
borders = flatnonzero(diff(A==0))

在我的电脑上,这段代码运行需要1.79毫秒。

2

@chthonicdaemon的回答已经帮你解决了90%的问题,但如果你想用这些索引来切割你的数组,你还需要一些额外的信息。

假设你想用这些索引来提取数组中不为0的部分。你已经找到了数组变化的索引,但你不知道变化是从True变成False,还是反过来。因此,你需要检查第一个和最后一个值,并根据情况进行调整。否则,在某些情况下,你可能会提取到一段全是零的内容,而不是你想要的数据。

举个例子:

import numpy as np

def contiguous_regions(condition):
    """Finds contiguous True regions of the 1D boolean array "condition".
    Returns a 2D array where the first column is the start index of the region
    and the second column is the end index."""
    # Find the indicies of changes in "condition"
    idx = np.flatnonzero(np.diff(condition)) + 1

    # Prepend or append the start or end indicies to "idx"
    # if there's a block of "True"'s at the start or end...
    if condition[0]:
        idx = np.append(0, idx)
    if condition[-1]:
        idx = np.append(idx, len(condition))

    return idx.reshape(-1, 2)

# Generate an example dataset...
t = np.linspace(0, 4*np.pi, 20)
x = np.abs(np.sin(t)) + 0.1
x[np.sin(t) < 0.5] = 0

print x

# Get the contiguous regions where x is not 0
for start, stop in contiguous_regions(x != 0):
    print x[start:stop]

在这个例子中,我们的数据集看起来是这样的:

array([ 0.        ,  0.71421271,  1.06940027,  1.01577333,  0.        ,
        0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
        0.        ,  0.93716648,  1.09658449,  0.83572391,  0.        ,
        0.        ,  0.        ,  0.        ,  0.        ,  0.        ])

然后通过以下操作:

for start, stop in contiguous_regions(x != 0):
    print x[start:stop]

我们将得到:

[ 0.71421271  1.06940027  1.01577333]
[ 0.93716648  1.09658449  0.83572391]

撰写回答