填写 numpy ndarray 的最佳方法?

best way to fill in a numpy ndarray?

我使用以下代码生成带有渐变的图像。我逐个元素访问数组。有更好的方法吗?谢谢

import cv2
import numpy as np

x = np.ndarray((256,256,3), dtype=np.uint8)
for i in xrange(256):
    for j in xrange(256):
        for k in xrange(3):
            x[i, j, k] = i
cv2.imwrite('SYxmp_out.jpg', x)

对于 ij 的所有值,您的目标似乎是用 i 填充 x[i, j, k]k.

你可以构造这样的数组:

x = np.repeat(np.arange(256, dtype=np.uint8), (256*3)).reshape(256, 256, 3)

然后我们得到一个如下所示的数组:

>>> np.repeat(np.arange(256, dtype=np.uint8), (256*3)).reshape(256, 256, 3)
array([[[  0,   0,   0],
        [  0,   0,   0],
        [  0,   0,   0],
        ...,
        [  0,   0,   0],
        [  0,   0,   0],
        [  0,   0,   0]],

       [[  1,   1,   1],
        [  1,   1,   1],
        [  1,   1,   1],
        ...,
        [  1,   1,   1],
        [  1,   1,   1],
        [  1,   1,   1]],

       [[  2,   2,   2],
        [  2,   2,   2],
        [  2,   2,   2],
        ...,
        [  2,   2,   2],
        [  2,   2,   2],
        [  2,   2,   2]],

       ...,

       [[253, 253, 253],
        [253, 253, 253],
        [253, 253, 253],
        ...,
        [253, 253, 253],
        [253, 253, 253],
        [253, 253, 253]],

       [[254, 254, 254],
        [254, 254, 254],
        [254, 254, 254],
        ...,
        [254, 254, 254],
        [254, 254, 254],
        [254, 254, 254]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]], dtype=uint8)

对于第二个轴,我们可以使用np.tile:

>>> np.tile(np.repeat(np.arange(256, dtype=np.uint8), 3), 256).reshape(256, 256, 3)
array([[[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ...,
        [253, 253, 253],
        [254, 254, 254],
        [255, 255, 255]],

       [[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ...,
        [253, 253, 253],
        [254, 254, 254],
        [255, 255, 255]],

       [[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ...,
        [253, 253, 253],
        [254, 254, 254],
        [255, 255, 255]],

       ...,

       [[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ...,
        [253, 253, 253],
        [254, 254, 254],
        [255, 255, 255]],

       [[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ...,
        [253, 253, 253],
        [254, 254, 254],
        [255, 255, 255]],

       [[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ...,
        [253, 253, 253],
        [254, 254, 254],
        [255, 255, 255]]], dtype=uint8)

尽管如果事情更复杂,广播可能是更好的主意。例如,对于第一个维度,我们可以使用:

x = np.zeros((256, 256, 3))
x[:] = np.arange(256)[:,None,None]

而对于第二个,我们可以使用:

x = np.zeros((256, 256, 3))
x[:] = np.arange(256)[None,:,None]

或不提及 256 两次:

而对于第二个,我们可以使用:

x = np.zeros((256, 256, 3))
x[:] = np.arange(x.shape[0])[:,None,None]

# second dimension
x = np.zeros((256, 256, 3))
x[:] = np.arange(x.shape[1])[None,:,None]

基准:

如果我 运行 问题中的代码 (f)、答案中的代码 (g) 和广播版本 (h) i7-7500U CPU @ 2.70GHz 一百次,我获得以下基准:

>>> timeit(f, number=100)
3.1465475099976175
>>> timeit(g, number=100)
0.05008594098035246
>>> timeit(h, number=100)
0.03603723298874684

所以这应该意味着 gf 大约提速 62 倍,hf 提速大约 87 倍。