Найти ближайшую точку в сетке Matlab

Добрый день

Я пытаюсь запрограммировать умный способ найти ближайшие точки сетки к точкам вдоль контура.

Сетка представляет собой 2-мерную сетку, хранящуюся в x и y (которые содержат позиции ячеек сетки в километрах x и y).

Контур представляет собой линию, состоящую из точек x и y, не обязательно расположенных через равные промежутки.

Это показано ниже — красные точки — это сетка, а синие — точки на контуре. Как найти индексы красной точки, ближайшей к каждой синей точке?

интерполировать красные точки, ближайшие к каждой синей точке

Изменить. Я должен упомянуть, что сетка представляет собой сетку широты/долготы в области, довольно близкой к южному полюсу. Итак, точки (красные точки) — это положение в метрах от южного полюса (с использованием полярного стереографического изображения). Поскольку сетка является географической сеткой, интервалы сетки неодинаковы - с ячейками немного другой формы (где красные точки определяют вершины ячеек) из-за искажения в высоких широтах. В результате я не могу просто найти, какая строка/столбец матрицы x и y ближе всего соответствует входным координатам точки - в отличие от обычной сетки из meshgrid, значения в строках и столбца различаются ...

Привет Дэйв


person David_G    schedule 27.11.2012    source источник
comment
Ваша сетка очень регулярна, но не выровнена по прямоугольным осям xy. Не могли бы вы дать нам математическое определение точек сетки? Я подозреваю, что лучший способ - найти ответ алгебраически, а не алгоритмически - поскольку сетка четко определена, вы можете определить ближайшую точку по геометрии, а не путем проверки пар точек.   -  person Brian L    schedule 27.11.2012
comment
@BrianL Хорошая идея! Если точки имеют преобразование вращения, вы можете выровнять их по оси, а затем выполнить поиск на основе метода расширяющегося прямоугольника!   -  person Fantastic Mr Fox    schedule 27.11.2012
comment
@BrianL и Бен - в своем редактировании я попытался уточнить природу сетки. Он не выровнен по оси xy, и хотя он выглядит правильным, это не так — он географический (широта/долгота), и из-за расположения на высокой широте (около южного полюса) самые южные ячейки немного меньше, чем самый северный. Кроме того, для ориентации - север находится внизу справа на графике выше, так как это полярное стереографическое изображение.   -  person David_G    schedule 27.11.2012
comment
@David_G, твое изображение исчезло, и теперь вопрос менее полезен .. думаешь, ты мог бы повторно загрузить его сюда?   -  person naught101    schedule 16.02.2018
comment
Да извини. Старый штатный хостинг умер! Я посмотрю что я могу сделать.   -  person David_G    schedule 16.02.2018
comment
@ naught101 Ничего себе, я очень удивлен, что смог найти их спрятанными в резервной копии 5-летней давности!   -  person David_G    schedule 16.02.2018


Ответы (4)


Обычный метод - пойти:

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-kd-tree

Эта библиотека предоставит вам средства для простого создания kd-дерева из данных и поиска в нем ближайшей точки.

В качестве альтернативы вы можете использовать дерево квадрантов, не такое простое, но с той же идеей. (возможно, вам придется написать свою собственную библиотеку для этого)

Убедитесь, что самый большой набор данных (в данном случае ваши красные точки) входит в дерево, так как это обеспечит наибольшее сокращение времени.

