2

この投稿は私の以前の質問に関連しています: アルゴリズムをそこにアップロードしたため、matlab での画像処理。コードのフィルタリング部分を変更しようとしていると思います。matlabのfilter.m関数では、フィルター(B、A、時間での私のピクセルの進化)を受け入れることができ、フィルター処理された値を返します。しかし、現時点では、時系列全体を一緒に渡さなければなりません。

しかし問題は、時系列全体をフィルターに渡すのではなく、ある方法でコードを変更したいということです。値。1 つの画像をコードに挿入しているので、sudo コードを作成しましたが、フィルタリング部分を変更する方法がわかりません。

clear all
j=1;
for i=0:3000
  str = num2str(i);
  str1 = strcat(str,'.mat');
  load(str1);
  D{j}=A(20:200,130:230);
  j=j+1;
end
N=5;
w = [0.00000002 0.05;0.05 0.1;0.1 0.15;0.15 0.20;
     0.20 0.25;0.25 0.30;0.30 0.35;0.35 0.40;
     0.40 0.45;0.45 0.50;0.50 0.55;0.55 0.60;
     0.60 0.65;0.65 0.70;0.70 0.75;0.75 0.80;
     0.80 0.85;0.85 0.90;0.90 0.95;0.95 0.99999999];
for ind=1:20
  wn = w(ind,:);
  [b,a] = butter(N,wn);
  bCoeff(ind,:)=b;
  aCoeff(ind,:)=a;
end

ts=[];
sumLastImages=[];
for k=1:10 %number of images
  for bands=1:20 %number of bands
    for i=1:10 %image h
      for j=1:10 %image w
        pixelValue = D{k}(i,j);          
        % reflectivity elimination        
        % for the current pixel, have the summation of the same position from before 
        % images and create a mean value base on the temporal values
        sumLastImages(i,j)=pixelValue+sumLastImages(i,j);
        meanValue = sumLastImages(i,j)/k;

        if(meanValue==0)            
          filteredimages{bands}(i,j)=0; 
          continue;
        else
          pixel_calculated_meanvalue = pixelValue/meanValue; 
        end                      
        % filter part that need to be changed, and because we are adding 
        % one value then the reutrn of the filter is one too         
        ts_f = filter(bCoeff(bands,:), aCoeff(bands,:), ...
                      pixel_calculated_meanvalue);                         
        filteredimages{bands}(i,j)=ts_f;            
      end     
    end       

    finalImagesSummation{bands}(:,:) = ...
      (filteredimages{bands}(:,:)^2)+finalImagesSummation{bands}(:,:);
    finalImages{bands}(:,:)=finalImagesSummation/k;
  end
end

編集 私はこのようにコードを変更することができました。これで最初の 200 枚の画像をロードし、その後、画像を 1 つずつフィルターに挿入できますが、問題は"Out of memory. Type HELP MEMORY for your options."大きな画像でエラーが発生することです。コードを効率化するための私のコードは次のとおりです。

%%
cd('D:\MatlabTest\06-06-Lentils');
clear all

%%

N=5;
W = [0.0 0.10;0.10 0.20;0.20 0.30;0.30 0.40;
     0.40 0.50;0.50 0.60 ;0.60 0.70;0.70 0.80 ;
     0.80 0.90;0.90 1.0];

[bCoeff{1},aCoeff{1}] = butter(N,0.1,'Low');
for ind=2:9
  wn = W(ind,:);
  [b,a] = butter(N,wn);
  bCoeff{ind}=b;
  aCoeff{ind}=a;
end
[bCoeff{10},aCoeff{10}] = butter(N,0.9,'high');

%%
j=1;

D = zeros(200,380,320);

T = 200;
K = 0:399;
l = T+1;
Yout = cell(1,10);
figure;

