Как сравнить матричный элемент с его соседями без использования цикла в MATLAB? - PullRequest
11 голосов
/ 18 февраля 2011

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

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

Ответы [ 3 ]

9 голосов
/ 18 февраля 2011

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

array = magic(6); %# make some data

msk = [0 1 0;1 0 1;0 1 0]; %# make a 4-neighbour mask

%# dilation will replace the center pixel with the 
%# maximum of its neighbors
maxNeighbour = imdilate(array,msk);

%# set pix to zero if less than neighbors
array(array<maxNeighbour) = 0;

array =
    35     0     0    26     0     0
     0    32     0     0     0    25
    31     0     0     0    27     0
     0     0     0     0     0     0
    30     0    34     0     0    16
     0    36     0     0    18     0

отредактировано для использования тех же данных, что и @gnovice, и для исправления кода

8 голосов
/ 18 февраля 2011

Один из способов сделать это - использовать функцию NLFILTER из Инструментов обработки изображений , которая применяет данную функцию к каждому блоку матрицы M-by-N:

>> A = magic(6)  %# A sample matrix

A =

    35     1     6    26    19    24
     3    32     7    21    23    25
    31     9     2    22    27    20
     8    28    33    17    10    15
    30     5    34    12    14    16
     4    36    29    13    18    11

>> B = nlfilter(A,[3 3],@(b) b(5)*all(b(5) >= b([2 4 6 8])))

B =

    35     0     0    26     0     0
     0    32     0     0     0    25
    31     0     0     0    27     0
     0     0     0     0     0     0
    30     0    34     0     0    16
     0    36     0     0    18     0

Приведенный выше код определяет анонимную функцию , которая использует линейное индексирование , чтобы получить центральный элемент подматрицы 3 × 3 b(5) и сравнить его с 4-связным соседи b([2 4 6 8]). Значение в центральном элементе умножается на логический результат, возвращаемый функцией ALL , который равен 1, когда центральный элемент больше всех его ближайших соседей, и 0 в противном случае.

5 голосов
/ 18 февраля 2011

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

Вот идея разбита ...

Генерация некоторых тестовых данных:

>> sizeA = 3;
A = randi(255, sizeA)

A =

   254   131    94
   135    10   124
   105   191    84

Дополните границы нулевыми элементами:

>> A2 = zeros(sizeA+2) * -Inf;
A2(2:end-1,2:end-1) = A

A2 =

     0     0     0     0     0
     0   254   131    94     0
     0   135    10   124     0
     0   105   191    84     0
     0     0     0     0     0

Построим четыре матрицы первых разностей:

>> leftDiff = A2(2:end-1,2:end-1) - A2(2:end-1,1:end-2)

leftDiff =

   254  -123   -37
   135  -125   114
   105    86  -107

>> topDiff = A2(2:end-1,2:end-1) - A2(1:end-2,2:end-1)

topDiff =

   254   131    94
  -119  -121    30
   -30   181   -40

>> rightDiff = A2(2:end-1,2:end-1) - A2(2:end-1,3:end)

rightDiff =

   123    37    94
   125  -114   124
   -86   107    84

>> bottomDiff = A2(2:end-1,2:end-1) - A2(3:end,2:end-1)

bottomDiff =

   119   121   -30
    30  -181    40
   105   191    84

Найдите элементы, которые превосходят всех соседей:

indexKeep = find(leftDiff >= 0 & topDiff >= 0 & rightDiff >= 0 & bottomDiff >= 0)

Создать полученную матрицу:

>> B = zeros(sizeA);
B(indexKeep) = A(indexKeep)

B =

   254     0     0
     0     0   124
     0   191     0

После оборачивания всего этого в функцию и проверки ее на 1000 случайных матриц 100x100 алгоритм выглядит довольно быстрым:

>> tic;
for ii = 1:1000
A = randi(255, 100);
B = test(A);
end; toc
Elapsed time is 0.861121 seconds.
...