如果矩阵中的值是相邻的

2024-09-29 17:10:52 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我目前正在尝试找出一个更为优化的解决方案来确定图像中的连接组件。目前,我有一个具有特定值的坐标数组。我想创建这些坐标组的基础上,如果他们是接触。我正在使用一个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)

但是,如果图像很大,这显然需要大量的时间。我的想法是创建一个具有图像宽度和高度尺寸的布尔矩阵,然后将值“true”分配给与图像像素相对应的矩阵值(图像为黑白)。在

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

输入数组如下所示:

^{pr2}$

输出看起来像

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

我希望改进的函数将检查“真”值是否接触,并创建一个包含所有接触值的“网络”(它将与找到的新值一起运行)。在


Tags: newindexifnpanyequalalldelete
2条回答

根据代码的最终目标,您可能会发现^{}及其相关项很有用。在

例如

In [44]: from scipy.ndimage import label

In [45]: x
Out[45]: 
array([[ True,  True, False, False,  True],
       [False, False, False,  True,  True],
       [False,  True, False,  True, False],
       [ True,  True, False, False, False]], dtype=bool)

In [46]: x.astype(int)  # More concise, easier to read
Out[46]: 
array([[1, 1, 0, 0, 1],
       [0, 0, 0, 1, 1],
       [0, 1, 0, 1, 0],
       [1, 1, 0, 0, 0]])

label返回两个值。第一个是与输入数组大小相同的数组。输入中每个不同连接的组件都分配了一个整数值,从1开始。背景为0。第二个返回值是找到的组件数。在

^{pr2}$

在下面,where(labeled_array = i)返回一个包含两个数组的元组。这些数组分别是所连接组件的行和列索引:

In [50]: for i in range(1, nlabels+1):
    ...:     print(where(labeled_arr == i))
    ...:     
(array([0, 0]), array([0, 1]))
(array([0, 1, 1, 2]), array([4, 3, 4, 3]))
(array([2, 3, 3]), array([1, 0, 1]))

您可以将它们压缩在一起以将它们转换为(行、列)对的列表:

In [52]: for i in range(1, nlabels+1):
    ...:     print(list(zip(*where(labeled_arr == i))))
    ...:     
[(0, 0), (0, 1)]
[(0, 4), (1, 3), (1, 4), (2, 3)]
[(2, 1), (3, 0), (3, 1)]

方法1

我们可以得到欧几里德距离,看看是否有任何距离在sqrt(2)之内,它将用distance = 1覆盖{},用{}对角。这将给我们一个掩码,当索引到组坐标数组中时,它将给我们从中连接的那些。在

因此,使用^{}来获得这些欧几里德距离的实现是-

from scipy.spatial.distance import cdist

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

样本运行-

^{pr2}$

方法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作为布尔数组而不是2列坐标数组,则可能会更好。我们的想法是Arr^{},然后看看{}的哪个坐标也在这个放大的图像中。对于扩展,我们将使用所有一的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)

样本运行-

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]])

相关问题 更多 >

    热门问题