[0, 0, 0, 2, 2, 0, 2, 2, 2, 0]
我需要找到索引(开始,停止):
(3, 5)
(6, 9)
我能够实现的最快的事情是创建一个布尔数组:
truth = data > threshold
然后使用
numpy.argmin
和
numpy.argmax
循环遍历数组以查找开始和结束位置。
pos = 0
truth = container[RATIO,:] > threshold
while pos < len(truth):
start = numpy.argmax(truth[pos:]) + pos + offset
end = numpy.argmin(truth[start:]) + start + offset
if not truth[start]:#nothing more
break
if start == end:#goes to the end
end = len(truth)
pos = end
但是对于我的数组中的数十亿个位置来说这太慢了,而且我找到的跨度通常只是连续的几个位置。有谁知道找到这些跨度的更快方法?
In [11]: a
Out[11]: array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0])
In [12]: a1 = a > 1
使用 : 将其向左移动一位(以获取每个索引处的下一个状态)
In [13]: a1_rshifted = np.roll(a1, 1)
In [14]: starts = a1 & ~a1_rshifted # it's True but the previous isn't
In [15]: ends = ~a1 & a1_rshifted
其中
In [16]: np.nonzero(starts)[0], np.nonzero(ends)[0]
Out[16]: (array([3, 6]), array([5, 9]))
并将它们压缩在一起:
In [17]: zip(np.nonzero(starts)[0], np.nonzero(ends)[0])
Out[17]: [(3, 5), (6, 9)]
您可以使用
scipy.ndimage.measurements.label 来识别任何非零值的区域。它返回一个数组,其中每个元素的值是原始数组中跨度或范围的 id。
然后您可以使用scipy.ndimage.measurements.find_objects 返回提取这些范围所需的切片。您可以直接从这些切片访问开始/结束值。
在你的例子中:
import numpy
from scipy.ndimage.measurements import label, find_objects
data = numpy.array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0])
labels, number_of_regions = label(data)
ranges = find_objects(labels)
for identified_range in ranges:
print(identified_range[0].start, identified_range[0].stop)
你应该看到:
3 5
6 9
希望这有帮助!
a = np.pad(im, ((0, 0), (0, 1)), constant_values=0)
b = np.pad(im, ((0, 0), (1, 0)), constant_values=0)
starts = a & ~b
ends = ~a & b
sx, sy = np.nonzero(starts)
ex, ey = np.nonzero(ends)
批准的答案有一个问题,因为如果你以 True 结尾,它会被滚到前面并弄乱值。您确实想用 0 填充这些值。然后您将找到 1 -> 0 转换和 0 -> 1 转换,并将它们放入您需要的格式。