【问题标题】:Nearest Upsampling using Numpy使用 Numpy 进行最近上采样
【发布时间】:2021-05-12 14:29:55
【问题描述】:

假设我有,

x = [[1 ,2],
     [3 ,4]]

我喜欢拥有,

y = [[1 ,1 ,2 ,2],
     [1 ,1 ,2 ,2],
     [3 ,3 ,4 ,4],
     [3 ,3 ,4 ,4]]

我已经使用 repeat 做到了,但我的问题是,纯 numpy 中是否有一种更快且矢量化的方法。

我的第二个问题是,您如何有效地从 y 降到 x?

谢谢,祝你有美好的一天:)

【问题讨论】:

标签: python numpy image-processing


【解决方案1】:

使用np.kron() kronecker 产品:

x = np.array([[1, 2], [3, 4]])
y = np.kron(x,np.ones((2,2))   # np.ones((n,n)) where n indicate the number of repetition. 

【讨论】:

    【解决方案2】:

    如果你不关心输出的形状,你可以通过改变元数据来做这个操作

    x = np.array([[1, 2], [3, 4]])
    np.lib.stride_tricks.as_strided(x, (4,2,2), (8,0,0))
    

    输出:

    array([[[1, 1],
            [1, 1]],
    
           [[2, 2],
            [2, 2]],
    
           [[3, 3],
            [3, 3]],
    
           [[4, 4],
            [4, 4]]])
    

    此外,np.block 将提供所需的输出形状(通过复制)

    x = np.lib.stride_tricks.as_strided(x, (4,2,2), (8,0,0))
    np.block([[x[0], x[1]], 
              [x[2], x[3]]])
    

    输出:

    array([[1, 1, 2, 2],
           [1, 1, 2, 2],
           [3, 3, 4, 4],
           [3, 3, 4, 4]])
    

    np.block也可以使用transposereshape模拟:

    x = np.lib.stride_tricks.as_strided(x, (1,2,2,2,2), (32,16,0,8,0))
    x.reshape(4,4) # copy!
    

    输出:

    array([[1, 1, 2, 2],
           [1, 1, 2, 2],
           [3, 3, 4, 4],
           [3, 3, 4, 4]])
    

    不过,这会像np.block 一样复制内存。您可以尝试通过x.shape = (4,4) 直接设置形状来验证这一点:

    AttributeError: Incompatible shape for in-place modification. Use `.reshape()` to make a copy with the desired shape.
    

    以同样的方式,只需更改形状和步幅即可对输出进行下采样:

    np.lib.stride_tricks.as_strided(x, (2,2), (8*8,8*2))
    

    输出:

    array([[1, 2],
           [3, 4]])
    

    请注意,这是在没有任何复制的情况下完成的。我与8 相乘的原因是它是 64 位整数的字节大小。

    通用解决方案

    def upsample(x, k):
        return np.lib.stride_tricks.as_strided(x, (np.prod(x.shape), k, k), (x.dtype.itemsize, 0, 0))
    

    【讨论】:

    • 当我以某种方式运行第一个 sn-p 时,我的输出是:array([[[ 1, 1], [ 1, 1]], [[ 3, 3], [ 3, 3] ], [[ 1, 1], [1, 1]], [[462730709, 462730709], [462730709, 462730709]]])
    • 此版本未针对任何输入进行通用化。但原理是一样的,我将使用适用于任何数组的解决方案来编辑​​我的答案。
    • 谢谢!但输出是使用 x = np.array([[1, 2], [3, 4]])
    • 确保 x 的 dtype 是 64 位整数。尝试先运行x = x.astype(np.int64)
    • 我用第一个代码 sn-p 的通用解决方案编辑了我的答案。它应该适用于任何 dtype 和正上采样因子。这应该为您提供足够的信息,以使其他方法也适用于任何数组。
    【解决方案3】:

    你可以试试这个:使用简单的广播乘法,然后是转置和整形操作。

    x = np.array([[1, 2], [3, 4]])
    m, n = x.shape
    k = 2 # upsampling factor
    
    tmp = x.reshape(-1, 1, 1) * np.ones((1, k, k))
    y = tmp.reshape(m, n, k, k).transpose(0, 2, 1, 3).reshape(m*k, n*k)
    print(y)
    
    array([[1., 1., 2., 2.],
           [1., 1., 2., 2.],
           [3., 3., 4., 4.],
           [3., 3., 4., 4.]])
    

    要从y 中恢复x,只需反转reshape 和transpose 操作,并沿最后两个轴执行maxpool 类型的操作以获取原始m x n 形状的数组:

    x = y.reshape(m, n, k, k).transpose(0, 2, 1, 3).max(axis = (2, 3))
    

    此方法适用于任何形状 m x n 和上采样因子 k 的数组。

    【讨论】:

    • 太棒了!但我没有将其与重复进行基准测试。它在速度方面是否具有可比性?
    • 它在 cpu 上速度较慢,但​​在 gpu 上它完全优于 repeat
    猜你喜欢
    • 2022-10-03
    • 1970-01-01
    • 2023-03-24
    • 2015-02-06
    • 1970-01-01
    • 2017-06-12
    • 2014-05-04
    • 2010-09-06
    • 2017-12-19
    相关资源
    最近更新 更多