【问题标题】:Find closest point in matlab grid在matlab网格中查找最近点
【发布时间】:2012-11-14 17:20:31
【问题描述】:

纪念日

我正在尝试编写一种智能方法来找到离轮廓点最近的网格点。

网格是一个二维网格,存储在xy(其中包含网格单元的x 和y 公里位置)。

轮廓是一条线,由 x 和 y 位置组成,不一定是规则间隔的。

如下图所示——红点是网格,蓝点是轮廓上的点。如何找到离每个蓝点最近的红点的索引?

编辑 - 我应该提到该网格是一个纬度/经度网格,位于非常靠近南极的区域。因此,这些点(红点)是以米为单位的距离南极的位置(使用极地立体表示法)。由于网格是地理网格,因此网格间距不相等 - 由于高纬度地区的变形,单元格的形状略有不同(红点定义单元格的顶点)。 结果是我不能只找到xy 矩阵的哪一行/列最接近输入点坐标 - 与meshgrid 中的常规网格不同,行中的值 列不同...

干杯 戴夫

【问题讨论】:

  • 您的网格非常规则,但未与矩形 xy 轴对齐。您能否给我们一个网格点的数学定义?我怀疑最好的方法是通过代数而不是算法找到答案 - 因为网格是明确定义的,您可以通过几何而不是通过测试点对来确定最近的点。
  • @BrianL 好主意!如果这些点具有旋转变换,您可以将它们轴向对齐,然后基于扩展框方法进行搜索!
  • @BrianL 和 Ben - 在我的编辑中,我试图详细说明网格的性质。它不与 xy 轴对齐,虽然它看起来很规则,但实际上并非如此 - 它是地理上的(纬度/经度),并且由于高纬度位置(靠近南极),最南端的单元略小于最北端。此外,对于方向 - 北在上图中的右下角,因为它是极地立体表示。
  • 是的,对不起。老员工网站托管死了!我会看看我能做什么。
  • @naught101 哇,我很惊讶我能在 5 年前的备份中找到它们!

标签: matlab nearest-neighbor


【解决方案1】:

通常的方法是去:

for every blue point {
    for every red point {
        is this the closest so far
    }
}

但更好的方法是将红色数据放入kd树中。这是一棵树,它沿着平均值分割数据,然后沿着它们的平均值分割两个数据集,等等,直到你把它们分成一个树结构。

这会将您的搜索效率从O(n*m) 更改为O(log(n)*m)

这是一个图书馆:

http://www.mathworks.com.au/matlabcentral/fileexchange/4586-k-d-tree

该库将为您提供轻松从数据中创建 kd 树并在其中搜索最近点的方法。

或者,您可以使用四叉树,不是那么简单,而是相同的想法。 (您可能需要为此编写自己的库)

确保最大的数据集(在这种情况下是您的红点)进入树,因为这将最大程度地减少时间。

【讨论】:

  • +1 感谢@Ben 的建议 - 我还没有听说过 kd-trees。如果我不能用代数方式解决这个问题(如你上面建议的那样),我可能会尝试你的建议。
  • 我不明白这如何提高效率。似乎应该可以构建一个病态的例子,例如最近的两个点在第一个平均值的两侧,所以你必须走整棵树才能发现它们是最接近的(如果我理解它是如何正确使用的)。是这样吗?是不是平均效率提高很多,但效率上限却没有?
  • @naught101 您没有在 KD 树中搜索两个点。一个点来自于对一组点的迭代。最接近这一点的是在 KD 树中搜索。是的,最坏的情况是一样的,但平均情况是 O(log(n)),这对于像这样的大型数据集来说要好得多。
  • 抛开效率不谈,我认为这种方法在某些情况下会产生不正确的结果。例如,如果您要匹配的点位于迭代 2 中右上角矩形中左下角点的右下方,那么它显然最接近该点,但它会被分配给迭代 3 中右下角矩形左上角的点。这可能是 3 倍远,甚至不是第二好的分配选择。我猜这个方法会在前几个(8?)最佳点中找到一个网格点,但似乎不能保证找到最好的..
  • @naught101 这只是一个树映射,用于搜索特定点 O(log(n)) 而不是 O(n)。您仍然可以保证找到实际的最近点。这是一种众所周知且完整的方法,有大量文献:andrewd.ces.clemson.edu/courses/cpsc805/references/…
【解决方案2】:

我想我已经找到了一种方法来使用griddatanearest 标志。

我创建了一个与xy 矩阵大小相同的矩阵,但填充了相应矩阵元素的线性索引。这是通过将向量(即1:size(x,1)*size(x,2))重新整形为与x 相同的维度而形成的。

然后我使用griddatanearest 标志来找到最接近我的轮廓上每个点的点的线性索引(蓝点)。然后,只需使用ind2sub 转换回下标符号,我就会得到一个 2 行向量来描述最接近蓝点轮廓上每个点的点的矩阵下标。

下图显示了轮廓(蓝点)、网格(红点)和最近的网格点(绿点)。

这是我使用的代码sn-p:

index_matrix1 = 1:size(x,1)*size(x,2); 
index_matrix1 = reshape(index_matrix1,size(x));
lin_ind = griddata(x,y,index_matrix1,CX,CY,'nearest'); % where CX and CY are the coords of the contour
[sub_ind(1,:),sub_ind(2,:)] = ind2sub(size(x),lin_ind);

【讨论】:

    【解决方案3】:

    我想在立体表示中,您的点在r-theta 坐标中形成一个整齐的网格。 (我对此不太熟悉,如果我错了,请纠正我。我的建议可能仍然适用。

    对于绘图,您将立体图转换为经纬度,这会扭曲网格。但是,为了找到最近的点,请考虑将蓝色轮廓点的经纬度转换为立体坐标,这样可以很容易地使用其rtheta 值确定每个点的单元格。

    如果您可以对立体表示中的单元格进行索引,则当您转换为另一种表示时,索引将相同。

    主要要求是在某种变换下,网格点由XY这两个向量定义,这样对于X中的任意xY中的y,@ 987654331@ 是一个网格点。接下来通过该变换同时变换网格和轮廓点。然后给定任意点(x1, y1),我们可以通过找到最接近xx1 和最接近yy1 来找到合适的网格单元。变换回来得到所需坐标系中的点。

    【讨论】:

      【解决方案4】:

      dsearchn: N-D 最近点搜索。

      [k, d] = dsearchn(A,B) :返回到最近点的距离 d。 d 是长度为 p 的列向量。

      http://au.mathworks.com/help/matlab/ref/dsearchn.html?s_tid=gn_loc_drop

      【讨论】:

        猜你喜欢
        • 2019-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多