【问题标题】:Reverse skimage view_as_blocks() with numpy.reshape()使用 numpy.reshape() 反转 skimage view_as_blocks()
【发布时间】:2020-05-10 01:41:54
【问题描述】:

我想将具有 2 个通道的 4x4 图像划分为多个不重叠的正方形。

之后,我想重建图像。

from skimage.util import view_as_blocks

# create testM array 
array([[[[0.53258505, 0.31525832, 0.21378392, 0.5019507 ],
         [0.31612498, 0.24320562, 0.93560226, 0.08232264],
         [0.89784454, 0.12741783, 0.88049819, 0.29542855],
         [0.11336386, 0.71023215, 0.45679456, 0.2318959 ]],

        [[0.61038755, 0.74389586, 0.85199794, 0.46680889],
         [0.01701045, 0.93953861, 0.03183684, 0.00740579],
         [0.58878569, 0.71348253, 0.33221104, 0.12276253],
         [0.04026615, 0.53837528, 0.06759152, 0.27477069]]]])

# use view_as_blocks() to get "grid" image
testB = view_as_blocks(testM, block_shape=(1,2,2,2)).reshape(-1,*(1,2,2,2))

现在我有这个大小为 2x2 的数组的多个块:

array([[[[[0.53258505, 0.31525832],
          [0.31612498, 0.24320562]],

         ...

         [[0.33221104, 0.12276253],
          [0.06759152, 0.27477069]]]]])


但是,我无法将其重塑回原来的形状

testB.reshape(1,2,4,4)

导致这一点。每个“块”只是一个接一个地附加一个值,但不被视为一个块。

array([[[[0.53258505, 0.31525832, 0.31612498, 0.24320562],
         [0.61038755, 0.74389586, 0.01701045, 0.93953861],
         [0.21378392, 0.5019507 , 0.93560226, 0.08232264],
         [0.85199794, 0.46680889, 0.03183684, 0.00740579]],

        [[0.89784454, 0.12741783, 0.11336386, 0.71023215],
         [0.58878569, 0.71348253, 0.04026615, 0.53837528],
         [0.88049819, 0.29542855, 0.45679456, 0.2318959 ],
         [0.33221104, 0.12276253, 0.06759152, 0.27477069]]]])

在使用reshape() 之前,我已经尝试了多个.swapaxes(),但都无法正常工作。

【问题讨论】:

  • 尝试混合使用重塑、转置(或交换)和重塑,例如arr1.reshape(2,2,2,2,2).transpose(0,1,3,2,4).reshape(2,4,4)
  • 你在两个reshapes之间做什么?避免这些可能很简单,就像使用 np.ndindex 作为 for 循环迭代器,而不是在第一个维度上循环。
  • @hpaulj:我尝试了几种变体,但经过大量尝试后找不到合适的变体
  • @DanielF:我正在使用skimage 将图像划分为非重叠块。

标签: python numpy multidimensional-array reshape scikit-image


【解决方案1】:
In [30]: testM=np.array([[[[0.53258505, 0.31525832, 0.21378392, 0.5019507 ], 
    ...:          [0.31612498, 0.24320562, 0.93560226, 0.08232264], 
    ...:          [0.89784454, 0.12741783, 0.88049819, 0.29542855], 
    ...:          [0.11336386, 0.71023215, 0.45679456, 0.2318959 ]], 
    ...:  
    ...:         [[0.61038755, 0.74389586, 0.85199794, 0.46680889], 
    ...:          [0.01701045, 0.93953861, 0.03183684, 0.00740579], 
    ...:          [0.58878569, 0.71348253, 0.33221104, 0.12276253], 
    ...:          [0.04026615, 0.53837528, 0.06759152, 0.27477069]]]]) 
    ...:                                                                                         
In [31]: testM.shape                                                                             
Out[31]: (1, 2, 4, 4)
In [32]: from skimage.util import view_as_blocks                                                 
In [33]: testB = view_as_blocks(testM, block_shape=(1,2,2,2))                                    
In [34]: testB.shape                                                                             
Out[34]: (1, 1, 2, 2, 1, 2, 2, 2)

