2

这篇文章与我之前的问题有关:matlab 中的图像处理, 因为我在那里上传了我的算法。我的想法是我正在尝试更改代码的过滤部分。在 matlab filter.m 函数中可以接受过滤器(B,A,我的像素随时间演变),它会返回过滤后的值。但目前我必须一起通过整个时间序列。

但问题是,现在我想以某种方式更改代码,而不是将整个时间序列传递给过滤器,我想一次传递一个值,但我希望过滤器函数将值视为第 n 个值而不是第一个值。我创建了一个 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 张图像,之后我能够将图像一张一张地注入过滤器,但现在的问题是我收到"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

概述

如果您想要的只是一个 IIR 滤波器,您可以逐步提供它,即您不必一次提供完整的向量,您可以简单地实现自己的函数并使用任一persistent变量。

简单的方法

下面的代码片段定义了一个函数myFilter,它使用persistent 变量,您可以使用以下命令控制变量:

  • init: 设置 IIR 系数
  • getA: 返回 A 系数,即输出权重
  • 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

这种方法的缺点是只能同时拥有一个有源滤波器。这是有问题的,例如在您的问题中,您有不同的过滤器以交替方式更新。

先进的方法

为了同时操作多个过滤器,您需要一些方法来识别过滤器。我在这里介绍的解决方案适用于手柄。句柄是简单的整数。更准确地说,它实际上是一个持久数组的索引,它本身保存着滤波器状态,即滤波器系数以及输入和输出的缓冲区。

调用语法有点复杂,因为你必须传递一个句柄。但是,多个过滤器可能同时处于活动状态。

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

稍后在过滤器部分中,只需将您的值添加到所有过滤器中。但是,为此您还需要反转循环,因为现在您需要每个带每个像素一个过滤器。如果您先循环遍历像素,然后循环遍历波段,则可以重用过滤器:

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 回答
2

无需重写过滤功能,有一个简单的解决方案!

如果您想一次输入filter一个样本,您还需要传递状态参数,以便每个输入样本都根据其前身进行处理。过滤后,新的状态实际上是作为第二个参数返回的,这样大部分工作已经由 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

使用此方法,您可以一次处理一个输入样本,只需确保在每次filter调用后存储最后一个过滤器状态。如果您计划使用多个过滤器,则必须为每个过滤器存储一个状态向量!

于 2012-07-26T20:38:48.503 回答
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),则myfunc返回 x 和 y。

于 2012-07-20T16:50:13.027 回答