如何向 Numpy 数组添加新的维度?

我从一个图像的数组开始。

In[1]:img = cv2.imread('test.jpg')

该形状是您可能期望的一个640x480 RGB 图像。

In[2]:img.shape
Out[2]: (480, 640, 3)

然而,这个图像,我有一个视频帧,这是100帧长。理想情况下,我希望有一个单一的数组,其中包含从这个视频的所有数据,使 img.shape返回 (480, 640, 3, 100)

将下一帧(即下一组图像数据,另一个480 x 640 x 3数组)添加到初始数组的最佳方法是什么?

303502 次浏览

你可以先创建一个正确大小的数组,然后填充它:

frames = np.empty((480, 640, 3, 100))


for k in xrange(nframes):
frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))

如果框架是以某种特定方式命名的单个 jpg 文件(在例子中,frame _ 0.jpg、 frame _ 1.jpg 等)。

注意,您可以考虑使用 (nframes, 480,640,3)形状的数组。

您可以使用 np.concatenate()使用 axis参数来指定应该连接的维度。如果被连接的数组没有这个维度,您可以使用 np.newaxis来指示应该在哪里添加新的维度:

import numpy as np
movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)

如果你正在阅读许多文件:

import glob
movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)

一个维度可以添加到一个数字数组,如下所示:

image = image[..., np.newaxis]

我采用了这种方法:

import numpy as np
import cv2


ls = []


for image in image_paths:
ls.append(cv2.imread('test.jpg'))


img_np = np.array(ls) # shape (100, 480, 640, 3)
img_np = np.rollaxis(img_np, 0, 4) # shape (480, 640, 3, 100).

或者

image = image[..., np.newaxis]

@ 幸福的答案中,你也可以使用 numpy.expand_dims

image = np.expand_dims(image, <your desired dimension>)

例如:

x = np.array([1, 2])


print(x.shape)  # prints (2,)

然后

y = np.expand_dims(x, axis=0)

产量

array([[1, 2]])

还有

y.shape

给予

(1, 2)

Numpy 中没有允许您以后追加更多数据的结构。

相反,numpy 将所有数据放入一个连续的数字块(基本上是一个 C 数组) ,任何调整都需要分配一个新的内存块来保存它。Numpy 的速度来自于能够将数字数组中的所有数据保存在同一块内存中; 例如,数学运算可以是 为了速度而平行化,而你得到的 缓存未命中更少。

所以你会有两种解决方案:

  1. 预先为 numpy 数组分配内存并填入值,如 JoshAdel 的答案,或者
  2. 将数据保存在普通的 python 列表中,直到实际需要将它们放在一起时为止(见下文)

images = []
for i in range(100):
new_image = # pull image from somewhere
images.append(new_image)
images = np.stack(images, axis=3)

请注意,不需要首先展开单个图像数组的维度,也不需要提前知道预期的图像数量。

考虑重塑方法的方法1和产生相同结果的 np.newaxis 方法的方法2:

#Lets suppose, we have:
x = [1,2,3,4,5,6,7,8,9]
print('I. x',x)


xNpArr = np.array(x)
print('II. xNpArr',xNpArr)
print('III. xNpArr', xNpArr.shape)


xNpArr_3x3 = xNpArr.reshape((3,3))
print('IV. xNpArr_3x3.shape', xNpArr_3x3.shape)
print('V. xNpArr_3x3', xNpArr_3x3)


#Approach 1 with reshape method
xNpArrRs_1x3x3x1 = xNpArr_3x3.reshape((1,3,3,1))
print('VI. xNpArrRs_1x3x3x1.shape', xNpArrRs_1x3x3x1.shape)
print('VII. xNpArrRs_1x3x3x1', xNpArrRs_1x3x3x1)


#Approach 2 with np.newaxis method
xNpArrNa_1x3x3x1 = xNpArr_3x3[np.newaxis, ..., np.newaxis]
print('VIII. xNpArrNa_1x3x3x1.shape', xNpArrNa_1x3x3x1.shape)
print('IX. xNpArrNa_1x3x3x1', xNpArrNa_1x3x3x1)