这真的是你想要的形状吗?无论如何,应用重塑,结合最初的 4 个维度:

In [36]: testB.reshape(-1,*(1,2,2,2)).shape                                                      
Out[36]: (4, 1, 2, 2, 2)

当我建议时

arr1.reshape(2,2,2,2,2).transpose(0,1,3,2,4).reshape(2,4,4)

我在想形状为 (2,4,4) 的源被分为 (2,2) 窗口。也就是说,每个 (4,4) 子数组变成了 (2,2,2,2) 数组,即 (2,2) 块的 (2,2) 数组。有许多尺寸 2 和 4 尺寸,很难跟踪哪个是哪个。

这是我的目标转变:

In [62]: testM1 = testM[0,0,:,:]                                                                 
In [63]: testM1                                                                                  
Out[63]: 
array([[0.53258505, 0.31525832, 0.21378392, 0.5019507 ],
       [0.31612498, 0.24320562, 0.93560226, 0.08232264],
       [0.89784454, 0.12741783, 0.88049819, 0.29542855],
       [0.11336386, 0.71023215, 0.45679456, 0.2318959 ]])
In [64]: testB1 = view_as_blocks(testM1, block_shape=(2,2))                                      
In [65]: testB1.shape                                                                            
Out[65]: (2, 2, 2, 2)
In [66]: testB1.transpose(0,2,1,3).reshape(4,4)                                                  
Out[66]: 
array([[0.53258505, 0.31525832, 0.21378392, 0.5019507 ],
       [0.31612498, 0.24320562, 0.93560226, 0.08232264],
       [0.89784454, 0.12741783, 0.88049819, 0.29542855],
       [0.11336386, 0.71023215, 0.45679456, 0.2318959 ]])

取一个 (4,4) 块并分成 (2,2,2,2) 个窗口,然后返回。

我怀疑同样的转换适用于您更复杂的维度,但我没有时间(或兴趣)来解决细节。

【讨论】:

    【解决方案2】:

    发生的事情是您的.reshape((-1, 1, 2, 2, 2)),即您的块线性化,正在导致复制:

    import numpy as np
    from skimage.util import view_as_blocks
    
    arr = np.arange(24).astype(np.uint8).reshape((4, 6))
    blocked = view_as_blocks(arr, (2, 3))
    blocked_reshaped = blocked.reshape((-1, 2, 3))
    print(arr.shape)
    print(arr.strides)
    print(blocked.shape)
    print(blocked.strides)
    print(blocked_reshaped.shape)
    print(blocked_reshaped.strides)
    print(np.may_share_memory(blocked, blocked_reshaped))
    

    结果:

    (4, 6)
    (6, 1)
    (2, 2, 2, 3)
    (12, 3, 6, 1)
    (4, 2, 3)
    (6, 3, 1)
    False
    

    步幅表明数组的元素在底层内存中不再具有相同的线性顺序,因此重塑会导致您观察到的奇怪转置:

    block_reshaped_orig = blocked_reshaped.reshape((4, 6))
    print(arr)
    print(block_reshaped_orig)
    

    结果:

    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    [[ 0  1  2  6  7  8]
     [ 3  4  5  9 10 11]
     [12 13 14 18 19 20]
     [15 16 17 21 22 23]]
    

    我看到两个选项:

    • 如果您可以避免整形和复制,那么最后的整形调用就可以正常工作。
    • 如果您需要对正在执行的其他一些处理进行 reshape,那么具有讽刺意味的是,您可以使用另一个 view_as_blocks 调用并 reshape 来恢复原始订单:
    print(
        view_as_blocks(blocked_reshaped_orig, (2, 3)).reshape((4, -1))
    )
    

    结果:

    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    

    我希望这会有所帮助!

    【讨论】:

    • 感谢您的意见!我确实可以用二维数组重现它。然而,对于 3d 数组(不幸的是我需要 3d 数组),我在重新应用 view_as_blocks() 时找不到正确的设置,数组总是混淆...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 2018-09-16
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多