我正在使用带有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)
...
答案 0 :(得分:3)
我建议使用tuple
强制逐行建立索引,而使用np.rollaxis
或transpose
而不是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)
如果您交换lut
,np.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的索引。希望这是有道理的。