[英]numpy: contiguous 3d volume of contiguous 2d slices?
我想將幾個 2D C 連續圖像數組加載到 3D 卷中,並通過直觀的索引訪問它們,例如slice3 = volume[:,:,2]
這需要對原始連接的 1D 表示進行一些重塑。
現在,由於我加載了大量圖像並從中計算出更多新卷,這必須在您的普通 PC 上運行,因此我擔心內存使用情況和計算性能。
問:我怎樣才能讓 3D 體積和 2D 切片保持連續,這樣我就可以有效地在體積上做一些事情,在單獨的切片上做一些事情。
這是一些可以玩的示例:
import numpy as np
# dimensions:
rows = 2
cols = 2
slices = 3
# create array
a = np.arange(rows*cols*slices)
print(a)
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
# this is the original concatenated input of the slices [[0,1],[2,3]], [[4,5],[6,7]], [[8,9],[10,11]]
# a contiguous?
print(a.flags['C_CONTIGUOUS'])
# True
a = a.reshape(rows,cols,slices)
print(a)
# a still contiguous?
print(a.flags['C_CONTIGUOUS'])
# True
# what about a slice?
print(a[:,:,0])
# [[0 3]
# [6 9]]
# ouch! that's not the slice I wanted! I wanted to keep [[0,1],[2,3]] together
# this slice is of course also not contiguous:
print(a[:,:,0].flags['C_CONTIGUOUS'])
# False
# ok, let's start over
a = a.ravel()
print(a)
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
a = a.reshape(slices,rows,cols)
a = a.swapaxes(0,1)
a = a.swapaxes(1,2)
# what about a slice?
print(a[:,:,0])
# [[0 1]
# [2 3]]
# now that's the kind of slice I wanted!
# a still contiguous?
print(a.flags['C_CONTIGUOUS'])
# False
# slice contiguous?
print(a[:,:,0].flags['C_CONTIGUOUS'])
# True
# only halfway there.. :(
再次:有沒有辦法在保持體積和單個切片 C 連續的同時實現所需的切片索引?
選項1
不要太糾結於哪個維度對應於slices
:
a = a.reshape(slices, rows, cols)
就這樣吧。 一個很好的副作用是要說 slice 1
,你就做
a[1]
不需要a[1, :, :]
甚至a[1, ...]
。
選項 2
如果您確實糾結於哪個維度slices
對應,則必須復制數據以保持連續性。 但是,您只需一份副本即可到達那里,而不是使用兩次swapaxes
。
一種方法是使用transpose
:
a = a.reshape(slices, rows, cols).transpose(1, 2, 0)
或者你可以使用np.moveaxis
:
a = np.moveaxis(a.reshape(slices, rows, cols), 0, -1)
不,3D 數組a
不可能是 C 連續的, a[:,:,0]
也不可能是 C 連續的。
為什么? 根據定義,C-contiguous 數組在最后一維有一個單位步長,例如
>>> a = np.arange(rows*cols*slices)
>>> a = a.reshape(slices,rows,cols)
>>> print([stride // a.itemsize for stride in a.strides])
[4, 2, 1]
對於任何C-contiguous 數組,對最后一個維度進行切片將創建一個非 C-contiguous 數組,因為它在最后一個維度中不能有單位步長:
>>> b = a[:, :, 0]
>>> print([stride // b.itemsize for stride in b.strides])
[4, 2]
如果您希望切片是 C 連續的,則需要在第一個維度和第一個維度中切片:
>>> c = a[0, :, :]
>>> print([stride // c.itemsize for stride in c.strides])
[2, 1]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.