person Fantastic Mr Fox    schedule 27.11.2012
comment
+1 Спасибо за предложение @Ben - я не слышал о kd-деревьях. Я мог бы попробовать ваше предложение, если я не могу решить это алгебраически (как вы предлагаете выше). - person David_G; 27.11.2012
comment
Я не понимаю, как это значительно повышает эффективность. Кажется, что должна быть возможность построить патологический пример, где, например. ближайшие две точки находятся по обе стороны от первого среднего, поэтому вам придется пройтись по всему дереву, чтобы найти, что они самые близкие (если я понимаю, как это правильно используется). Так ли это? Дело в том, что средняя эффективность значительно улучшилась, а верхняя граница эффективности — нет? - person naught101; 16.02.2018
comment
@ naught101 вы не ищете две точки в дереве KD. Одна точка получается в результате повторения множества точек. Ближе всего к этому приходит поиск в дереве KD. Да, в худшем случае то же самое, но в среднем это O (log (n)), что намного лучше для такого большого набора данных. - person Fantastic Mr Fox; 20.02.2018
comment
Помимо эффективности, я думаю, что этот метод может в некоторых случаях давать неверные результаты. Например, если точка, которую вы хотите сопоставить, находится чуть ниже и правее нижней левой точки в верхнем правом прямоугольнике на итерации 2, она явно будет ближайшей к этой точке, но вместо этого она будет присвоена точка в левом верхнем углу нижнего правого прямоугольника в итерации 3. Это может быть в 3 раза дальше, и даже не второй лучший выбор назначения. Я предполагаю, что этот метод найдет точку сетки в нескольких (8?) лучших точках, но, похоже, не гарантируется найти лучшую. - person naught101; 08.10.2018
comment
@ naught101 Это просто отображение дерева для поиска определенной точки O (log (n)) вместо O (n). Вы по-прежнему гарантированно найдете настоящую ближайшую точку. Это хорошо известный и полный метод, по которому имеется множество литературы: andrewd.ces.clemson.edu/courses/cpsc805/references/ - person Fantastic Mr Fox; 08.10.2018
comment
@FantasticMrFox: Верно. В этом PDF-файле показана куча шагов (слайды 16-20), которые не описаны, но в основном похоже, что он ищет узел дерева, в котором находится точка (как вы описали), но затем он возвращается назад , и проверяет все остальные разделы, которые попадают в радиус между точкой и точкой узла. Я не очень понимаю, как работает эта часть, но пример выглядит так, будто он проверяет почти все дерево (например, это пример почти наихудшего случая). - person naught101; 10.10.2018
comment
@ naught101 Нет, он ищет ближайшие разделы, которые можно найти за O (log (n)). Он также говорит, что время поиска составляет log (n), поэтому я не уверен, в чем проблема, которую вы видите. Кроме того, большинство университетов преподают это как часть любого базового алгоритма грубого... - person Fantastic Mr Fox; 10.10.2018
comment
@FantasticMrFox: например, см. imgur.com/a/9vsdLGz — зеленая точка будет присвоена нижняя правая точка, даже если она ближе к точке чуть выше нее. Часть алгоритма проверяет все части дерева, перекрывающие круг с центром в зеленой точке с радиусом до назначенной точки. В худшем случае это может проверить все дерево. - person naught101; 10.01.2019

Я думаю, что нашел способ сделать это, используя флаг nearest для griddata.

Я создаю матрицу того же размера, что и матрицы сетки x и y, но заполняемую линейными индексами соответствующего элемента матрицы. Это формируется путем изменения формы вектора (который равен 1:size(x,1)*size(x,2)) до тех же размеров, что и x.

Затем я использую griddata и флаг nearest, чтобы найти линейный индекс точки, ближайшей к каждой точке моего контура (синие точки). Затем, простое преобразование обратно в нотацию индекса с помощью ind2sub оставляет мне 2 вектора-строки, описывающие индексы матрицы для точек, ближайших к каждой точке на контуре с синими точками.

На приведенном ниже графике показан контур (синие точки), сетка (красные точки) и ближайшие точки сетки (зеленые точки).

результат сетки

Это фрагмент кода, который я использовал:

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);
person David_G    schedule 28.11.2012

Я предполагаю, что в стереографическом представлении ваши точки образуют аккуратную сетку в координатах r-theta. (Я не слишком знаком с этим, так что поправьте меня, если я ошибаюсь. Мое предложение все еще может быть применимо).

Для построения вы конвертируете из стереографического изображения в широту-долготу, что искажает сетку. Однако для нахождения ближайшей точки рассмотрите возможность преобразования широты и долготы точек синего контура в стереографические координаты, где легко определить ячейку для каждой точки, используя ее значения r и theta.

Если вы можете проиндексировать ячейку в стереографическом представлении, индекс будет таким же при преобразовании в другое представление.

Основное требование состоит в том, что при некотором преобразовании узлы сетки определяются двумя векторами, X и Y, так что для любых x в X и y в Y (x, y) является точкой сетки. Затем преобразуйте сетку и точки контура с помощью этого преобразования. Затем, учитывая произвольную точку (x1, y1), мы можем найти соответствующую ячейку сетки, найдя ближайшую точку x к x1 и ближайшую точку y к y1. Преобразуйте обратно, чтобы получить точки в нужной системе координат.

person Brian L    schedule 27.11.2012

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

person electron1979    schedule 04.02.2016