堆叠具有一个不同维度的多维numpy数组

时间:2017-07-18 20:49:31

标签: python arrays numpy multidimensional-array neural-network

好吧 - 假设我有两个numpy数组,形状是:

(185, 100, 50, 3)

(64,  100, 50, 3)

包含的值为185或64帧视频(对于每帧,宽度为100像素,高度为50,3个通道,这些只是图像。图像的细节保持不变 - 唯一改变的值是每个视频的帧数) 我需要把它们变成一个像

这样的形状的单个数组
(2, n, 100, 50, 3)

包含两个视频(作为批处理通过神经网络)

我已经尝试过使用np.stack了 - 但是我得到了

ValueError: all input arrays must have the same shape

2 个答案:

答案 0 :(得分:3)

这是一个快速的头脑风暴想法,我有战略和Python代码。注意:我只是坚持只是评论,但为了说明这个想法,我需要输入一些代码。所以我们走吧! (建议喝咖啡/浓烈的饮料......)

当前状态

  • 我们有4个vid1
  • 的视频1 (185, 100, 50, 3)
  • 我们有4个vid2
  • 的视频2 (64, 100, 50, 3)
  • ...形状代表(frame ID, width, height, RGB channels)
  • 我们希望将两个视频“叠加”为一个具有5D形状{n}的numpy数组(2, n, 100, 50, 3)。注意:2因为我们正在堆叠2个视频。 n是我们可以选择的超参数。我们保持视频大小相同(100 width x 50 height x 3 RGB channels

有机会

我看到的第一件事是vid1的帧数大约是vid2的3倍。我们使用60作为共同因素怎么样?即让我们将超参数n设置为60。 (注意:可能需要一些“框架裁剪”/“框架丢弃” - 这将在下面介绍。)

策略

阶段1 - 裁剪两个视频(扔掉一些帧)

让我们将vid1vid2裁剪为60(我们的n - 超参数)的倍数的漂亮整数。具体地:

  • 裁剪vid1,以便形状变为(180, 100, 50, 3)。 (即我们丢掉最后5帧)。我们称之为新的裁剪视频vid1_cropped
  • 裁剪vid2,以便形状变为(60, 100, 50, 3)。 (即我们丢掉最后4帧)。我们称之为新的裁剪视频vid2_cropped

第2阶段 - 将两个视频都设为60帧

  • vid2_cropped已经是60帧,形状为(60, 100, 50, 3)。所以我们不管这个。
  • vid1_cropped然而是180帧。所以我建议我们将这个视频减少到60帧,通过平均3帧批次的RGB通道值 - 对于所有像素位置(沿宽度和高度)。我们将在此过程结束时获得的是一个有点“稀释”(平均)的视频,其形状与vid2_cropped - (60, 100, 50, 3)相同。我们称之为稀释视频vid1_cropped_diluted

阶段3 - 将两个相同形状的视频叠加在一起

既然vid2_croppedvid1_cropped_diluted都具有相同的4D形状(60, 100, 50, 3)。我们可以将它们堆叠在一起以获得我们最终的5D形状(2, 60, 100, 50, 3) numpy数组 - 让我们称之为vids_combined

我们完成了!

演示

将策略转化为代码。我在Python 3.6(使用Jupyter Notebook / Jupyter Console)中做到了这一点。

一些注意事项:

  • 我还没有验证代码(并根据需要进行了修改)。在此期间如果你看到任何错误请大声说 - 我很乐意更新。

  • 我对“稀释”(np.average step)下面的第10行感觉可能包含错误。即,对于所有像素位置,我的意思是仅针对RGB通道值执行3帧平均。我需要仔细检查语法。 (与此同时请查看第10行!)

  • 这篇文章说明了概念和一些代码实现。理想情况下,我会通过更小的视频尺寸更深入地逐步完成这一过程,这样我们就可以逐像素地获得更好的直觉/可视化每一步。 (当我有时间时,我可能会回到这里)。目前,我认为numpy数组形状分析足以传达这个想法。

In [1]: import numpy as np

In [2]: vid1 = np.random.random((185, 100, 50, 3))

In [3]: vid1.shape
Out[3]: (185, 100, 50, 3)

In [4]: vid2 = np.random.random((64, 100, 50, 3))

In [5]: vid2.shape
Out[5]: (64, 100, 50, 3)

In [6]: vid1_cropped = vid1[:180]

In [7]: vid1_cropped.shape
Out[7]: (180, 100, 50, 3)

In [8]: vid2_cropped = vid2[:60]

In [9]: vid2_cropped.shape
Out[9]: (60, 100, 50, 3)

In [10]: vid1_cropped_diluted = np.average(vid1_cropped.reshape(3,60,100,50,3),
       : axis=0)

In [11]: vid1_cropped_diluted.shape
Out[11]: (60, 100, 50, 3)

In [12]: vids_combined = np.stack([vid1_cropped_diluted, vid2_cropped])

In [13]: vids_combined.shape
Out[13]: (2, 60, 100, 50, 3)

答案 1 :(得分:-1)

您无法堆叠具有不同维度的数组,因为您需要为每个维度添加值。

因此,您的选择是:

  1. 根本不使用数组,只需使用python列表
  2. 用零填充数组直到它们是相同的形状
  3. 将数组重新采样为相同的形状
  4. Atlas7的答案是3的实现,但您可能会以某种方式更好地使用scipy.ndimage.zoom,以获得更灵活的解决方案