Как я могу найти самые плотные области на изображении? - PullRequest
13 голосов
/ 04 января 2010

Рассмотрим черно-белое изображение, например this

alt text

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

Может кто-нибудь подсказать, как этого можно достичь?

Ответы [ 4 ]

18 голосов
/ 05 января 2010

Если у вас есть доступ к Toolbox для обработки изображений , вы можете воспользоваться рядом фильтрующих и морфологических операций, которые он содержит. Вот один из способов решения вашей проблемы, используя функции imfilter, imclose и imregionalmax:

% Load and plot the image data:
imageData = imread('lattice_pic.jpg');  % Load the lattice image
subplot(221);
imshow(imageData);
title('Original image');

% Gaussian-filter the image:
gaussFilter = fspecial('gaussian', [31 31], 9);  % Create the filter
filteredData = imfilter(imageData, gaussFilter);
subplot(222);
imshow(filteredData);
title('Gaussian-filtered image');

% Perform a morphological close operation:
closeElement = strel('disk', 31);  % Create a disk-shaped structuring element
closedData = imclose(filteredData, closeElement);
subplot(223);
imshow(closedData);
title('Closed image');

% Find the regions where local maxima occur:
maxImage = imregionalmax(closedData);
maxImage = imdilate(maxImage, strel('disk', 5));  % Dilate the points to see
                                                  % them better on the plot
subplot(224);
imshow(maxImage);
title('Maxima locations');

А вот изображение, которое создает приведенный выше код:

enter image description here

Чтобы все выглядело хорошо, я просто продолжал пробовать несколько разных комбинаций для параметров для фильтра Гаусса (созданного с помощью fspecial) и структурирующего элемента (созданного с помощью strel ). Однако это небольшое количество проб и ошибок дало очень хороший результат.

ПРИМЕЧАНИЕ: Изображение, возвращаемое с imregionalmax, не всегда имеет только один пиксель, установленный на 1 (для обозначения максимумов). Выходное изображение часто содержит кластеры пикселей, потому что соседние пиксели во входном изображении могут иметь равные значения и, следовательно, оба учитываются как максимумы. В приведенном выше коде я также расширил эти точки с помощью imdilate, просто чтобы их было легче увидеть на изображении, что делает еще больший кластер пикселей с центром в максимумах. Если вы хотите уменьшить кластер пикселей до одного пикселя, вы должны удалить шаг расширения и изменить изображение другими способами (добавить шум к результату или отфильтровать его, затем найти новые максимумы и т. Д.).

7 голосов
/ 04 января 2010

Раздвижное окно (просто, но медленно)

Вы можете создать скользящее окно (например, размером 10x10 пикселей), которое будет перебирать изображение, и для каждой позиции вы будете подсчитывать количество белых пикселей в этом поле 10x10 и сохранять позиции с наибольшим количеством.

Весь этот процесс: O (n * m) , где n - количество пикселей изображения, а m - размер скользящего окна.

Другими словами, вы свертываете изображение с средним фильтром (здесь фильтр коробки), а затем используете экстремумы.

Раздвижное окно (быстрое)

Сначала вычислите таблицу суммированных областей , которую можно сделать очень эффективно за один проход:

  1. создать двумерный массив sat с тем же размером, что и исходное изображение img.
  2. Итерация по каждому индексу и вычисление для каждого индекса x и y

    sat[x, y] = img[x, y] + sat[x-1, y] + sat[x, y-1] - sat[x-1, y-1]
    

    Например, для изображения, где 0 темное, а 1 белое, это результат:

       img            sat
    0 0 0 1 0 0   0 0 0 1 1 1 
    0 0 0 1 0 0   0 0 0 2 2 2
    0 1 1 1 0 0   0 1 2 5 5 5
    0 1 0 0 0 0   0 2 3 6 6 6
    0 0 0 0 0 0   0 2 3 6 6 6
    
  3. Теперь перебираем индексы таблицы суммированных областей со скользящим окном и вычисляем количество белых пикселей в нем, используя углы A, B, C, D скользящего окна:

       img            sat          window
    0 0 0 1 0 0   0 0 0 1 1 1   0 A-----B 1 
    0 0 0 1 0 0   0 0 0 2 2 2   0 | 0 2 | 2
    0 1 1 1 0 0   0 1 2 5 5 5   0 | 2 5 | 5
    0 1 0 0 0 0   0 2 3 6 6 6   0 | 3 6 | 6
    0 0 0 0 0 0   0 2 3 6 6 6   0 D-----C 6
    

    Рассчитать

    density(x', y') = sat(A) + sat(C) - sat(B) - sat(D)
    

    Что в приведенном выше примере

    density(1, 0) = 0 + 6 - 1 - 2 = 3
    

Для этого процесса требуется временное изображение, но оно просто O (n) , поэтому скорость не зависит от размера скользящего окна.

6 голосов
/ 04 января 2010

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

измените размер фильтра Гаусса, чтобы получить желаемое количество «плотных» областей.

4 голосов
/ 04 января 2010

Может быть, наивный подход:

Вы определяете квадрат n * n, который является максимальным размером области, в которой вы измеряете плотность. Для каждой точки на изображении вы рассматриваете эту точку как центр квадрата и считаете количество черных (b) и белых (w) точек. Используя разницу b-w, вы можете определить, в каких квадратах наиболее белый цвет.

Наиболее плотные области должны быть определены нечетким образом. Если в одной области 600 белых точек, а в другой 599, то для человеческого глаза они имеют одинаковую плотность. 600 - плотность 100%, а 599 - плотность 99% и 1% плотность. Для этого используйте эпсилон.

n может быть предопределено или основано на некоторой функции (т. Е. Процент от размера изображения).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...