python - 检查相邻值是否在 Numpy 矩阵中

标签 python arrays numpy

因此,我目前正在尝试找出一个更优化的解决方案来确定图像中的连通分量。目前,我有一个坐标具有特定值的数组。我想根据它们是否接触来创建这些坐标组。我正在使用一个 numpy 数组,目前我必须检查每个值(左上、中上、右上、左中、右中、左下、中下、右下)是否在该数组中。我通过以下代码这样做:

for x in range (0, groupCoords.shape[0]):
            global tgroup
            xCoord = groupCoords.item((x,0))
            yCoord = groupCoords.item((x,1))
            new = np.array([[xCoord, yCoord]])
            if np.equal(Arr,[xCoord, yCoord+1]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord,yCoord+1]], axis=0)
                new = np.append(new, [[xCoord,yCoord+1]], axis=0)
                index = np.argwhere((Arr == [xCoord,yCoord+1]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord, yCoord-1]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord, yCoord-1]],axis=0)
                new = np.append(new, [[xCoord,yCoord-1]], axis=0)
                index = np.argwhere((Arr == [xCoord,yCoord-1]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord+1, yCoord]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord+1,yCoord]],axis=0)
                new = np.append(new, [[xCoord+1,yCoord]], axis=0)
                index = np.argwhere((Arr == [xCoord+1,yCoord]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord+1, yCoord+1]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord+1,yCoord+1]],axis=0)
                new = np.append(new, [[xCoord+1,yCoord+1]], axis=0)
                index = np.argwhere((Arr == [xCoord+1,yCoord+1]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord+1, yCoord-1]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord+1,yCoord-1]],axis=0)
                new = np.append(new, [[xCoord+1,yCoord-1]], axis=0)
                index = np.argwhere((Arr == [xCoord+1,yCoord-1]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord-1, yCoord]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord-1,yCoord]],axis=0)
                new = np.append(new, [[xCoord-1,yCoord]], axis=0)
                index = np.argwhere((Arr == [xCoord-1,yCoord]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord-1, yCoord+1]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord-1,yCoord+1]],axis=0)
                new = np.append(new, [[xCoord-1,yCoord+1]], axis=0)
                index = np.argwhere((Arr == [xCoord-1,yCoord+1]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

            if np.equal(Arr,[xCoord-1, yCoord-1]).all(1).any():
                tgroup = np.append(tgroup, [[xCoord-1,yCoord-1]],axis=0)
                new = np.append(new, [[xCoord-1,yCoord-1]], axis=0)
                index = np.argwhere((Arr == [xCoord-1,yCoord-1]).all(1))
                Arr = np.delete(Arr, (index), axis=0)

但是,如果图像很大,这显然会花费大量时间。我的想法是创建一个 bool 矩阵,其尺寸为图像的宽度和高度,然后将值“true”分配给矩阵中与图像中的像素相对应的值(图像为黑白)。

我想知道,是否有可能不必像那样检查每个值,而是确定它们是否是标记为“true”的元素直接围绕另一个“true”值?

这是输入数组的样子:

[
 [0 0]
 [0 1]
 [0 2]
 [10 2]

]

输出看起来像

[
 [0 0]
 [0 1]
 [0 2]
]

我希望改进的函数将检查“真实”值是否相交,并创建所有相交值的“网络”(它将继续运行找到的新值)。

最佳答案

方法 #1

我们可以获得欧氏距离并查看是否有任何距离在 sqrt(2) 范围内,这将覆盖 up-downdistance = 1 distance = sqrt(2) 的对角线。这将为我们提供一个掩码,当它被索引到组坐标数组中时,将为我们提供与之相连的掩码。

因此,使用 Scipy's cdist 的实现为了获得这些欧氏距离,将是 -

from scipy.spatial.distance import cdist

out = groupCoords[(cdist(groupCoords,Arr)<1.5).any(1)]

sample 运行-

In [401]: Arr
Out[401]: 
array([[ 5,  4],
       [11, 12],
       [ 5,  3],
       [ 1,  3],
       [15,  8],
       [55, 21]])

In [402]: groupCoords
Out[402]: 
array([[2, 3],  # In neighbourhood of (1,3)
       [5, 6],
       [6, 2],  # In neighbourhood of (5,3)
       [5, 3],  # In neighbourhood of (5,4)
       [5, 8]])

In [403]: groupCoords[(cdist(groupCoords,Arr)<1.5).any(1)]
Out[403]: 
array([[2, 3],
       [6, 2],
       [5, 3]])

方法 #2

另一种方法是检查两个数组的第一列之间的绝对元素差异,第二列也是如此。最后,从这两个掩码中获取联合掩码并检查任何匹配项并再次索引到组数组中以获取过滤后的坐标。

因此,这种方法的实现将是 -

col0_mask = (np.abs(groupCoords[:,0,None] - Arr[:,0])<=1)
col1_mask = (np.abs(groupCoords[:,1,None] - Arr[:,1])<=1)
out = groupCoords[(col0_mask & col1_mask).any(1)]

方法 #3

另一种方法可能会更好,如果您将 Arr 作为 bool 数组而不是 2 列坐标数组。思路是dilate this boolean array Arr 的坐标,然后查看 groupCoords 中的哪些坐标也位于此膨胀图像中。对于扩张,我们将使用一个 3 x 3 核来覆盖所有这些邻域。为了检测这些共同点,我们需要用这些 groupCoords 绘制图像。

因此,代码将是 -

from scipy.ndimage.morphology import binary_dilation

img = np.zeros(Arr.shape,dtype=bool)
img[groupCoords[:,0],groupCoords[:,1]] = 1
out = np.argwhere(binary_dilation(Arr,np.ones((3,3))) & img)

sample 运行-

In [444]: # Inputs : groupCoords and let's create a sample array for Arr
     ...: groupCoords = np.array([[2,3],[5,6],[6,2],[5,3],[5,8]])
     ...: 
     ...: Arr_Coords = np.array([[5,4],[11,12],[5,3],[1,3],[15,8],[55,21]])
     ...: Arr = np.zeros(Arr_Coords.max(0)+1,dtype=bool)
     ...: Arr[Arr_Coords[:,0], Arr_Coords[:,1]] = 1
     ...: 

In [445]: img = np.zeros(Arr.shape,dtype=bool)
     ...: img[groupCoords[:,0],groupCoords[:,1]] = 1
     ...: out = np.argwhere(binary_dilation(Arr,np.ones((3,3))) & img)
     ...: 

In [446]: out
Out[446]: 
array([[2, 3],
       [5, 3],
       [6, 2]])

关于python - 检查相邻值是否在 Numpy 矩阵中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41418717/

相关文章:

python - 当我按 CSS 类过滤时,为什么 scrapy 和 beautifulsoup 都没有返回任何内容?

php - 如何使单选按钮返回 bool 值真/假而不是开/关

python - Pandas 适用于 numpy interp,尺寸问题

python - 使用自定义格式化程序登录 django

python - 将对象保存到数据库时出现问题,因为模型包含 jsonfield sqlite3 django

python - Python中将多行字符串作为命令行输入

php - CodeIgniter 中带有单表的多级菜单

arrays - 是否可以找到数组中元组的索引?

python - numpy数组: IndexError: failed to coerce slice entry of type numpy. ndarray的多个索引到整数

python - 如何在 pandas Dataframe 中查找 numpy 数组列的 boolean 值?