簡體   English   中英

numpy:連續 2d 切片的連續 3d 體積?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM