Подтвердить что ты не робот

Алгоритм обнаружения "кластеров" точек

У меня есть 2D-область с "точками", распределенными по этой области. Теперь я пытаюсь обнаружить "кластеры" точек, то есть областей с определенной высокой плотностью точек.

Любые мысли (или ссылки на статьи с мыслями) о том, как изящно определить эти области?

4b9b3361

Ответ 1

Как определить произвольное разрешение для вашего пространства и вычислить для каждой точки в этой матрице меру расстояния от этой точки до всех точек, тогда вы можете сделать "тепловой график" и использовать порог для определения кластеры.

Это приятное упражнение для обработки, возможно, позже я опубликую решение.

EDIT:

Вот он:

//load the image
PImage sample;
sample = loadImage("test.png");
size(sample.width, sample.height);
image(sample, 0, 0);
int[][] heat = new int[width][height];

//parameters
int resolution = 5; //distance between points in the gridq
int distance = 8; //distance at wich two points are considered near
float threshold = 0.5;
int level = 240; //leven to detect the dots
int sensitivity = 1; //how much does each dot matters

//calculate the "heat" on each point of the grid
color black = color(0,0,0);
loadPixels();
for(int a=0; a<width; a+=resolution){
  for(int b=0; b<height; b+=resolution){
    for(int x=0; x<width; x++){
      for(int y=0; y<height; y++){
        color c = sample.pixels[y*sample.width+x];        
        /**
         * the heat should be a function of the brightness and the distance, 
         * but this works (tm)
         */
        if(brightness(c)<level && dist(x,y,a,b)<distance){
          heat[a][b] += sensitivity;
        }
      }
    }
  }
}

//render the output
for(int a=0; a<width; ++a){
  for(int b=0; b<height; ++b){
    pixels[b*sample.width+a] = color(heat[a][b],0,0);
  }
}
updatePixels();
filter(THRESHOLD,threshold);

EDIT 2 (менее эффективный код, но тот же вывод):

//load the image
PImage sample;
sample = loadImage("test.png");
size(sample.width, sample.height);
image(sample, 0, 0);
int[][] heat = new int[width][height];
int dotQ = 0;
int[][] dots = new int[width*height][2];
int X = 0;
int Y = 1;


//parameters
int resolution = 1; //distance between points in the grid
int distance = 20; //distance at wich two points are considered near
float threshold = 0.6;
int level = 240; //minimum brightness to detect the dots
int sensitivity = 1; //how much does each dot matters

//detect all dots in the sample
loadPixels();
for(int x=0; x<width; x++){
 for(int y=0; y<height; y++){
   color c = pixels[y*sample.width+x];
   if(brightness(c)<level) {
       dots[dotQ][X] += x;
       dots[dotQ++][Y] += y;
   }
 }
}

//calculate heat
for(int x=0; x<width; x+=resolution){
 for(int y=0; y<height; y+=resolution){
   for(int d=0; d<dotQ; d++){
     if(dist(x,y,dots[d][X],dots[d][Y]) < distance)
       heat[x][y]+=sensitivity;
   }
 }
}

//render the output
for(int a=0; a<width; ++a){
 for(int b=0; b<height; ++b){
   pixels[b*sample.width+a] = color(heat[a][b],0,0);
 }
}
updatePixels();
filter(THRESHOLD,threshold);

/** This smooths the ouput with low resolutions
* for(int i=0; i<10; ++i) filter(DILATE);
* for(int i=0; i<3; ++i) filter(BLUR);
* filter(THRESHOLD);
*/

И результат с (уменьшенным) образцом Кента:

Ответ 2

Я бы предложил использовать ядро ​​с переменным сдвигом, чтобы найти центр плотности ваших точек.

Иллюстрация среднего сдвига http://cvr.yorku.ca/members/gradstudents/kosta/compvis/file_mean_shift_path.gif

На этом рисунке показано, что ядро ​​среднего сдвига (с центром на краю кластера) сходится к точке кластера с наибольшей плотностью.

В теории (в двух словах):

Несколько ответов на эти вопросы уже намекают на способ сглаживания:

То, что вы видите в анимированном рисунке, представляет собой комбинацию этих двух предложений: он использует движущийся "блок" (т.е. ядро) для поиска локально высокой плотности.

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

