提取与过滤器匹配的元素

时间:2015-02-15 01:45:38

标签: numpy scipy scikit-image

我想过滤其足迹(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]])

1 个答案:

答案 0 :(得分:3)

我的答案基于我几小时前写的a very similar answer

#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中生成视图,这意味着不是实际数据的副本,但使用大步生成一个看似不同的数组。在这种情况下,它将生成数组data的所有可能的3x3子矩阵(可以重叠)。然后,通过编写patches.all(axis=-1).all(axis=-1),您首先要检查子矩阵行中的元素是否全为True(或者在布尔意义上等效为True,因此不是0,空列表,空字典,空元组和a很少有其他特殊情况),从而折叠这个数组的一个轴,然后用第二个.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

因此,对于每个充满1的3x3子矩阵,此数组dual现在具有“1”(实际为真)。然而,这些子矩阵是重叠的,所以你首先想要将这些补丁全部设置为0,而这些3x3子矩阵中的任何一个都不是全部(这是第一个代码块中的一到最后一行:patches[dual==False] = 0)和< em>然后你可以在最初拥有所有的3x3子矩阵中再次应用那些。 替代方案是与kernel = np.ones((3,3))相关联或考虑多个按位操作(如在另一个答案中),但当数组的维度超出简单(2,2)时,最后一个方法变得非常难以编写。