【问题标题】:Efficiently applying function over moving window numpy array在移动窗口numpy数组上有效地应用函数
【发布时间】:2016-09-27 14:34:08
【问题描述】:

我有大约 100,000 个二维数组,我需要在其中应用本地过滤器。两个尺寸都有一个均匀的大小,窗口超过 2x2 块并进一步移动 2 块,因此每个元素都在一个窗口中一次。输出是一个相同大小的二进制二维数组,我的过滤器也是一个二进制 2x2 块。过滤器中为 0 的部分将映射为 0,过滤器中为 1 的部分如果具有相同的值则全部映射为 1,如果它们不完全相同则映射为 0。这是一个例子:

Filter:  0 1     Array to filter:  1 2 3 2    Output:  0 1 0 0
         1 0                       2 3 3 3             1 0 0 0

当然,我可以使用双 for 循环来做到这一点,但这非常低效,必须有更好的方法。我读到这个:Vectorized moving window on 2D array in numpy 但是我不确定如何将它应用到我的案例中。

【问题讨论】:

    标签: python performance python-2.7 numpy


    【解决方案1】:

    您可以拆分每个2x2 子数组,然后重新整形,使每个窗口块成为2D 数组中的一行。 从每一行中,使用boolean indexing 提取与f==1 位置对应的元素。 然后,查看每一行中所有提取的元素是否相同,给我们一个掩码。使用此掩码与f 相乘,得到整形后的最终二进制输出。

    因此,假设 f 作为过滤器数组,A 作为数据数组,遵循这些步骤的矢量化实现将如下所示 -

    # Setup size parameters
    M = A.shape[0]
    Mh = M/2
    N = A.shape[1]/2
    
    # Reshape input array to 4D such that the last two axes represent the 
    # windowed block at each iteration of the intended operation      
    A4D = A.reshape(-1,2,N,2).swapaxes(1,2)
    
    # Determine the binary array whether all elements mapped against 1 
    # in the filter array are the same elements or not
    S = (np.diff(A4D.reshape(-1,4)[:,f.ravel()==1],1)==0).all(1)
    
    # Finally multiply the binary array with f to get desired binary output
    out = (S.reshape(Mh,N)[:,None,:,None]*f[:,None,:]).reshape(M,-1)
    

    示例运行 -

    1) 输入:

    In [58]: A
    Out[58]: 
    array([[1, 1, 1, 1, 2, 1],
           [1, 1, 3, 1, 2, 2],
           [1, 3, 3, 3, 2, 3],
           [3, 3, 3, 3, 3, 1]])
    
    In [59]: f
    Out[59]: 
    array([[0, 1],
           [1, 1]])
    

    2) 中间输出:

    In [60]: A4D
    Out[60]: 
    array([[[[1, 1],
             [1, 1]],
    
            [[1, 1],
             [3, 1]],
    
            [[2, 1],
             [2, 2]]],
    
    
           [[[1, 3],
             [3, 3]],
    
            [[3, 3],
             [3, 3]],
    
            [[2, 3],
             [3, 1]]]])
    
    In [61]: S
    Out[61]: array([ True, False, False,  True,  True, False], dtype=bool)
    

    3) 最终输出:

    In [62]: out
    Out[62]: 
    array([[0, 1, 0, 0, 0, 0],
           [1, 1, 0, 0, 0, 0],
           [0, 1, 0, 1, 0, 0],
           [1, 1, 1, 1, 0, 0]])
    

    【讨论】:

    • 同样的方法可以用np.kron(~np.any(np.diff(A4D[...,f==1]), -1), f) ;-)
    • @morningsun 啊是的 kron 用于最后一步的乘法!谢谢!
    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 2019-05-06
    • 2011-11-24
    • 1970-01-01
    • 2018-01-24
    • 2022-01-06
    相关资源
    最近更新 更多