В каждой итерации ядро ​​определяет его центральные координаты для следующей итерации - это называется сдвигом. Следовательно, название означает сдвиг. Условие остановки для итераций - это когда расстояние сдвига падает до 0 (т.е. Мы находимся в самом плотном пятне в окрестности).

Всестороннее введение в средний сдвиг (как в теории, так и в приложениях) можно найти в этой презентации ppt.

На практике:

Реализация среднего сдвига доступна в OpenCV:

int cvMeanShift( const CvArr* prob_image, CvRect window,
                 CvTermCriteria criteria, CvConnectedComp* comp );

O'Reilly Learning OpenCv (выдержки из книги Google) также содержит хорошее объяснение того, как это работает. В основном просто загрузите это изображение точек (prob_image).

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

Ответ 3

Чтобы добавить немного помощника в Trebs выражение, я думаю, что важно, чтобы реально определить, что определение кластера, конечно, "близко друг к другу", это скорее vauge.

Возьмите этот набор образцов, который я сгенерировал, я знаю, что там есть форма кластера, я его создал.

Однако программная идентификация этого "кластера" может быть сложной.

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

Кроме того, обратите внимание, что есть области сверхвысокой плотности, которые находятся в контексте большей картины, просто отвлекают

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

Что бы вы ни разработали, я бы по крайней мере интересовался тем, как он идентифицирует данные в этом наборе.

(Я думаю, что поиск технологий HDRI ToneMapping может быть в порядке, потому что они работают более или менее по плотности света, и есть "локальные" тонемапы и "глобальные" карты тонов, каждый из которых дает разные результаты)

Ответ 4

Нанесите фильтр размытия на копию вашей 2D-области. Что-то вроде

1 2 3 2 1
2 4 6 4 2
3 6 9 6 3
2 4 6 4 2
1 2 3 2 1

"Более темные" области теперь идентифицируют кластеры точек.

Ответ 5

Вы можете попробовать создать Quadtree представление данных. Более короткие пути на графике будут соответствовать областям с высокой плотностью.

Или, если говорить более четко: при использовании Quadtree и обхода уровня, каждый нижний уровень node, состоящий из "точек", будет представлять собой область с высокой плотностью. По мере увеличения уровня узлов такие узлы представляют собой области с более низкой плотностью "точек"

Ответ 6

Здесь есть отличный учебник по алгоритмам кластеризации , они обсуждают K-средства и K-gussussians.

Ответ 7

Как насчет морфологического подхода?

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

OpenCV поддерживает морфологические операции (как и ряд библиотек обработки изображений):

http://www.seas.upenn.edu/~bensapp/opencvdocs/ref/opencvref_cv.htm#cv_imgproc_morphology

Ответ 8

Это действительно звучит как академический вопрос.

Решение, которое приходит на ум, включает в себя деревья r *. Это делит вашу общую площадь на отдельные по размеру и, возможно, перекрывающиеся ящики. После этого вы можете определить, будет ли каждая ячейка представлять "кластер" или нет для вас, вычисляя среднее расстояние.

R * Деревья

Если этот подход становится сложным для реализации, вам может быть лучше сбить ваш datagrid на подразделения с равным размером и определить, происходит ли кластер в каждом; вы должны быть очень внимательны к краевым условиям с этим подходом. Я бы предположил, что после начального деления вы проходите и рекомбинируете области с datapoints в пределах определенного порога определенного края.

Ответ 9

  • Установите функцию плотности вероятности в данные. Я бы использовал "смесь гауссианцев" и поместил ее с помощью обучения максимизации ожиданий, заправленного алгоритмом K-средних. Значения K-значений сами по себе иногда могут быть достаточными без EM. Число самих кластеров должно быть загружено с помощью алгоритма выбора порядка модели.
  • Затем каждую точку можно забить с помощью p (x) с использованием модели. То есть получить заднюю вероятность того, что точка была сгенерирована моделью.
  • Найдите максимальное значение p (x) для поиска центроидов кластера.

Это можно очень быстро закодировать в инструменте, таком как Matlab, с помощью инструментария машинного обучения. Изучение MoG/EM/кластеризация K-Me широко обсуждаются в веб-стандартах. Мой любимый текст - "Классификация образцов" Дуда/Харта.

Ответ 10

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

