Python Numpy-创建重叠的3D子阵列作为矢量,该矢量为';内存效率

Python Numpy-创建重叠的3D子阵列作为矢量,该矢量为';内存效率,python,memory-management,image-processing,tree,numpy,Python,Memory Management,Image Processing,Tree,Numpy,我正试图从一个较大的3D阵列(用于基于面片的分割)中创建一个相同大小的所有重叠子阵列的列表,其中每个子阵列都需要展平(作为1D向量),以便我可以利用sklearn.neights.BallTree中的球树 例如,给定一张100x100x100的图像,如果我把它分解成5x5x5个重叠的面片(子阵列),我会得到其中的96x96x96=884736 但是,如果不为每个展平/矢量化子阵列分配更多内存,我还没有找到任何这样做的方法。这似乎是因为每个子阵列在内存中不是连续的 e、 g.对于100x100x1

我正试图从一个较大的3D阵列(用于基于面片的分割)中创建一个相同大小的所有重叠子阵列的列表,其中每个子阵列都需要展平(作为1D向量),以便我可以利用sklearn.neights.BallTree中的球树

例如,给定一张100x100x100的图像,如果我把它分解成5x5x5个重叠的面片(子阵列),我会得到其中的96x96x96=884736

但是,如果不为每个展平/矢量化子阵列分配更多内存,我还没有找到任何这样做的方法。这似乎是因为每个子阵列在内存中不是连续的

e、 g.对于100x100x100图像,如果我想将每个5x5x5面片作为1D向量(长度为125),numpy决定在内存中为所有884736面片分配一个全新的阵列,该阵列将变得相当大,尤其是如果我想处理多个100x100x100图像


我欢迎任何在python/numpy中克服这一内存挑战的解决方案。我曾考虑创建numpy.ndarray对象的子类,该对象在较大的图像中存储指向修补程序位置的指针,但仅在调用时以1D numpy数组的形式返回数据(在未使用时,该数组将再次删除),但在子类化ndarray对象方面,我没有遇到足够的细节。如果唯一的解决方案是用C/C++实现所有东西,我会非常失望。我很感激能提供的任何帮助,谢谢

根据你的问题,你可能已经意识到了这一切。然而,我发布这个“答案”更多的是讨论问题是什么,因为很多人可能没有意识到它们

如果您没有,您可以从充当移动窗口的
100x100x100
图像创建
96x96x96x5x5x5
数组,而无需分配任何额外内存

但是,由于每个维度只能有一个跨步,因此在不复制的情况下无法将其重塑为
96x96x96x125
阵列

无论如何,这里有一个例子(基本上是这样的):

但是,正如您已经注意到的,如果不创建副本,我们无法将其重塑为
96x96x96x125
y.shape=(96,96,96,-1)
将引发错误,
z=y.restrape((96,96,96,-1))
将起作用,但将返回副本

(相关文档位于
numpy中。如果这看起来令人困惑,则重塑
。基本上
重塑
将在可能时避免复制,如果没有,则返回副本,而设置
形状
属性将在无法复制时引发错误。)

然而,即使您构建了一个更高效的数组容器,
sklearn.neights.BallTree
几乎肯定会生成临时的中间副本


你提到你在做图像分割。为什么不研究一种更有效的算法,而不是你似乎在尝试的“蛮力”?(或者,如果这不可行,请向我们提供更多的细节,说明为什么……也许有人会有更好的想法?

在scipy tooThis中使用kdtree也需要矢量化图像数据。基于贴片的分割方法基于所述方法,该方法已被证明比其他“更有效”的方法具有更好的结果分割算法。然而,我希望在更大范围内试验这个想法,但是如果使用python/numpy,内存需求会禁止我这样做。如果有一种不需要重新实现的方法来解决这个问题,那就太好了。
import numpy as np

def rolling_window_lastaxis(a, window):
    """Directly taken from Erik Rigtorp's post to numpy-discussion.
    <http://www.mail-archive.com/numpy-discussion@scipy.org/msg29450.html>"""
    if window < 1:
       raise ValueError, "`window` must be at least 1."
    if window > a.shape[-1]:
       raise ValueError, "`window` is too long."
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

def rolling_window(a, window):
    """Takes a numpy array *a* and a sequence of (or single) *window* lengths
    and returns a view of *a* that represents a moving window."""
    if not hasattr(window, '__iter__'):
        return rolling_window_lastaxis(a, window)
    for i, win in enumerate(window):
        if win > 1:
            a = a.swapaxes(i, -1)
            a = rolling_window_lastaxis(a, win)
            a = a.swapaxes(-2, i)
    return a

x = np.zeros((100,100,100), dtype=np.uint8)
y = rolling_window(x, (5,5,5))
print 'Now *y* will be a 96x96x96x5x5x5 array...'
print y.shape
print 'Representing a "rolling window" into *x*...'
y[0,0,0,...] = 1
y[1,1,0,...] = 2
print x[:10,:10,0] # Note that *x* and *y* share the same memory!
Now *y* will be a 96x96x96x5x5x5 array...
(96, 96, 96, 5, 5, 5)
Representing a "rolling window" into *x*...
[[1 1 1 1 1 0 0 0 0 0]
 [1 2 2 2 2 2 0 0 0 0]
 [1 2 2 2 2 2 0 0 0 0]
 [1 2 2 2 2 2 0 0 0 0]
 [1 2 2 2 2 2 0 0 0 0]
 [0 2 2 2 2 2 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]