如何向 Numpy 数组添加新维度?
- 2025-03-04 08:23:00
- admin 原创
- 92
问题描述:
我从一个图像的 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 数组)添加到我的初始数组的最佳方法是什么?
解决方案 1:
可以按如下方式向 numpy 数组添加维度:
image = image[..., np.newaxis]
解决方案 2:
或者
image = image[..., np.newaxis]
在@dbliss的回答中,你也可以使用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)
解决方案 3:
您可以预先创建一个正确大小的数组并填充它:
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)
形状数组。
解决方案 4:
Python 式的
X = X[:, :, None]
相当于
X = X[:, :, numpy.newaxis]
和X = numpy.expand_dims(X, axis=-1)
但是由于您明确询问有关堆叠图像的问题,我建议您堆叠可能在循环中收集的list
图像。np.stack([X1, X2, X3])
如果你不喜欢维度的顺序,你可以重新排列np.transpose()
解决方案 5:
a = np.expand_dims(a, axis=-1)
或者
a = a[:, np.newaxis]
或者
a = a.reshape(a.shape + (1,))
解决方案 6:
您可以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)
解决方案 7:
考虑使用重塑方法的方法 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]]]]
解决方案 8:
numpy 中没有允许您稍后添加更多数据的结构。
相反,numpy 将所有数据放入一个连续的数字块(基本上是 C 数组),并且任何调整大小都需要分配一个新的内存块来保存它。Numpy 的速度来自于能够将 numpy 数组中的所有数据保存在同一块内存中;例如,数学运算可以并行化以提高速度,并且缓存未命中率更低。
因此你会有两种解决方案:
预先分配 numpy 数组的内存并填写值,如 JoshAdel 的答案中所述,或者
将数据保存在普通的 Python 列表中,直到真正需要将它们放在一起(见下文)
images = []
for i in range(100):
new_image = # pull image from somewhere
images.append(new_image)
images = np.stack(images, axis=3)
请注意,无需先扩展单个图像数组的尺寸,也不需要提前知道预计有多少张图像。
解决方案 9:
您可以将堆栈与轴参数一起使用:
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])
解决方案 10:
我遵循了这种方法:
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).
解决方案 11:
这对我有用:
image = image[..., None]
解决方案 12:
这将帮助你在任何你想要的地方添加轴
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)
解决方案 13:
有三种方法可以向 ndarray 添加新维度。
首先:使用“np.newaxis”(类似于@dbliss 答案)
np.newaxis 只是为了更容易理解而赋予了 None 的别名
。如果你用 None 替换 np.newaxis,它的工作方式相同
。但最好使用 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.expand_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)
第三:使用“reshape()”
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)
扫码咨询,免费领取项目管理大礼包!