for i = 1:length(K)-200
  disp(i)

  if i == 1
    for j = 1:T
      str = int2str(K(1)+j-1);
      str1 = strcat(str,'.mat');
      load(str1);
      D(j,1:380,1:320) = A;
    end

  else

    str = int2str(l);
    str1 = strcat(str,'.mat');
    load(str1);

    temp = D(2:200,1:380,1:320) ;
    temp(200,1:380,1:320) = A;
    D = temp;
    clear temp
    l = l +1;

  end


  for p = 1:380
    for q = 1:320
      x = D(:,p,q) - mean(D(:,p,q));

      for k = 1:10
        temp = filter(bCoeff{k},aCoeff{k},x);
        if i == 1
          Yout{k}(p,q) = mean(temp);
        else
          Yout{k}(p,q) = (Yout{k}(p,q)  + mean(temp))/2;
        end
      end
    end
  end

  for k = 1:10
    subplot(5,2,k)
    subimage(Yout{k}*1000,[0 255]);
    color bar
    colormap jet
  end
  pause(0.01);
end

disp('Done Loading...')
4

3 に答える 3

2

フィルター関数を書き直す必要はありません簡単な解決策があります。

一度に 1 つのサンプルをフィードする場合は、各入力サンプルが前のサンプルに応じて処理されるように、状態パラメーターfilterも渡す必要があります。フィルター処理後、新しい状態は実際には 2 番目のパラメーターとして返されるため、ほとんどの作業は MATLAB によって既に行われています。これは良い知らせです!

読みやすくするために、変数名を一時的に単純な文字に置き換えさせてください。

a = aCoeff(bands, :);    
b = bCoeff(bands, :);
x = pixel_calculated_meanvalue;

ts_fで表されyます。

そして、これは:

y = filter(b, a, x);

実際にはこれと同等です:

N = numel(x);
y = zeros(N, 1);                             %# Preallocate memory for output
z = zeros(max(length(a), length(b)) - 1, 1); %# This is the initial filter state
for i = 1:N
    [y(i), z] = filter(b, a, x(i), z);
end

結果が同じであることを自分で確認できます。

あなたの例では、コードは次のようになります。

N = numel(pixel_calculated_meanvalue);
ts_f = zeros(N, 1);
z = zeros(max(length(aCoeff(bands, :)), length(bCoeff(bands, :))) - 1, 1); 
for i = 1:N
    [ts_f(i), z] = filter(bCoeff(bands, :), aCoeff(bands, :), ...
        pixel_calculated_meanvalue(i), z);
end

このメソッドを使用すると、一度に 1 つの入力サンプルを処理できますが、filter呼び出しごとに最後のフィルター状態を保存するようにしてください。複数のフィルターを使用する予定がある場合は、フィルターごとに状態ベクトルを格納する必要があります。

于 2012-07-26T20:38:48.503 に答える
2

概要

インクリメンタルに供給できる IIR フィルターだけが必要な場合、つまり一度に完全なベクトルを提供する必要がない場合は、単純に独自の関数を実装していずれかのpersistent変数を使用できます。

シンプルなアプローチ

以下のコード スニペットは 、次のコマンドで制御できる変数myFilterを使用する function を定義します。persistent

  • init: IIR係数を設定します
  • getA: A 係数、つまり outputweights を返します。
  • getB: B 係数、つまり入力重みを返します。
  • getX: 格納された入力データ x[0]、x[1]、... x[M] を返します
  • getY: 出力データ y[0]、y[1]、... y[N] を返します
  • getCurrentY: 最後の出力データ y[N] を返します

関数は次のとおりです。

function result = myFilter(varargin)
% myFilter   A simple IIR filter which can be fed incrementally.
%
% The filter is controlled with the following commands:
%   myFilter('init', B, A)
%      Initializes the coefficients B and A. B are the weights for the
%      input and A for the output.
%   myFilter('reset')
%      Resets the input and output buffers to zero.
%   A = myFilter('getA')
%   B = myFilter('getB')
%      Returns the filter coefficients A and B, respectively.
%   x = myFilter('getX')
%   y = myFilter('getY')
%      Returns the buffered input and output vectors.
%   y = myFilter('getCurrentY')
%      Returns the current output value.
%   myFilter(x)
%      Adds the new value x as input to the filter and updates the 
%      output.

    persistent Bcoeff
    persistent Acoeff
    persistent x
    persistent y

    if ischar(varargin{1})
        % This is a command.
        switch varargin{1}
            case 'init'
                Bcoeff = varargin{2};
                Acoeff = varargin{3};
                Bcoeff = Bcoeff / Acoeff(1);
                Acoeff = Acoeff / Acoeff(1);
                x = zeros(size(Bcoeff));
                y = zeros(1, length(Acoeff) - 1);
                return

            case 'reset'
                x = zeros(size(Bcoeff));
                y = zeros(1, length(Acoeff) - 1);
                return

            case 'getA'
                result = Acoeff;
                return

            case 'getB'
                result = Bcoeff;
                return

            case 'getX'
                result = x;
                return

            case 'getY'
                result = y;
                return

            case 'getCurrentY'
                result = y(1);
                return

            otherwise
                error('Unknown command');
        end
    end

    % A new value has to be filtered.
    xnew = varargin{1};
    x = [xnew, x(1:end-1)];
    ynew = sum(x .* Bcoeff) - sum(y .* Acoeff(2:end));
    y = [ynew, y(1:end-1)];
