【问题标题】:Check if all elements are True in sliding windows across a 2D array - Python检查二维数组的滑动窗口中的所有元素是否为真 - Python
【发布时间】:2023-03-24 02:15:01
【问题描述】:

我有一个多维 numpy 数组,其中元素是 True 或 False 值:

import numpy as np 
#just making a toy array grid to show what I want to do 
grid = np.ones((4,4),dtype = 'bool')
grid[0,0]=False 
grid[-1,-1]=False 
#now grid has a few false values but is a 4x4 filled with mostly true values

现在我需要生成另一个数组 M,其中每个站点 M[i,j] 的值取决于 grid[i:i+2,j:j+2],如下所示

M = np.empty((4x4)) #elements to be filled

#here is the part I want to clean up 
for ii in range(4): 
    for jj in range(4): 

        #details here are unimportant. It's just that M[ii,jj] depends on 
        #multiple elements of grid in some way
        if ii+2<=4 and jj+2<=4:     
            M[ii,jj] = np.all(grid[ii:ii+2,jj:jj+2]==True)
        else: 
            M[ii,jj] = False 

有没有办法使用网格中的元素填充数组 M 而没有双循环?

【问题讨论】:

    标签: python numpy multidimensional-array vectorization


    【解决方案1】:

    方法#1

    这是2D convolution 的一种方法-

    from scipy.signal import convolve2d as conv2
    
    out = (conv2(grid,np.ones((2,2),dtype=int),'valid')==4).astype(int)
    

    示例运行 -

    In [118]: grid
    Out[118]: 
    array([[False,  True,  True,  True],
           [ True,  True,  True,  True],
           [ True,  True,  True,  True],
           [ True,  True,  True, False]], dtype=bool)
    
    In [119]: (conv2(grid,np.ones((2,2),dtype=int),'valid')==4).astype(int)
    Out[119]: 
    array([[0, 1, 1],
           [1, 1, 1],
           [1, 1, 0]])
    

    请注意,预期输出的最后一行和最后一列在初始化的输出数组中将全为零。这是因为代码的滑动特性,因为它不会沿着行和列有那么大的范围。

    方法#2

    这是另一个带有 2D 统一过滤器的 -

    from scipy.ndimage.filters import uniform_filter as unif2d
    
    out = unif2d(grid,size=2).astype(int)[1:,1:]
    

    方法#3

    这是另一个4D slided windowed view -

    from skimage.util import view_as_windows as viewW
    
    out = viewW(grid,(2,2)).all(axis=(2,3)).astype(int)
    

    有了all(axis=(2,3)),我们只是在每个窗口的两个维度上检查所有元素是否都是True 元素。


    运行时测试

    In [122]: grid = np.random.rand(5000,5000)>0.1
    
    In [123]: %timeit (conv2(grid,np.ones((2,2),dtype=int),'valid')==4).astype(int)
    1 loops, best of 3: 520 ms per loop
    
    In [124]: %timeit unif2d(grid,size=2).astype(int)[1:,1:]
    1 loops, best of 3: 210 ms per loop
    
    In [125]: %timeit viewW(grid,(2,2)).all(axis=(2,3)).astype(int)
    1 loops, best of 3: 614 ms per loop
    

    【讨论】:

    • 感谢迪瓦卡!我认为滑动窗口视图对我来说最有意义——这种方法也应该对本项目稍后的其他任务有用。我必须对这些进行更多调查以了解它们的工作原理
    • 我了解 viewW(grid,(2,2)) 从网格中拉出 2x2 块。传入的简单问题: .all((2,3)) 做什么?为什么是 (2,3)?
    • @kevinkayaks 在上面添加了一些 cmets。
    • @kevinkayaks np.all((2, 3)) 只是 .all(axis=(2, 3)) 所以沿着轴 2 和 3。
    • 这会更快地将 2d 卷积分解为两个 1d 卷积 - 但大概这就是 uniform_filter 所做的
    猜你喜欢
    • 2019-07-04
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 2021-07-06
    相关资源
    最近更新 更多