为了理解我要实现的目标,让我们想象一个形状为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)
的块作为“原子大小”。
希望这足够清楚!
答案 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