我有一个形状为(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)
现在我想比较img
和maxa
,我知道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)
什么是更快的方法?
2条答案
按热度按时间yptwkmov1#
上述答案是正确的,因为典型的numpy方式是通过广播。但是,不需要
np.newaxis
!“Reducing”操作(
np.sum
,np.max
,np.ufunc.reduce
等)都有一个关键字参数keepdims
。From thenp.max
docs(强调我的):keepdims
-bool, optional
如果将其设置为True,则缩小的轴将作为尺寸为1的尺寸保留在结果中。使用此选项,结果将根据原始阵列正确广播。
因此,无论减少哪个轴,以下内容始终有效:
为了说明主要区别:
wqsoz72f2#
如果这是你想要的:
那你就这么做
Numpy广播规则意味着外部尺寸根据需要添加,而不是内部尺寸。这意味着您可以比较形状
[x, y, z]
和形状[y, z]
(对于所有x
,do...),但不能比较形状[x, y]
(对于所有z
,do...)。然而,内部维度可以被设置为1,以允许适当的广播。这就是我们对np.newaxis
所做的。它将[x, y]
形状转换为[x, y, 1]
。弃用警告只是为了比较不兼容形状的数组并获得
False
返回值;不适合在数组中使用==
。