NumPy中的Fancier Fancy Indexing?

时间:2012-08-17 23:00:57

标签: python numpy

我正在使用带有NumPy的查找表(LUT)实现颜色插值。有一次,我使用RGB值的4个最高位来从17x17x17x4 LUT中选择相应的CMYK值。现在它看起来像这样:

import numpy as np
rgb = np.random.randint(16, size=(3, 1000, 1000))
lut = np.random.randint(256, size=(17, 17, 17, 4))
cmyk = lut[rgb[0], rgb[1], rgb[2]]

这是第一个问题......有没有更好的方法?你可以告诉NumPy lut的索引沿着rgb的轴0存储,而不必实际写出来,这似乎很自然。 NumPy中有cmyk = lut.fancier_take(rgb, axis=0)这样的东西吗?

此外,我留下了一个形状(1000, 1000, 4)的数组,所以为了与输入保持一致,我需要使用几个swapaxes来旋转它:

cmyk = cmyk.swapaxes(2, 1).swapaxes(1, 0).copy()

我还需要添加copy语句,因为如果不是,结果数组在内存中不连续,以后会带来麻烦。

现在我倾向于在花式索引之前旋转LUT然后按照以下方式做一些事情:

swapped_lut = lut.swapaxes(2, 1).swapaxes(1, 0)
cmyk = swapped_lut[np.arange(4), rgb[0], rgb[1], rgb[2]]

但同样,它似乎并不正确......必须有一种更优雅的方式来做到这一点,对吧?像cmyk = lut.even_fancier_take(rgb, in_axis=0, out_axis=0) ...

这样的东西

2 个答案:

答案 0 :(得分:3)

我建议使用tuple强制逐行建立索引,而使用np.rollaxistranspose而不是swapaxes

lut[tuple(rgb)].transpose(2, 0, 1).copy()

np.rollaxis(lut[tuple(rgb)], 2).copy()

要先滚动轴,请使用:

np.rollaxis(lut, -1)[(Ellipsis,) + tuple(rgb)]

答案 1 :(得分:1)

如果您交换lutnp.arange(4)无效,则需要执行以下操作:

swapped_lut = np.rollaxis(lut, -1)
cmyk = swapped_lut[:, rgb[0], rgb[1], rgb[2]].copy()

或者你可以替换

cmyk = lut[rgb[0], rgb[1], rgb[2]]
cmyk = cmyk.swapaxes(2, 1).swapaxes(1, 0).copy()

使用:

cmyk = lut[tuple(rgb)]
cmyk = np.rollaxis(cmyk, -1).copy()

但要尝试一步到位,......也许:

rng = np.arange(4).reshape(4, 1, 1)
cmyk = lut[rgb[0], rgb[1], rgb[2], rng]

这根本不是很可读吗?

看一下这个问题的答案Numpy multi-dimensional array indexing swaps axis order。它很好地解释了numpy如何广播多个数组以获得输出大小。在这里你想要创建到广播到(4,1000,1000)的lut的索引。希望这是有道理的。