正如您所暗示的那样,有一种方法可以实现这一目标
In [900]: M = np.lib.stride_tricks.as_strided(A, shape=(2,2,3,3), strides=(16,4,16,4))
In [901]: M
Out[901]:
array([[[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]],
[[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]]],
[[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]],
[[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]]]])
In [902]: M.reshape(4,3,3) # to get it in form you list
Out[902]:
array([[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]],
[[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]],
[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]],
[[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]]])
步伐的一个问题是,它是先进的,并且很难向没有多少经验的人解释.我想出了没有太多试验和错误的表格,但我已经在这里闲逛太久了. :)).
但是这个迭代解决方案更容易解释:
In [909]: alist=[]
In [910]: for i in range(2):
...: for j in range(2):
...: alist.append(A[np.ix_(range(i,i+3),range(j,j+3))])
...:
In [911]: alist
Out[911]:
[array([[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]]),
array([[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]]),
array([[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]]),
array([[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]])]
可以使用np.array(alist)将其转换为数组.如果它更清楚,使用它没有任何问题.
关于as_strided方法要记住的一件事是它是一个视图,对M的更改可能会改变A,而M中某个位置的更改可能会修改M中的几个位置.但重塑M可能会将其转换为副本.因此总体而言,从M读取值更安全,并将它们用于求和和均值等计算.到位的变化可能是不可预测的.
迭代解决方案可以生成副本.
使用np.ogrid而不是np.ix_的迭代解决方案(否则相同的想法):
np.array([A[np.ogrid[i:i+3, j:j+3]] for i in range(2) for j in range(2)])
ix_和ogrid都只是构造索引块的向量对的简单方法:
In [970]: np.ogrid[0:3, 0:3]
Out[970]:
[array([[0],
[1],
[2]]), array([[0, 1, 2]])]
同样的事情,但切片对象:
np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(2) for j in range(2)])
其列表版本具有与as_strided解决方案类似的视图行为(列表的元素是视图).
对于具有非重叠块的6×6,请尝试:
In [1016]: np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(0,6,3) for j i
...: n range(0,6,3)])
Out[1016]:
array([[[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15]],
[[ 4, 5, 6],
[10, 11, 12],
[16, 17, 18]],
[[19, 20, 21],
[25, 26, 27],
[31, 32, 33]],
[[22, 23, 24],
[28, 29, 30],
[34, 35, 36]]])
假设你想要连续的块,内部切片/范围不会改变,只是外部i和j的步进
In [1017]: np.arange(0,6,3)
Out[1017]: array([0, 3])