有什么方法可以对多个值而不只是一个值运行np.where?

时间:2019-01-20 23:29:26

标签: python python-3.x image numpy image-processing

我想知道我是否有一个numpy数组中的图像,例如250x250x3(3个通道),是否可以使用np.where来快速找出大小为3的250x250数组中的任何一个是否等于[143 ,255、0]或由rgb表示的另一种颜色,并获得250x250布尔数组?

当我在代码中使用4x4x3进行尝试时,得到的结果是3x3数组,但我不确定该形状的来源。

import numpy as np

test = np.arange(4,52).reshape(4,4,3)
print(np.where(test == [4,5,6]))

-------------------------------------------

Result:

array([[0, 0, 0],
       [0, 0, 0],
       [0, 1, 2]])


What I'm trying to get:

array([[1, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

2 个答案:

答案 0 :(得分:2)

为简单起见,假设我们正在寻找所有3个通道都等于1的所有位置。

np.random.seed(0)
a=np.random.randint(0,2,(3,5,5))
print(a)
np.where((a[0]==1)*(a[1]==1)*(a[2]==1))

此输出

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

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

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

(array([0, 0, 1, 2, 4], dtype=int64), array([1, 2, 4, 0, 1], dtype=int64))

确实有5个坐标,其中所有3个通道均等于1。 如果您想获得更易读的表示形式,请用

替换最后一行
tuple(zip(*np.where((a[0]==1)*(a[1]==1)*(a[2]==1))))

这将输出

((0, 1), (0, 2), (1, 4), (2, 0), (4, 1))

是所有3个通道均等于1的所有5个位置。

请注意,(a[0]==1)*(a[1]==1)*(a[2]==1)只是

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

您要查找的布尔表示形式。

如果要获取其他任何三元组,请说[143, 255, 0],只需使用(a[0]==143)*(a[1]==255)*(a[2]==0)

答案 1 :(得分:2)

解决方案

您根本不需要np.where(或任何特别复杂的东西)。您可以利用布尔数组的功能:

print(np.all(test == [4,5,6], axis=-1).astype(int))
# output:
#     [[1 0 0 0]
#      [0 0 0 0]
#      [0 0 0 0]
#      [0 0 0 0]]

等效的替代方法是使用logical_and

print(np.logical_and.reduce(test == [4,5,6], axis=-1).astype(int))
# output:
#     [[1 0 0 0]
#      [0 0 0 0]
#      [0 0 0 0]
#      [0 0 0 0]]

重型测试

import numpy as np
np.random.seed(0)

# the subarray we'll search for
pattern = [143, 255, 0]

# generate a random test array
arr = np.random.randint(0, 255, size=(255,255,3))

# insert the pattern array at ~10000 random indices
ix = np.unique(np.random.randint(np.prod(arr.shape[:-1]), size=10000))
arr.reshape(-1, arr.shape[-1])[ix] = pattern

# find all instances of the pattern array (ignore partial matches)
loc = np.all(arr==pattern, axis=-1).astype(int)

# test that the found locs are equivalent to the test ixs
locix = np.ravel_multi_index(loc.nonzero(), arr.shape[:-1])
np.testing.assert_array_equal(np.sort(ix), np.sort(locix))
# test has been run, the above assert passes