Проверьте окружающие ненулевые элементы - PullRequest
5 голосов
/ 04 августа 2010

Это следующая часть ниже:

2) Дополнительный вопрос:

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

Примечание: если соседние объекты находятся в радиусе двух или более центров, возьмите наименьшее среднее значение центра для проверки.

    0    12     9     
    4  **9**    15     
   11    19     0 

'9' в середине находится в радиусе 12, 15 и 19 центров, поэтому возьмите минимальное среднее из этих минимальных [9.000, 9.000, 8.000] = 8.000

Например, когда радиус = 1 м или 1 элемент на расстоянии.

new_x =

     0         0          0          0         0
     0         0     **9.0000**    9.0000      0
     0      4.0000     9.0000    **9.0000**    0
     0    **8.3333** **8.0000**      0         0
     0      2.0000     4.0000      8.0000      0
     0      4.0000     5.0000      8.0000      0
     0         0          0          0         0

Test_x =

     0         0           0           0         0
     0         0       **9.0000**      1         0
     0         0           1       **9.0000**    0
     0    **8.3333**   **8.0000**      0         0
     0         0           0           0         0
     0         0           0           0         0
     0         0           0           0         0

=============================================== ==================================

1) Скажите, если у меня есть матрица, показанная ниже,

X =

 0     0     0     0     0
 0     0    12     9     0
 0     4     9    15     0
 0    11    19     0     0
 0     2     4     8     0
 0     4     5     8     0
 0     0     0     0     0

и я хочу найти среднее значение окружающих ненулевых элементов, которое больше 10. Остальные элементы остаются неизменными, т.е. элементы <10. </p>

Итак, я хочу, чтобы мое решение выглядело примерно так:

new_x =

     0         0         0         0         0
     0         0    9.0000    9.0000         0
     0    4.0000    9.0000    9.0000         0
     0    8.3333    8.0000         0         0
     0    2.0000    4.0000    8.0000         0
     0    4.0000    5.0000    8.0000         0
     0         0         0         0         0

Не: что я НЕ только смотрю на соседей элемента, который больше некоторого значения (т. Е. 10 в данном случае).

Допустим, любые элементы, которые больше 10, являются «центром», и мы хотим найти среднее число ненулевых элементов с радиусом, скажем, 1 м. где 1 метр = 1 элемент от центра.

Примечание: он не всегда может быть на расстоянии 1 метра в радиусе, то есть может быть 2 или более. В этом случае это не будет только верх, низ, левый и правый от центра.

**** Также помните о границе матрицы. Например, когда радиус = 2 или более, некоторые из средних ненулевых соседей находятся за пределами границы. **

Например,

Для радиуса = 1 м = 1 элемент, new_x = среднее значение [(i + 1, j), (i-1, j), (i, j + 1) и (i, j-1)] - сверху, снизу, справа и слева от центра.

Для радиуса = 2 м = 2 элемента, new_x = среднее значение [(i + 1, j), (i + 2, j), (i-1, j), (i-2, j), (i, j + 1), (i, j + 2), (i, j-1), (i, j-2), (i + 1, j + 1), (i + 1, j-1), (i-1, j-1) и (I-1, J + 1)].

=============================================== ===================

Я пробовал несколько вещей раньше, однако я не знаком с функциями.

Поэтому, пожалуйста, помогите мне решить проблему.

Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 04 августа 2010

EDIT : Обратите внимание, что для этого требуются функции из панели инструментов обработки изображений, а именно: COLFILT и STREL

r = 1;                       %# radius
t = 10;                      %# threshold value
mid = round((2*r+1)^2/2);    %# mid point
nhood = getnhood(strel('diamond', r));
nhood(mid) = false;
fcn = @(M)sum(M(nhood(:),:),1)./(sum(M(nhood(:),:)~=0)+all(M(nhood(:),:)==0)).*(M(mid,:)>=t)+M(mid,:).*(M(mid,:)<t);
new_x = colfilt(x, 2*[r r]+1, 'sliding',fcn)

Для r = 1:

new_x =
            0            0            0            0            0
            0            0            9            9            0
            0            4            9            9            0
            0       8.3333            8            0            0
            0            2            4            8            0
            0            4            5            8            0
            0            0            0            0            0

Для r = 2:

new_x =
            0            0            0            0            0
            0            0         11.2            9            0
            0            4            9       10.167            0
            0            7       7.7778            0            0
            0            2            4            8            0
            0            4            5            8            0
            0            0            0            0            0

На самом деле, он должен работать для любого radius >= 1

Обратите внимание, как структурирующий элемент ромбовидной формы представляет окрестность:

nhood =
     0     1     0
     1     0     1
     0     1     0

nhood =
     0     0     1     0     0
     0     1     1     1     0
     1     1     0     1     1
     0     1     1     1     0
     0     0     1     0     0

and so on..

Пояснение:

Мы используем функцию COLFILT , которая пересекает матрицу, используя скользящую окрестность NxN, и помещает каждый блок как столбец во временную матрицу.

Мы обрабатываем каждый столбец этой временной матрицы (блоков), используя функцию fcn, и результат будет помещен в правильное место после завершения ( COLFILT использует IM2COL COL2IM внизу).