end

そして使用例:

% Define the filter coefficients. Bcoeff acts on the input, Acoeff on
% the output.
Bcoeff = [4, 5];
Acoeff = [1, 2, 3];
% Initialize the filter.
myFilter('init', Bcoeff, Acoeff);

% Add a value to be filtered.
myFilter(10)
myFilter('getCurrentY')

ans =
    40

% Add another one.
myFilter(20)
myFilter('getCurrentY')

ans =
    50

% And a third one.
myFilter(30)
myFilter('getCurrentY')

ans =
     0

% Compare with the Matlab filter function.
filter(Bcoeff, Acoeff, [10 20 30])

ans =
    40    50     0

このアプローチの欠点は、アクティブなフィルターを同時に 1 つしか持てないことです。これは、たとえば質問で、交互に更新されるさまざまなフィルターがある場合に問題があります。

高度なアプローチ

複数のフィルターを同時に操作するには、フィルターを識別する何らかの方法が必要です。ここで紹介するソリューションは、ハンドルで動作します。ハンドルは単純な整数です。より正確に言えば、これは実際には永続的な配列へのインデックスであり、それ自体がフィルター状態、つまりフィルター係数と入力と出力のバッファーを保持します。

ハンドルを渡す必要があるため、呼び出し構文はもう少し複雑です。ただし、複数のフィルターが同時にアクティブになる可能性があります。

function result = myFilterH(varargin)
% myFilterH   A simple IIR filter which can be fed incrementally.
%             Operates on a filter handle.
%
% The filter is controlled with the following commands:
%   handle = myFilterH('create')
%      Creates a new filter handle.
%   myFilterH(handle, 'init', B, A)
%      Initializes the coefficients B and A. B are the weights for the
%      input and A for the output. handle identifies the filter.
%   myFilterH(handle, 'reset')
%      Resets the input and output buffers to zero.
%   A = myFilterH(handle, 'getA')
%   B = myFilterH(handle 'getB')
%      Returns the filter coefficients A and B, respectively.
%   x = myFilterH(handle, 'getX')
%   y = myFilterH(handle, 'getY')
%      Returns the buffered input and output vectors.
%   y = myFilterH(handle, 'getCurrentY')
%      Returns the current output value.
%   myFilterH(handle, x)
%      Adds the new value x as input to the filter and updates the 
%      output.

    persistent handles

    if ischar(varargin{1})
        if strcmp(varargin{1}, 'create')
            if isempty(handles)
                handles = struct('x', [], 'y', [], 'A', [], 'B', []);
                result = 1;
            else
                result = length(handles) + 1;
                handles(result).x = [];
            end
            return
        else
            error('First argument must be a filter handle or ''create''');
        end
    end

    % The first input should be the handles(hIdx).
    hIdx = varargin{1};
    if hIdx < 0 || hIdx > length(handles)
        error('Invalid filter handle')
    end

    if ischar(varargin{2})
        % This is a command.
        switch varargin{2}
            case 'init'
                handles(hIdx).B = varargin{3};
                handles(hIdx).A = varargin{4};
                handles(hIdx).B = handles(hIdx).B / handles(hIdx).A(1);
                handles(hIdx).A = handles(hIdx).A / handles(hIdx).A(1);
                handles(hIdx).x = zeros(size(handles(hIdx).B));
                handles(hIdx).y = zeros(1, length(handles(hIdx).A) - 1);
                return

            case 'reset'
                handles(hIdx).x = zeros(size(handles(hIdx).B));
                handles(hIdx).y = zeros(1, length(handles(hIdx).A) - 1);
                return

            case 'getA'
                result = handles(hIdx).A;
                return

            case 'getB'
                result = handles(hIdx).B;
                return

            case 'getX'
                result = handles(hIdx).x;
                return

            case 'getY'
                result = handles(hIdx).y;
                return

            case 'getCurrentY'
                result = handles(hIdx).y(1);
                return

            otherwise
                error('Unknown command');
        end
    end

    % A new value has to be filtered.
    xnew = varargin{2};
    handles(hIdx).x = [xnew, handles(hIdx).x(1:end-1)];
    ynew = sum(handles(hIdx).x .* handles(hIdx).B) ...
               - sum(handles(hIdx).y .* handles(hIdx).A(2:end));
    handles(hIdx).y = [ynew, handles(hIdx).y(1:end-1)];
