如何在NumPy中比较三维数组和二维数组?

34gzjxbg  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(138)

我有一个形状为(height, width, 3)的三维数组,它代表一个BGR图像,值是[0,1]中的浮点数。
在对像素进行一些操作之后,我得到一个形状为(height, width)的二维数组,数组中的值是对每个像素执行一些操作的结果。
现在我想比较原始图像和结果,更具体地说,我想比较每个像素的每个BGR分量和位于同一坐标的结果数组的值。
例如,我想知道每个像素中哪个BGR分量最大:

import numpy as np

img = np.random.random((360, 640, 3))
maxa = img.max(axis=-1)

现在我想比较imgmaxa,我知道img == maxa不工作:

In [335]: img == maxa
<ipython-input-335-acb909814b9a>:1: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.
  img == maxa
Out[335]: False

我不擅长描述事物,所以我将向你展示我打算在Python中做什么:

result = [[[c == maxa[y, x] for c in img[y, x]] for x in range(640)] for y in range(360)]

显然这是低效的,但我想证明我知道逻辑。
我在NumPy中也做了同样的事情,但我认为它可以更有效:

img == np.dstack([maxa, maxa, maxa])

我已经证实了我理解的正确性:

In [339]: result = [[[c == maxa[y, x] for c in img[y, x]] for x in range(640)] for y in range(360)]
     ...: np.array_equal(arr3, img == np.dstack([maxa, maxa, maxa]))
Out[339]: True

我对我的方法进行了基准测试:

In [340]: %timeit [[[c == maxa[y, x] for c in img[y, x]] for x in range(640)] for y in range(360)]
509 ms ± 16.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [341]: maxals = maxa.tolist()

In [342]: imgls = img.tolist()

In [343]: %timeit [[[c == maxals[y][x] for c in imgls[y][x]] for x in range(640)] for y in range(360)]
156 ms ± 2.57 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [344]: %timeit img == np.dstack([maxa, maxa, maxa])
4.25 ms ± 121 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

什么是更快的方法?

yptwkmov

yptwkmov1#

上述答案是正确的,因为典型的numpy方式是通过广播。但是,不需要np.newaxis
“Reducing”操作(np.sumnp.maxnp.ufunc.reduce等)都有一个关键字参数keepdimsFrom the np.max docs(强调我的):
keepdims - bool, optional
如果将其设置为True,则缩小的轴将作为尺寸为1的尺寸保留在结果中。使用此选项,结果将根据原始阵列正确广播。
因此,无论减少哪个轴,以下内容始终有效:

import numpy as np

# No matter which axis
axis = np.random.choice([0, 1, 2])

img = np.random.random((360, 640, 3))
maxa = img.max(axis=axis, keepdims=True)

img == maxa

为了说明主要区别:

>>> img.max(axis=-1).shape
(360, 640)
>>> img.max(axis=-1, keepdims=True).shape
(360, 640, 1)
wqsoz72f

wqsoz72f2#

如果这是你想要的:

img == np.dstack([maxa, maxa, maxa])

那你就这么做

img == maxa[..., np.newaxis]

Numpy广播规则意味着外部尺寸根据需要添加,而不是内部尺寸。这意味着您可以比较形状[x, y, z]和形状[y, z](对于所有x,do...),但不能比较形状[x, y](对于所有z,do...)。然而,内部维度可以被设置为1,以允许适当的广播。这就是我们对np.newaxis所做的。它将[x, y]形状转换为[x, y, 1]
弃用警告只是为了比较不兼容形状的数组并获得False返回值;不适合在数组中使用==

相关问题