Исходя из вашего вопроса, вы уже можете знать обо всем этом. Тем не менее, я публикую этот «ответ» как более подробное обсуждение проблем, потому что многие люди могут не знать о них ....
Если вы этого не сделаете, вы можете создать массив 96x96x96x5x5x5
из изображения 100x100x100
, который действует как движущееся окно 5x5x5
, без выделения дополнительной памяти.
Однако, поскольку вы можете иметь только один шаг на измерение, нет способа преобразовать его в массив 96x96x96x125
без создания копии.
Во всяком случае, вот пример (в основном взят прямо из одного из моих предыдущих ответов ):
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
почти наверняка сделает временные промежуточные копии.
Вы упоминаете, что делаете сегментацию изображения. Почему бы не взглянуть на более эффективный алгоритм, чем "грубая сила", которую вы пытаетесь использовать? (Или, если это неосуществимо, дайте нам еще несколько подробностей о том, почему ... Может быть, у кого-то будет идея получше?)