提取匹配过滤器的元素
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)
时,最后一种方法变得非常难以编写。
我要过滤足迹(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)
时,最后一种方法变得非常难以编写。