将Numpy数组整形为形状为(n,n,n)的立方体的字典表

时间:2020-07-09 19:50:42

标签: python numpy scipy

为了理解我要实现的目标,让我们想象一个形状为a的ndarray (8,8,8),从字典上我从中取出形状为(4,4,4)的块。因此,在遍历此类块时,索引将如下所示:

0: a[0:4, 0:4, 0:4]  
1: a[0:4, 0:4, 4:8]  
2: a[0:4, 4:8, 0:4]  
3: a[0:4, 4:8, 4:8]  
4: a[4:8, 0:4, 0:4]  
5: a[4:8, 0:4, 4:8]  
6: a[4:8, 4:8, 0:4]  
7: a[4:8, 4:8, 4:8]  

正是我要访问的这些数据块。显然,这可以通过使用将当前迭代转换为相应索引的表达式来描述。下面是一个示例。

a = np.ones((8,8,8))
f = 4

length = round(a.shape[0] * a.shape[1] * a.shape[2] / f**3)

x = a.shape[0] / f
y = a.shape[1] / f
z = a.shape[2] / f

for i in range(length):
    print(f"{i}: {round((int(i/(z*y))%x)*f)}:{round(f+(int(i/(z*y))%x)*f)}, {round((int(i/z)%y)*f)}:{round(f+(int(i/z)%y)*f)}, {round((i%z)*f)}:{round(f+(i%z)*f)}")

我很抱歉必须这样做,但它会产生以下输出:

0: 0:4, 0:4, 0:4
1: 0:4, 0:4, 4:8
2: 0:4, 4:8, 0:4
3: 0:4, 4:8, 4:8
4: 4:8, 0:4, 0:4
5: 4:8, 0:4, 4:8
6: 4:8, 4:8, 0:4
7: 4:8, 4:8, 4:8

因此,这实际上会生成正确的索引,但是,如果它们在第0轴和第1轴上具有相同的索引,则只允许您一次访问多个块,因此不会回绕。理想情况下,我会将整个ndarray整形为形状为b的ndarray (4, 4, 32),并按以下方式进行排序:b[:, :, :4]将返回a[0:4, 0:4, 0:4]b[:, :, 4:12]返回一个形状为(4, 4, 8)的ndarray,其中包含a[0:4, 0:4, 4:8]a[0:4, 4:8, 0:4]等。我希望此速度尽可能快,因此理想情况下,我保留内存布局并只更改数组的视图。
最后,如果可以从概念上考虑这一点,那么这基本上是ndarray.flatten()方法的一种变体,但是如果可以的话,可以使用形状为(4, 4, 4)的块作为“原子大小”。

希望这足够清楚!

2 个答案:

答案 0 :(得分:2)

您不清楚要输出什么。您在寻找这个吗?

from skimage.util.shape import view_as_windows
b = view_as_windows(a,(f,f,f),f).reshape(-1,f,f,f).transpose(1,2,3,0).reshape(f,f,-1)

@Paul建议的结果类似(实际上我更喜欢这个答案):

N = 8
b = a.reshape(2,N//2,2,N//2,N).transpose(1,3,0,2,4).reshape(N//2,N//2,N*4)

输出:

print(np.array_equal(b[:, :, 4:8],a[0:4, 0:4, 4:8]))
#True
print(np.array_equal(b[:, :, 8:12],a[0:4, 4:8, 0:4]))
#True
print(np.array_equal(b[:, :, 12:16],a[0:4, 4:8, 4:8]))
#True

答案 1 :(得分:-1)

def flatten_by(arr, atomic_size):
    a, b, c = arr.shape
    x, y, z = atomic_size
    
    r = arr.reshape([a//x, x, b//y, y, c//z, z])
    r = r.transpose([0, 2, 4, 1, 3, 5])
    r = r.reshape([-1, x, y, z])
    
    return r
flatten_by(arr, [4,4,4]).shape

>>>   (8, 4, 4, 4)

编辑:

该函数将C样式展平应用于数组,如下所示

注意: 此方法和@Ehsan的方法都产生“副本”而不是“视图”,即时调查它,并且如果我找到解决方案,则会更新答案

flattened = flatten_by(arr, [4,4,4])

required = np.array([
    arr[0:4, 0:4, 0:4],
    arr[0:4, 0:4, 4:8],  
    arr[0:4, 4:8, 0:4],  
    arr[0:4, 4:8, 4:8],  
    arr[4:8, 0:4, 0:4],  
    arr[4:8, 0:4, 4:8],  
    arr[4:8, 4:8, 0:4],  
    arr[4:8, 4:8, 4:8],  
])
np.array_equal(required, flattened)

>>> True