根据您的问题,您可能已经知道这一切。但是,我发布这个“答案”更多是为了讨论问题是什么,因为很多人可能不知道它们......
如果不是,您可以从 100x100x100 图像创建一个 96x96x96x5x5x5 数组,充当5x5x5 移动窗口,而无需分配任何额外的内存。
但是,由于每个维度只能有一个步幅,因此无法在不复制的情况下将其重塑为 96x96x96x125 数组。
无论如何,这是一个例子(基本上是straight from one of my previous answers):
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]]
但是,正如您已经指出的,我们无法在不创建副本的情况下将其改造成 96x96x96x125。 y.shape = (96,96,96,-1) 会引发错误,z = y.reshape((96,96,96,-1)) 会起作用,但会返回一个副本。
(如果这看起来令人困惑,相关文档在numpy.reshape 中。基本上reshape 将尽可能避免复制,如果不是则返回副本,而设置shape 属性将在复制时引发错误'不可能。)
但是,即使您构建了更高效的数组容器,sklearn.neighbors.BallTree 也几乎肯定会制作临时中间副本。
你提到你正在做图像分割。为什么不研究一种比您似乎正在尝试的“蛮力”更有效的算法呢? (或者如果这不可行,请告诉我们更多细节,说明原因……也许有人会有更好的主意?)