我们的结果是:

I. x [1, 2, 3, 4, 5, 6, 7, 8, 9]


II. xNpArr [1 2 3 4 5 6 7 8 9]


III. xNpArr (9,)


IV. xNpArr_3x3.shape (3, 3)


V. xNpArr_3x3 [[1 2 3]
[4 5 6]
[7 8 9]]


VI. xNpArrRs_1x3x3x1.shape (1, 3, 3, 1)


VII. xNpArrRs_1x3x3x1 [[[[1]
[2]
[3]]


[[4]
[5]
[6]]


[[7]
[8]
[9]]]]


VIII. xNpArrNa_1x3x3x1.shape (1, 3, 3, 1)


IX. xNpArrNa_1x3x3x1 [[[[1]
[2]
[3]]


[[4]
[5]
[6]]


[[7]
[8]
[9]]]]

蟒蛇

X = X[:, :, None]

相当于

X = X[:, :, numpy.newaxis]X = numpy.expand_dims(X, axis=-1)

但既然你明确要求叠加图像, 我会建议去叠加的图像 np.stack([X1, X2, X3])list,你可能已经收集在一个循环。

如果你不喜欢尺寸的顺序,你可以用 np.transpose()重新排列

这对我很有效:

image = image[..., None]

您可以使用的轴参数堆栈:

img.shape  # h,w,3
imgs = np.stack([img1,img2,img3,img4], axis=-1)   # -1 = new axis is last
imgs.shape #  h,w,3,nimages

例如: 将灰度转换为颜色:

>>> d = np.zeros((5,4), dtype=int)  # 5x4
>>> d[2,3] = 1


>>> d3.shape
Out[30]: (5, 4, 3)


>>> d3 = np.stack([d,d,d], axis=-2)  # 5x4x3   -1=as last axis
>>> d3[2,3]
Out[32]: array([1, 1, 1])

这将帮助您在任何需要的地方添加轴

    import numpy as np
signal = np.array([[0.3394572666491664, 0.3089068053925853, 0.3516359279582483], [0.33932706934615525, 0.3094755563319447, 0.3511973743219001], [0.3394407172182317, 0.30889042266755573, 0.35166886011421256], [0.3394407172182317, 0.30889042266755573, 0.35166886011421256]])
    

print(signal.shape)
#(4,3)
print(signal[...,np.newaxis].shape)  or  signal[...:none]
#(4, 3, 1)
print(signal[:, np.newaxis, :].shape)  or signal[:,none, :]


#(4, 1, 3)

有三个方面增加新的尺寸 ndarray。

首先: 使用“ np.newaxis”(类似于@dblisanswer)

  • Newaxis 只是给了 No 一个化名
    如果将 np.newwaxis 替换为 None,其工作原理是一样的
    但是最好使用 np.newaxis 来更加明确。
import numpy as np


my_arr = np.array([2, 3])
new_arr = my_arr[..., np.newaxis]


print("old shape", my_arr.shape)
print("new shape", new_arr.shape)


>>> old shape (2,)
>>> new shape (2, 1)

第二: 使用“ np.expo _ dims ()”

  • 在第一个参数和位置中指定原始 ndarray 在第二个参数轴中添加维度。
my_arr = np.array([2, 3])
new_arr = np.expand_dims(my_arr, -1)


print("old shape", my_arr.shape)
print("new shape", new_arr.shape)


>>> old shape (2,)
>>> new shape (2, 1)

第三: 使用“重塑()”

my_arr = np.array([2, 3])
new_arr = my_arr.reshape(*my_arr.shape, 1)


print("old shape", my_arr.shape)
print("new shape", new_arr.shape)


>>> old shape (2,)
>>> new shape (2, 1)
a = np.expand_dims(a, axis=-1)

或者

a = a[:, np.newaxis]

或者

a = a.reshape(a.shape + (1,))