numpy.rot90 对 3D 和更高阶数组的旋转的视觉理解,维数大于 3 的 ndarrays

visual understanding of rotation by numpy.rot90 for 3D and higher order arrays, ndarrays of dimension greater than 3

我试图理解 3D numpy 数组的单个 90 度旋转,但发现很难形象化(因此很难理解旋转过程本身)。

对于二维的情况,似乎很容易做到。例如,考虑以下代码片段,它对二维数组进行 90 度逆时针旋转:

In [222]: m = np.arange(6).reshape((2,3))

In [223]: m
Out[223]: 
array([[0, 1, 2],
       [3, 4, 5]])

二维阵列的 90° 变换

      <--------\
array([[0, 1, 2],\   # anti-clockwise
       [3, 4, 5]])\  # rotation
                   \
           ||

In [224]: np.rot90(m)
Out[224]: 
array([[2, 5],
       [1, 4],
       [0, 3]])

但是对于 3D 和更高维数组,事情变得复杂了。同样,作为示例,让我们考虑一个简单的 3D 数组:

In [219]: m = np.arange(12).reshape((2,2,3))

In [220]: m
Out[220]: 
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])

In [221]: np.rot90(m)
Out[221]: 
array([[[ 3,  4,  5],
        [ 9, 10, 11]],

       [[ 0,  1,  2],
        [ 6,  7,  8]]])

查看上面的输出,我无法理解旋转对数组的作用。是否有简化的流程来理解这种转变?形状我也看了,差不多,这就更难理解了

In [227]: np.rot90(m).shape
Out[227]: (2, 2, 3)

我对理解这个转换特别感兴趣,因为它总是 returns 原始数组缓冲区的一个新的“view”,这对写作非常有用在内存和时间方面的高性能代码。如果您对此有任何想法,请分享!

根据转置和翻转表达您的 2d 案例:

In [182]: m = np.arange(6).reshape((2,3))                                            

In [183]: m                                                                          
Out[183]: 
array([[0, 1, 2],
       [3, 4, 5]])

In [184]: m.transpose(1,0)                                                           
Out[184]: 
array([[0, 3],
       [1, 4],
       [2, 5]])

In [185]: m.transpose(1,0)[::-1, :]                                                  
Out[185]: 
array([[2, 5],
       [1, 4],
       [0, 3]])

在 3d 情况下,它似乎做同样的事情 - 第 3 轴标记:

In [188]: m.transpose(1,0,2)[::-1, :]                                                
Out[188]: 
array([[[ 3,  4,  5],
        [ 9, 10, 11]],

       [[ 0,  1,  2],
        [ 6,  7,  8]]])

如果我指定第二对轴,它会做同样的事情,但第一对会继续运行:

In [189]: np.rot90(m, axes=(1,2))                                                    
Out[189]: 
array([[[ 2,  5],
        [ 1,  4],
        [ 0,  3]],

       [[ 8, 11],
        [ 7, 10],
        [ 6,  9]]])

In [190]: _.shape                                                                    
Out[190]: (2, 3, 2)

In [191]: m.transpose(0,2,1)[:,::-1, :]                                              
Out[191]: 
array([[[ 2,  5],
        [ 1,  4],
        [ 0,  3]],

       [[ 8, 11],
        [ 7, 10],
        [ 6,  9]]])

不同的k需要不同的策略。例如 2 我打赌它只是翻转。

===

Out[188]显示并不能帮助我们可视化旋转,因为它涉及第一维平面和第二维行。但是如果我们选择一个 3 维列,并比较原始和旋转,我们可以看到相同的 2d 旋转:

In [192]: m[:,:,0]                                                                   
Out[192]: 
array([[0, 3],
       [6, 9]])

In [193]: Out[188][:,:,0]                                                            
Out[193]: 
array([[3, 9],
       [0, 6]])

3d 数组并不总是表示 3d 直角棱镜。它可以改为具有 3 个颜色通道的 2d 图像。这个 m 旋转然后在不改变颜色的情况下旋转图像。默认 'plane/row/column' 显示并不能帮助我们形象化这样的图像。