end

そして例:

% Define the filter coefficients.
Bcoeff = [4, 5];
Acoeff = [1, 2, 3];
% Create new filter handles.
fh1 = myFilterH('create');
fh2 = myFilterH('create');
% Initialize the filter handle. Note that reversing Acoeff and Bcoeff creates
% two totally different filters.
myFilterH(fh1, 'init', Bcoeff, Acoeff);
myFilterH(fh2, 'init', Acoeff, Bcoeff);

% Add a value to be filtered.
myFilterH(fh1, 10);
myFilterH(fh2, 10);
[myFilterH(fh1, 'getCurrentY'), myFilterH(fh2, 'getCurrentY')]

ans =
    40.0000    2.5000

% Add another one.
myFilterH(fh1, 20);
myFilterH(fh2, 20);
[myFilterH(fh1, 'getCurrentY'), myFilterH(fh2, 'getCurrentY')]

ans =
    50.0000    6.8750

% And a third one.
myFilterH(fh1, 30);
myFilterH(fh2, 30);
[myFilterH(fh1, 'getCurrentY'), myFilterH(fh2, 'getCurrentY')]

ans =
     0   16.4063

% Compare with the Matlab filter function.
filter(Bcoeff, Acoeff, [10 20 30])

ans =
    40    50     0

filter(Acoeff, Bcoeff, [10 20 30])
ans =
    2.5000    6.8750   16.4063

あなたの例にそれを使用する

この例で高度なアプローチを使用するには、最初にフィルターの配列を作成できます。

fh = [];
for ind = 1:20
  wn = w(ind,:);
  [b,a] = butter(N,wn);
  fh(ind) = myFilterH('create');
  myFilterH(fh(ind), 'init', b, a);
end

後でフィルター部分で、すべてのフィルターに値を追加するだけです。ただし、このためには、ループを逆にする必要もあります。これは、現時点では、ピクセルごとにバンドごとに 1 つのフィルターが必要になるためです。最初にピクセルをループしてからバンドをループすると、フィルターを再利用できます。

for height = 1:10
  for width = 1:10 
    for bands = 1:20
      myFilterH(fh(bands), 'reset');
      for k = 1:10
        [...]
        ts_f = myFilterH(fh(bands), ...
                         pixel_calculated_meanvalue);                         
        filteredimages{bands}(i,j) = myFilterH(fh(bands), 'getCurrentY');
      end
    end
  end
end

それが役立つことを願っています!

于 2012-07-21T00:33:12.767 に答える
0

質問を正しく理解していれば、核心は「Matlab 関数から複数のものを返すにはどうすればよいですか?」です。

次のように複数のものを返すことができます。

function [a,  b, np, x, y] = filter(ord, a,  b, np, x, y)
    %code of function here
    %make some changes to a, b, np, x, and y
end

別の関数からを呼び出してfilterその戻り値をキャッチする場合は、次のようにします。

function [] = main()
    %do some stuff, presumably generate initial values for ord, a,  b, np, x, y
    [new_a,  new_b, new_np, new_x, new_y] = filter(ord, a,  b, np, x, y)  
end

つまり、 を実行するfunction [x, y] = myfunc(a, b)と、myfuncx と y の両方が返されます。

于 2012-07-20T16:50:13.027 に答える