Ответ 11

Позвольте мне организовать это как исследовательскую статью

а. Заявление о проблеме

Чтобы процитировать Epaga: "У меня есть 2D-область с" точками ", распределенными по этой области. Теперь я пытаюсь обнаружить" кластеры "точек, то есть областей с определенной высокой плотностью точек".

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

b.Method case 1: Если точки - это просто точки (точки = точки в 2D-пространстве). В этом случае у вас уже будут как x, так и y местоположения для всех точек. Проблема сводится к кластеризации точек. Иван проделал большую работу по предложению решения. Он также обобщил другие ответы подобного вкуса. Мои 2cts в дополнение к его сообщению - это то, что вы считаете, знаете ли вы количество кластеров априори или нет. Алгоритмы (контролируемая и неконтролируемая кластеризация могут быть выбраны соответственно).

случай 2: если точки действительно происходят из изображения. Здесь проблема должна быть уточнена. Позвольте мне объяснить использование этого изображения alt text Если в сером значении точек не делается различий, группы 1, 2, 3, 4 и 5 являются "отдельными кластерами". Однако, если различие делается на основе значения серого, кластер 5 является сложным, так как точка имеет разные значения серого.

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

Ответ 12

Я думаю, это зависит от того, сколько разницы между точками и кластерами. Если расстояния большие и нерегулярные, я первоначально триангулирует точки, а затем удаляет/скрывает все треугольники со статистически большими длинами ребер. Оставшиеся подтреангуляции образуют кластеры произвольной формы. Пересечение ребер этих подтреангуляций дает многоугольники, которые могут быть использованы для определения, какие конкретные точки лежат в каждом кластере. Полигоны также можно сравнить с известными формами, такими как торт Кент Фредрик, по мере необходимости.

IMO, сетчатые методы хороши для быстрых и грязных решений, но очень быстро голодают очень быстро на разреженных данных. Квадратные деревья лучше, но TIN - мой личный фаворит для более сложного анализа.

Ответ 13

Я бы вычислил расстояния от каждой точки до всех других точек. Затем отсортируйте расстояния. Точки, которые имеют расстояние друг от друга, что ниже порога, считаются Near. Группа точек, находящихся рядом друг с другом, представляет собой кластер.

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

Ответ 14

Вы можете наложить логическую сетку поверх своего самолета. Если сетка имеет определенное количество содержащихся точек, она считается "плотной" и затем может быть разбавлена. Это делается в приложениях ГИС при работе с кластерными допусками. Использование сетки помогает разделить ваш алгоритм прореживания.

Ответ 15

Для этого вы можете использовать генетический алгоритм. Если вы определяете "кластер", как, например, прямоугольную подзону с высокой плотностью точек, вы можете создать начальный набор "решений", каждый из которых состоит из некоторого количества случайно сгенерированных неперекрывающихся прямоугольных кластеров, Затем вы должны написать "функцию пригодности", которая оценивает каждое решение - в этом случае вы хотели бы, чтобы функция пригодности сводила к минимуму общее количество кластеров и максимизировала плотность точек в каждом кластере.

Ваш первоначальный набор "решений" будет ужасен, скорее всего, но некоторые, вероятно, будут немного менее страшны, чем другие. Вы используете функцию фитнеса для устранения наихудших решений, а затем создаете решения следующего поколения, скрещивая "победителей" от последнего поколения. Повторяя это поколение процессов по генерации, вы должны получить одно или несколько хороших решений этой проблемы.

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

Ответ 16

Кластер 3.0 включает библиотеку методов С для проведения статистической кластеризации. У этого есть несколько различных методов, которые могут или не могут решить Вашу проблему, основываясь на том, какую форму образуют ваши точечные кластеры. Библиотека доступна здесь здесь и распространяется под лицензией Python.

Ответ 17

Вы пробовали простые, готовые решения, такие как ImagXpress от Accusoft Pegasus?

Метод BlobRemoval может быть настроен на подсчет пикселей и плотность, чтобы найти дыроколы, даже если они не являются непрерывными. (вы также можете попробовать функцию Dilate, чтобы закрыть пробелы)

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

С#:
public void DocumentBlobRemoval (  Область прямоугольника,  int MinPixelCount,  int MaxPixelCount,  короткая MinDensity )