简体   繁体   English

在 numpy 矩阵中寻找点

[英]Finding spots in a numpy matrix

I have the following Matrix made of 0s and 1s which I want to identify its spots(elements with the value 1 and connected to eachothers).我有以下由 0 和 1 组成的矩阵,我想识别它的点(值为 1 并相互连接的元素)。

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

In the matrix there are four spots.在矩阵中有四个点。

an example of my output should seem the following我的 output 的示例如下所示

spot_0 = array[(0,0),(0,1), (0,2), (1,0),(1,1), (1,2), (2,0),(2,1), (2,2), (3,0),(3,1), (3,2)]
Nbr_0 = 12
Top_Left = (0, 0)
and that is the same process for the other 3 spots

Does anyone know how can I identify each spot with the number of its elements and top_left element, using numpy functions?有谁知道如何使用 numpy 函数识别每个点的元素数量和 top_left 元素? Thanks谢谢

You can use a connected component labeling to find the spots.您可以使用连接的组件标签来查找斑点。 Then, you can use np.max so to find the number of component and np.argwhere so to find the locations of each component.然后,您可以使用np.max so 来查找组件的数量,并使用np.argwhere so 来查找每个组件的位置。 Here is an example:这是一个例子:

# OpenCV provides a similar function
from skimage.measure import label

components = label(M)
# array([[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
#        [1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2],
#        [1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2],
#        [1, 1, 1, 0, 0, 3, 3, 3, 0, 0, 0],
#        [0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0],
#        [4, 4, 4, 0, 3, 3, 3, 3, 0, 0, 0],
#        [4, 4, 4, 0, 0, 3, 3, 3, 0, 0, 0],
#        [4, 4, 4, 0, 0, 3, 3, 3, 0, 0, 0]])

for i in range(1, np.max(components)+1):
    spot_i = np.argwhere(components == i)
    Nbr_i = len(spot_i)
    Top_Left_i = spot_i[0]

Note that Top_Left only make sense for a rectangular area .请注意, Top_Left仅对矩形区域有意义。 If they are not rectangular this point needs to be carefully defined.如果它们不是矩形,则需要仔细定义这一点。

Note also that this method is only efficient with few component.另请注意,此方法仅在组件很少的情况下才有效。 If there are many component, then it is better to replace the current loop by an iteration over the components array (in this case the output structure is stored in a list l and l[components[i,j]] is updated with the information found for all item location (i,j) of components ).如果有很多组件,那么最好用对components数组的迭代来替换当前循环(在这种情况下,output 结构存储在列表l中, l[components[i,j]]用信息更新找到components的所有项目位置(i,j) )。 This last algorithm will be slow unless Numba/Cython are used to speed the process up.最后一个算法会很慢,除非使用 Numba/Cython 来加速这个过程。

You could use skimage.measure.label or other tools (for instance, OpenCV or igraph ) to create labels for connected components:您可以使用skimage.measure.label或其他工具(例如OpenCVigraph )为连接的组件创建标签:

#from @Jérôme's answer
from skimage.measure import label
components = label(M)

# array([[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
#        [1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2],
#        [1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2],
#        [1, 1, 1, 0, 0, 3, 3, 3, 0, 0, 0],
#        [0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0],
#        [4, 4, 4, 0, 3, 3, 3, 3, 0, 0, 0],
#        [4, 4, 4, 0, 0, 3, 3, 3, 0, 0, 0],
#        [4, 4, 4, 0, 0, 3, 3, 3, 0, 0, 0]])

In the later part you could create a one-dimensional view of image, sort values of pixels and find dividing points of sorted label values:在后面的部分中,您可以创建图像的一维视图,对像素值进行排序并找到排序后的 label 值的分界点:

components_ravel = components.ravel()
c = np.arange(1, np.max(components_ravel) + 1)
argidx = np.argsort(components_ravel)
div_points = np.searchsorted(components_ravel, c, sorter=argidx)

# Sorted label values are:
# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
# 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
# 2, 2, 2, 2
# 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
# 4, 4, 4, 4, 4, 4, 4, 4, 4
# So you find indices that divides these groups:
# [47, 59, 63, 79]

After that you could split array of indices that sorts your one-dimensional view of image at these points and convert them into two-dimensional ones:之后,您可以拆分索引数组,在这些点对图像的一维视图进行排序,并将它们转换为二维视图:

spots = []
for n in np.split(argidx, div_points)[1:]: #in case there are no zeros, cancel `[1:]`
    x, y = np.unravel_index(n, components.shape)
    spots.append(np.transpose([x, y]))

It creates a list of spot coordinates of each group:它创建每个组的点坐标列表:

[array([[1, 0], [1, 2], [0, 2], [0, 1], [1, 1], [0, 0], [2, 2], [2, 1], [2, 0], [3, 2], [3, 1], [3, 0]]),
 array([[2, 10], [1, 9], [2, 9], [1, 10]]),
 array([[6, 5], [7, 5], [7, 6], [7, 7], [6, 7], [6, 6], [3, 5], [4, 6], [3, 6], [4, 5], [3, 7], [5, 7], [5, 6], [4, 7], [5, 5], [5, 4]]),
 array([[5, 0], [5, 1], [5, 2], [6, 2], [7, 0], [6, 0], [6, 1], [7, 1], [7, 2]])]

Note that an order of pixels of each group is mixed.请注意,每个组的像素顺序是混合的。 This is because np.argsort uses a sort which is not stable.这是因为np.argsort使用了一种不稳定的排序。 You could fix it like so:你可以像这样修复它:

argidx = np.argsort(components_ravel, kind='stable')

In this case you'll get:在这种情况下你会得到:

[array([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2], [3, 0], [3, 1], [3, 2]]),
 array([[1, 9], [1, 10], [2, 9], [2, 10]]),
 array([[3, 5], [3, 6], [3, 7], [4, 5], [4, 6], [4, 7], [5, 4], [5, 5], [5, 6], [5, 7], [6, 5], [6, 6], [6, 7], [7, 5], [7, 6], [7, 7]]),
 array([[5, 0], [5, 1], [5, 2], [6, 0], [6, 1], [6, 2], [7, 0], [7, 1], [7, 2]])]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM