NumPy多维数组中任一轴上“True”值的最大数量

3

我有一个包含布尔值的Numpy多维数组。在我的情况下,它是一个立方体。

我想知道包含所有True值的最小矩形框的最大尺寸。换句话说,这将是任何轴上的True值之间的最大距离。

例如,如果我有以下数组:

np.array([[
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False,  True, False],
    [False, False,  True,  True, False],
    [False,  True,  True,  True, False],
    [False,  True, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
]])

如果我们在这个“盒子”中垂直距离为4,或者在左下和右上值之间的距离为4,那么它将返回4

  ...
  [False False  True]
  [False  True  True]
  [ True  True  True]
  [ True False False]
  ...

我在思考以下方案,但这听起来很冗余、重复且昂贵...实际上并没有完全发挥作用 :)

   from itertools import product

    max_1 = max(sum(cube[:, i, j]) for i, j in product(range(3), range(3)))
    max_2 = max(sum(cube[i, :, j]) for i, j in product(range(3), range(3)))
    max_3 = max(sum(cube[i, j, :]) for i, j in product(range(3), range(3)))

    # ... and then
    max_dim = max(max_1, max_2, max_3)

有什么建议吗?
3个回答

3

如果您的目标是获取最大维度的长度,您可以使用以下方法:

max(np.ptp(d) + 1 for d in np.nonzero(a))

其中a是您的布尔数组。您问题中数组的输出是4。如果您需要获取True值的最小三维边界框,请继续阅读。


可以使用numpy.nonzero在每个维度中找到True值的索引,然后根据numpy.nonzero找到的索引的最小值和最大值来索引原始数组。

import numpy as np

a = np.array([[
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, True, False],
    [False, False, True, True, False],
    [False, True, True, True, False],
    [False, True, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
]])

slices = [slice(d.min(), d.max()+1) for d in np.nonzero(a)]
a[slices[0], slices[1], slices[2]]

输出结果与您期望的输出一致。

array([[[False, False,  True],
        [False,  True,  True],
        [ True,  True,  True],
        [ True, False, False]]])

这可以转化为一个函数来处理 N 维数组。这会使用 numpy.s_, 它创建一个索引表达式,可用于获取数组的切片。

def get_bbox_indexer(a):
    slices = tuple(slice(d.min(), d.max()+1) for d in np.nonzero(a))
    return np.s_[slices]

indexer = get_bbox_indexer(a)
a[indexer]

输出结果与上面相同。
array([[[False, False,  True],
        [False,  True,  True],
        [ True,  True,  True],
        [ True, False, False]]])

为了获取被切片数组的最大维度大小,可以执行:
indexer = get_bbox_indexer(a)
max(a[indexer].shape)

1
你可以堆叠nonzero返回的索引来绕过推导式:(np.ptp(np.stack(np.nonzero(np.arange(12).reshape(3, 4))), axis=1) + 1).max() - Mad Physicist
np.ptp 真是美妙无比! - Jean-Francois T.

1

我认为最简单的方法是获取True元素的索引,然后计算这些索引的最小值和最大值--这将是你的矩形。

a = [...]
indices = np.array(np.where(a)).T
print(np.min(indices, axis=0), np.max(indices, axis=0))

[2 1 1] [2 4 3]

然后,为了获得最大长度,只需将这两个数相减,找到最大值并加1。
print(np.max(np.max(indices, axis=0) - np.min(indices, axis=0)) + 1)

4

0

这个答案对我来说实际上是有效的,但是它假设True值是连续的。

import numpy as np

a = np.array([[
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, True, False],
    [False, False, True, True, False],
    [False, True, True, True, False],
    [False, True, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
], [
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
    [False, False, False, False, False],
]])

max_axis = (np.sum(np.any(a, axis=axis), axis=1) for axis in range(3))
max_dim = max(max(m) for m in max_axis)
  1. 对于每个轴,检测其他轴上是否至少存在一个True
  2. 计算具有True的轴的数量
  3. 计算每个轴的最大值

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接