简体   繁体   English

numpy:连续 2d 切片的连续 3d 体积?

[英]numpy: contiguous 3d volume of contiguous 2d slices?

I want to load several 2D C contiguous image arrays into a 3D volume and access them in via intuitive indexing, eg slice3 = volume[:,:,2] which requires some reshaping from the original concatenated 1D representation.我想将几个 2D C 连续图像数组加载到 3D 卷中,并通过直观的索引访问它们,例如slice3 = volume[:,:,2]这需要对原始连接的 1D 表示进行一些重塑。

Now, since I load a lot of images and calculate even more new volumes from it which has to work on your average PC I'm concerned about memory usage as well as calculation performance.现在,由于我加载了大量图像并从中计算出更多新卷,这必须在您的普通 PC 上运行,因此我担心内存使用情况和计算性能。

Q: How can I achieve for the 3D volume as well as the 2D slices to remain contiguous, so I can efficiently do some stuff on the volume and some on individual slices.问:我怎样才能让 3D 体积和 2D 切片保持连续,这样我就可以有效地在体积上做一些事情,在单独的切片上做一些事情。

Here's some example to play with:这是一些可以玩的示例:

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.. :(

Again: Is there a way to achieve the desired slice indexing while keeping volume as well as individual slices C contiguous?再次:有没有办法在保持体积和单个切片 C 连续的同时实现所需的切片索引?

Option 1选项1

Don't get too hung up on which dimension corresponds to slices :不要太纠结于哪个维度对应于slices

a = a.reshape(slices, rows, cols)

Leave it at that.就这样吧。 A nice side-effect is that to get say slice 1 , you just do一个很好的副作用是要说 slice 1 ,你就做

a[1]

No need for a[1, :, :] or even a[1, ...] .不需要a[1, :, :]甚至a[1, ...]

Option 2选项 2

If you do get hung up on which dimension slices corresponds to, you have to copy the data to maintain contiguity.如果您确实纠结于哪个维度slices对应,则必须复制数据以保持连续性。 However, you can get there with just one copy, rather than using swapaxes twice.但是,您只需一份副本即可到达那里,而不是使用两次swapaxes

One way is to use transpose :一种方法是使用transpose

a = a.reshape(slices, rows, cols).transpose(1, 2, 0)

Or you can use np.moveaxis :或者你可以使用np.moveaxis

a = np.moveaxis(a.reshape(slices, rows, cols), 0, -1)

No, it is impossible for a 3D array a to be C-contiguous, and also for a[:,:,0] to be C-contiguous.不,3D 数组a不可能是 C 连续的, a[:,:,0]也不可能是 C 连续的。

Why?为什么? By definition, a C-contiguous array has a unit stride in the last dimension, For example根据定义,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]

For any C-contiguous array, slicing the last dimension will create a non-C-contiguous array, because it cannot have a unit stride in the last dimension:对于任何C-contiguous 数组,对最后一个维度进行切片将创建一个非 C-contiguous 数组,因为它在最后一个维度中不能有单位步长:

>>> b = a[:, :, 0]
>>> print([stride // b.itemsize for stride in b.strides])
[4, 2]

If you want your slices to be C-contiguous, you will need to slice in the first dimension and only the first dimension:如果您希望切片是 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