Хобрук: Ваш путь к мастерству в программировании

Группировка точек с помощью триангуляции

Язык: MATLAB

Определение проблемы:

У меня есть набор 2D-точек в пространстве. Я хотел бы сгруппировать точки на основе их евклидова расстояния. Мои данные имеют такое свойство, что две группы всегда разделены как минимум R единицами. Следовательно, для данной точки все точки, которые находятся ближе, чем на 50 единиц, могут считаться ее соседями. Объединение точек, имеющих общих соседей, приведет к группам (по крайней мере, такова идея).

Предлагаемый метод:

Используйте триангуляцию Делоне в Matlab и получите список ребер полученных треугольников. Удалите все ребра, длина которых превышает R единиц. Каждая группа оставшихся точек - это группы, которые я ищу. Оставшиеся несоединенные точки можно игнорировать.

Попытка: я попытался реализовать описанное выше в MATLAB, но я делаю ошибку, группируя оставшиеся точки. Прикрепляю свой код.

DT      = delaunayTriangulation(double(frame(:,1:2)));
edgeList   = edges(DT);

edgeVertex1 = frame(edgeList(:,1),:); 
edgeVertex2 = frame(edgeList(:,2),:); 

dVec = edgeVertex1 - edgeVertex2;
edgeLengths = sqrt(sum(abs(dVec).^2,2));
requiredEdges = edgeLengths < NEIGH_RADIUS;

edgeLengthsFiltered = edgeLengths(requiredEdges);
edgeListFiltered = edgeList(requiredEdges,:);

% Clustering
edgeOrigins = edgeListFiltered(:,1);
edgeEndings = edgeListFiltered(:,2);
nodeList = unique(edgeOrigins);

if isempty(nodeList)
    Result = struct([]);
    super_struct(i).result = Result;
else
    groups = cell(10,1);
    groups{1} = nodeList(1);
    groupLength = 2;
    flag = 0;

    % grouping
    for j = 1:1:length(nodeList);
        neighbourList = [nodeList(j); edgeEndings(edgeOrigins==nodeList(j))];
        % add current node as part of neighbourList
        for k = 1:1:groupLength-1
           te =  ismembc(groups{k}, neighbourList);
           if sum(te) ~=0
                temp = sort([groups{k}; neighbourList]);
                groups{k} = temp([true;diff(temp(:))>0]);
                flag = 1;
                break;
            end
        end

        if ~flag
            groups{groupLength} = neighbourList;
            groupLength = groupLength + 1;
        end

        flag = 0;
    end

    largeGroups = cell(1,1);
    largeGroups_c = 1;
    for j = 1:1:groupLength -1;
        if ~ isempty(groups{j})

        for k = j+1:1:groupLength - 1
            te = ismembc(groups{j}, groups{k});
            if sum(te) ~= 0
                temp = sort([groups{j}; groups{k}]);
                groups{j} = temp([true;diff(temp(:))>0]);
                groups{k} =[];
            end    
        end

        % ignore small groups
        if length(groups{j}) > MIN_PTS_IN_GROUP
            largeGroups{largeGroups_c} = groups{j};
            largeGroups_c = largeGroups_c+1;
        end

        end
    end

в приведенном выше коде frame — это переменная со списком точек. Константы NEIGH_RADIUS представляют R из вопроса. Другая константа MIN_PTS_IN_GROUP определяется пользователем для выбора минимального количества точек, необходимого для того, чтобы считать его интересующим кластером.

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

Результат запуска моего алгоритма группировки

Красные линии ограничивают одну группу, как указано в приведенном выше коде. Ясно, что есть пересекающиеся группы, что неправильно.

Вопрос 1 Может ли кто-нибудь предложить лучший (и правильный) способ группировки?

Вопрос 2 Любые другие альтернативные методы получения групп быстрее, чем Триангуляция, также были бы великолепны!

заранее спасибо


  • Вы заранее знаете, сколько групп? 07.04.2015
  • Нет. Количество групп неизвестно. 07.04.2015
  • Постройте граф ребер длиной меньше R, получите связанные компоненты через этот ответ. 08.04.2015
  • @knedlsepp Ваше предложение сработало. Спасибо. Получение подключенных компонентов было тем, что я искал. Меня также интересуют альтернативные подходы к проблеме (т.е. без использования триангуляции). 08.04.2015
  • Возможно, вы могли бы ускорить его, используя только следующие ребра: edges = knnsearch(frame,frame,'K',2) вместо ребер Делоне. Однако с точки зрения вычислительной сложности ваш подход delaunay уже должен быть неплохим. 08.04.2015
  • В порядке. Приведенный выше подход knnsearch на самом деле не очень хорошая идея, так как в большинстве случаев он не даст вам правильных результатов. Если я смогу придумать что-то лучше, я напишу ответ. 08.04.2015
  • @knedlsepp, я собирался сказать это 08.04.2015

Ответы:


1

Если вы знаете номер группы, которую вы ищете, вы можете использовать функцию kmeans в наборе инструментов статистики Matlab или найти другую имплементацию на бирже Matlab (кластеризация kmeans)

16.06.2015
  • В моем случае я не знаю, сколько кластеров/групп у меня есть заранее. 17.06.2015
  • Новые материалы

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

    Обзор 20 основных и современных методов работы с массивами в JavaScript
    Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

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