提取匹配过滤器的元素

Extracting the elements matching the filter

我要过滤足迹(3,3)由1组成的索引

import numpy as np
data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                 [1, 1 , 1 , 0 , 0 , 1 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 0 , 1],
                 [1, 1 , 0 , 0 , 0 , 1 , 1 , 1],
                 [1, 1 , 0 , 0 , 0 , 1 , 1 , 1]])

预期答案如下,不需要的位置设置为 0:

answer = np.array([[0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                 [0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                 [0, 0 , 0 , 0 , 0 , 0 , 0 , 0]])

我的回答基于 我几个小时前写的。

#from sklearn.feature_extraction.image import extract_patches  # similar to numpy's stride_tricks
from numpy.lib.stride_tricks import as_strided

data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                 [1, 1 , 1 , 0 , 0 , 1 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 0 , 1],
                 [1, 1 , 0 , 0 , 0 , 1 , 1 , 1],
                 [1, 1 , 0 , 0 , 0 , 1 , 1 , 1]])
patches = as_strided(data, shape=(data.shape[0]-2,data.shape[1]-2, 3, 3), strides=data.strides*2)
dual = patches.all(axis=-1).all(axis=-1)
patches[dual==False] = 0
patches[dual] = 1

结果(在 data 中)如您所示。

其工作方式如下: 函数 extract_patches 在数组 data 中生成 视图 ,这意味着它 不是 实际数据的副本但使用 strides 生成看似不同的数组。在这种情况下,它将生成数组 data 的所有可能的 3x3 子矩阵(可以重叠)。然后,通过编写 patches.all(axis=-1).all(axis=-1),您首先检查子矩阵行中的元素是否都是 True(或者在布尔意义上等同于 True,因此不为 0、空列表、空字典、空元组和一个其他一些特殊情况),从而折叠该数组的一个轴,然后用第二个 .all(axis=-1) 检查列以查看它们是否全部为真。

本段的小例子直观地说明:

>>> A = np.array([
... [1, 1, 0],        # -> along this row, not all elements are 1: so `all` along the last axis will return False
... [1, 1, 1],        # -> along this row, all elements are 1: so `all` along the last axis (axis=-1) will return True
... [1, 1, 1]])
>>> A.all(axis=-1)
array([False,  True,  True], dtype=bool)  # so it is done along the last axis, along the rows
>>> A.all(axis=-1).all(axis=-1)
False

所以这个数组 dual 现在对于每个全为 1 的 3x3 子矩阵都有一个“1”(实际上是 True)。但是,这些子矩阵是重叠的,所以只要这些 3x3 子矩阵中的任何一个不是全部,您首先要将补丁全部设置为 0(这是第一个代码块中的倒数一行:patches[dual==False] = 0)和 然后 你可以在每个原本全为 1 的 3x3 子矩阵中再次应用这些。 备选方案是与 kernel = np.ones((3,3)) 相关联或考虑多个按位运算(如另一个答案),但当数组的维度增长超过 (2,2) 时,最后一种方法变得非常难以编写。