Мы проверяем два случая в зависимости от значения центра блока:

  1. Если его меньше 10, он возвращает это значение без изменений: M(mid,:)

  2. если его> = 10, мы вычисляем среднее значение ненулевых элементов его окрестности sum(M(nhood(:),:),1) ./ (sum(M(nhood(:),:)~=0) + all(M(nhood(:),:)==0)). Последний член здесь необходимо избегать деления на ноль

Обратите внимание, как объединяются результаты 1 и 2, используя R1.*(M(mid,:)<t) + R2.*(M(mid,:)>=t) для эмуляции выбора if / else.

3 голосов
/ 04 августа 2010

Вот алгоритм, который, я думаю, вы описываете в своем вопросе. Для каждого пикселя:

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

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

fcn = @(x) [x(5) sum(x(2:2:8))/max(sum(x(2:2:8) > 0),1)]*[x(5) < 10; x(5) >= 10];
new_x = nlfilter(X,[3 3],fcn);


EDIT: Если у вас нет доступа к Toolbox для обработки изображений , вы также можете сделать это, используя встроенную функцию CONV2 , например так:

kernel = [0 1 0; ...                      %# Convolution kernel
          1 0 1; ...
          0 1 0];
sumX = conv2(X,kernel,'same');            %# Compute the sum of neighbors
                                          %#   for each pixel
nX = conv2(double(X > 0),kernel,'same');  %# Compute the number of non-zero
                                          %#   neighbors for each pixel
index = (X >= 10);                        %# Find logical index of pixels >= 10
new_x = X;                                %# Initialize new_x
new_x(index) = sumX(index)./max(nX(index),1);  %# Replace the pixels in index
                                               %#   with the average of their
                                               %#   non-zero neighbors

Выше обрабатывает ваш радиус = 1 случай. Чтобы обратиться к вашему случаю radius = 2, вам просто нужно изменить ядро ​​свертки на следующее и перезапустить приведенный выше код:

kernel = [0 0 1 0 0; ...
          0 1 1 1 0; ...
          1 1 0 1 1; ...
          0 1 1 1 0; ...
          0 0 1 0 0];
1 голос
/ 04 августа 2010

РЕДАКТИРОВАТЬ : Вот решение, которое не требует панели инструментов обработки изображений.Однако он использует conv2nan.m, который является частью бесплатной NaN панели инструментов .

Этот подход основан на выполнении двух различных операций фильтрации / свертки: одна, которая получает сумму окружений длякаждый элемент, и тот, который получает количество ненулевых surrounders.Затем вы готовы объединить их, чтобы получить только среднее число ненулевых окружений.Как это:

% set up starting point matrix with some zeros
X = magic(4);
X(X < 5) = 0;

X(X == 0) = NaN; % convert zeros to NaNs to work with conv2nan
countmat = double(X > 0);

cmat = [0 1 0;
        1 0 1;
        0 1 0]; % consider surrounding elements only

[m1,c] = conv2nan(X,cmat); % sum of surrounding elements
[m2,c] = conv2nan(countmat,cmat); % number of surrounding elements > 0

x_new = m1./m2; % compute average we want

x_new = x_new(2:end-1,2:end-1); % trim edges created by conv2
x_new(~countmat) = 0; % restore zero elements
x_new(X < 10) = X(X < 10) % restore < 10 elements

Это делает некоторую дополнительную работу в том, что свертки выполняются для всех элементов, а не только для тех, которые> = 10. Но это более общий подход, чем подход с ручным циклом.

1 голос
/ 04 августа 2010

Вы можете сделать что-то вроде этого: (протестировано в Octave, должно работать в Matlab)

octave-3.2.3:17> toohigh = (x>=10)
toohigh =

   0   0   0   0   0
   0   0   1   0   0
   0   0   0   1   0
   0   1   1   0   0
   0   0   0   0   0
   0   0   0   0   0
   0   0   0   0   0

octave-3.2.3:18> nbr_avg = filter2(ones(3,3)/9,x)
nbr_avg =

   0.00000   1.33333   2.33333   2.33333   1.00000
   0.44444   2.77778   5.44444   5.00000   2.66667
   1.66667   6.11111   8.77778   7.11111   2.66667
   1.88889   5.44444   8.00000   6.11111   2.55556
   1.88889   5.00000   6.77778   4.88889   1.77778
   0.66667   1.66667   3.44444   2.77778   1.77778
   0.44444   1.00000   1.88889   1.44444   0.88889

octave-3.2.3:19> y=x; y(toohigh) = nbr_avg(toohigh)

y =

   0.00000   0.00000   0.00000   0.00000   0.00000
   0.00000   0.00000   5.44444   9.00000   0.00000
   0.00000   4.00000   9.00000   7.11111   0.00000
   0.00000   5.44444   8.00000   0.00000   0.00000
   0.00000   2.00000   4.00000   8.00000   0.00000
   0.00000   4.00000   5.00000   8.00000   0.00000
   0.00000   0.00000   0.00000   0.00000   0.00000

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

Более конкретно, filter2 позволяет вам свертывать произвольную матрицу. Матрица всех делает пространственный фильтр нижних частот.


примечание: моя математика не соответствует вашей. Я не совсем уверен, почему вы хотите усреднить только ненулевых соседей (это дает больший вес ненулевым соседям, когда есть нули), но если вы хотите это сделать, вы можете сделать filter2(ones(3,3),x) ./ M, где M = filter2(ones(3,3),(x ~= 0)) - это число ненулевых соседей.

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