nlfilter, дважды принимающий одни и те же значения

#matlab

#matlab

Вопрос:

Я использовал nlfilter для своей тестовой функции следующим образом:

 function funct
clear all;
clc;
I = rand(11,11);
ld = input('Enter the lag = ') % prompt for lag distance
A = nlfilter(I, [7 7], @dirvar);

% Subfunction
    function [h] = dirvar(I)
        c = (size(I) 1)/2
        EW = I(c(1),c(2):end)
        h = length(EW) - ld
    end
end
  

Функция работает нормально, но ожидается, что nlfilter она будет прогрессировать поэлементно, но в первых двух итерациях значения EW будут одинаковыми 0.2089 0.4162 0.9398 0.1058 . Но затем для всех итераций выбирается следующий элемент, для 3-го это 0.4162 0.9398 0.1058 0.1920 , для 4-го это 0.9398 0.1058 0.1920 0.5201 и так далее. Почему это так?

Ответ №1:

Об этом не о чем беспокоиться. Это происходит потому, что nlfilter должен оценить вашу функцию, чтобы знать, какой вывод создавать. Таким образом, он использует feval один раз, прежде чем начать перемещаться по изображению. Результат этого февального вызова — это то, что вы видите в первый раз.

Из кода nlfilter:

 % Find out what output type to make.
rows = 0:(nhood(1)-1);
cols = 0:(nhood(2)-1);
b = mkconstarray(class(feval(fun,aa(1 rows,1 cols),params{:})), 0, size(a));

% Apply fun to each neighborhood of a
f = waitbar(0,'Applying neighborhood operation...');
for i=1:ma,
    for j=1:na,
        x = aa(i rows,j cols);
        b(i,j) = feval(fun,x,params{:});
    end
    waitbar(i/ma)
end
  

Вызов 4-й строки для eval — это то, что вы наблюдаете как первый вывод из EW, но он не используется ни для чего другого, кроме как для придания матрице b правильного класса. Все надлежащие итерации выполняются в приведенном ниже цикле for. Это означает, что наблюдаемые вами «повторяющиеся» значения не влияют на вашу конечную выходную матрицу, и вам не нужно беспокоиться.

Ответ №2:

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

 sz = size(I,2);
h = sz - (sz 1)/2 - ld;
  

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

Комментарии:

1. Я использую length функцию для получения количества элементов. Я не использовал здесь точки с запятой, поскольку хотел проверить, как выполняется функция. Спасибо за ваши предложения!