在Python中按位置有效地分组坐标列表

时间:2014-07-27 20:05:41

标签: python algorithm grid

给定2D网格上的X,Y坐标点列表,创建相邻坐标点组列表的最有效算法是什么?

例如,给定在网格(15x15)上构成两个非相邻正方形(3x3)的点列表,该算法的结果将是对应于两个正方形的两组点。

我想你可以做一个泛洪填充算法,但对于1024大小的大型2D阵列来说,这似乎有点过分而且效率不高。

3 个答案:

答案 0 :(得分:4)

基本上,这是图像处理操作。如果您使用像scikit-image(a.k.a。skimage)这样的图像处理库,那将很容易。处理真正庞大的数据最终会变慢,但1024x1024什么都不是。

In [1]: import numpy as np
In [2]: import skimage.morphology
In [3]: x = [0,1,2,0,1,2,0,1,2,-3,-2,-1,-3,-2,-1,-3,-2,-1]
In [4]: y = [0,0,0,1,1,1,2,2,2,-3,-3,-3,-2,-2,-2,-1,-1,-1]
In [5]: dense = np.zeros((9,9), dtype=bool)
In [6]: dense[y,x] = True

In [7]: print dense
[[ True  True  True False False False False False False]
 [ True  True  True False False False False False False]
 [ True  True  True False False False False False False]
 [False False False False False False False False False]
 [False False False False False False False False False]
 [False False False False False False False False False]
 [False False False False False False  True  True  True]
 [False False False False False False  True  True  True]
 [False False False False False False  True  True  True]]

In [8]: labeled = skimage.morphology.label(dense)
In [9]: print labeled
[[1 1 1 0 0 0 0 0 0]
 [1 1 1 0 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 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 2 2 2]
 [0 0 0 0 0 0 2 2 2]
 [0 0 0 0 0 0 2 2 2]]

In [10]: coords_yx = { i: (labeled == i).nonzero() for i in range(1,labeled.max()+1) }
In [11]: coords_yx
Out[11]:
{1: (array([0, 0, 0, 1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2, 0, 1, 2])),
 2: (array([6, 6, 6, 7, 7, 7, 8, 8, 8]), array([6, 7, 8, 6, 7, 8, 6, 7, 8]))}

答案 1 :(得分:2)

您可以散列所有坐标点(例如,使用python中的字典结构),然后对于每个坐标点,对该点的相邻邻居进行散列,以找到相邻的点对并“合并”它们。此外,对于每个点,您可以维护指向该点所属的连接组件的指针(使用字典结构),并且对于每个连接的组件,您可以维护属于该组件的点列表。

然后,当您对点的邻居进行散列并找到匹配项时,将合并这些点所属的两个连接的组件集,并更新联合集中所有新点的组指针。您可以证明您只需要对所有点的所有邻居进行一次哈希,这将找到所有连接的组件,此外,如果在合并两个连接的组件集时更新两个连接组件集中较小的一个的指针,那么运行时间的点数就是线性的。

答案 2 :(得分:1)

目前还不清楚“相邻”坐标点组的含义。您的两个不相邻的3x3正方形的示例表明您正在寻找所谓的connected components labeling

有许多实现可以提取连接的组件。以下是一些指导。

  1. cclabel
  2. OpenCV
  3. bwconncomp
  4. 然而,我已经实现了这种blob探测器,如果你正在寻找学习经验,它们并不难写。如果没有,那么我会选择像OpenCV这样最成熟的库,并使用他们的Python API,如果你需要的话。

    另外,你提到了“效率”。请注意,这些算法有单通道和双通道版本。顾名思义,单遍通常更有效,因为它只需要通过我们的数据。如果你的网格非常大,可能需要这样做。