137

我从一个图像的 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 阵列)添加到我的初始阵列的最佳方法是什么?

4

10 回答 10

159

您正在询问如何向 NumPy 数组添加维度,以便可以增长该维度以容纳新数据。可以按如下方式添加维度:

image = image[..., np.newaxis]
于 2014-09-10T00:47:26.693 回答
85

或者

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

@dbliss 的回答中,你也可以使用numpy.expand_dimslike

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)
于 2017-04-30T16:15:37.537 回答
31

您可以预先创建一个正确大小的数组并填充它:

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)异形阵列。

于 2013-06-30T21:24:25.357 回答
22

蟒蛇式

X = X[:, :, None]

这相当于

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

但是,当您明确询问堆叠图像时,我建议您将您可能在循环中收集list的图像堆叠起来。np.stack([X1, X2, X3])

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

于 2020-01-06T02:05:29.960 回答
8

您可以使用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)
于 2013-07-01T15:13:11.320 回答
3

考虑使用 reshape 方法的方法 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]]]]
于 2019-06-17T13:49:14.940 回答
2

这对我有用:

image = image[..., None]
于 2021-02-15T09:32:46.890 回答
2

numpy 中没有允许您稍后附加更多数据的结构。

相反,numpy 将所有数据放入一个连续的数字块中(基本上是一个 C 数组),并且任何调整大小都需要分配一个新的内存块来保存它。Numpy 的速度来自于能够将 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)

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

于 2017-11-06T07:15:51.873 回答
1

我遵循了这种方法:

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).
于 2016-06-21T07:44:53.740 回答
0

您可以将堆栈与轴参数一起使用:

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])
于 2022-01-27T20:07:13.197 回答