简体   繁体   中英

How to output a struct array when I use the nlfilter function?

I have the following function which calculates statistic parameters. I would like to pass this function to nlfilter to do the calculation for a whole image. But the output of nlfilter must be a scalar.

How can I convert this to a function handle suitable for use with nlfilter so I can save the output of the function getStatistics2 ?

The getStatistics2 function's output is an struct array.

function [out] = getStatistics2(D)
D = double(D);   
% out.MAX = max(D);%maximum
% out.MIN = min(D);%minimum
out.MEA = mean(D);%mean
out.MAD = mad(D);% mean absolute deviation y=mean(abs(X-mean(x)))
out.MED = median(D);%median
out.RAN = max(D) - min(D);%range
out.RMS = rms(D);%root mean square
out.STD = std(D);%stardard deviation
out.VAR= var(D);%variance

This is an interesting question. What's interesting is that your approach is almost perfect. The only reason it fails is because struct cannot be constructed using a numeric scalar input (ie struct(3) ). The reason I mention this is because somewhere during the execution of nlfilter (specifically in mkconstarray.m ), it calls the the following code:

repmat(feval(class, value), size);

Where:

  • class is 'struct' .
  • value is 0 .
  • size is the size() of the input image, eg [100,100] .

... and this fails because feval('struct', 0) , which is equivalent to struct(0) - and this we already know to be invalid.

So what do we do? Create a custom class that can be constructed this way!

Here's an example of one such class:

classdef MyStatsClass % Value class

  properties (GetAccess = public, SetAccess = private)
    MAX@double scalar = NaN;  % Maximum
    MIN@double scalar = NaN;  % Minimum
    MEA@double scalar = NaN;  % Mean
    MAD@double scalar = NaN;  % Mean absolute deviation y = mean(abs(X-mean(x)))
    MED@double scalar = NaN;  % Median
    RMS@double scalar = NaN;  % Root mean square
    STD@double scalar = NaN;  % Stardard deviation
    VAR@double scalar = NaN;  % Variance
    RAN@double scalar = NaN;  % Range    
  end % properties

  methods (Access = public)
    %% Constructor:
    function obj = MyStatsClass(vec)
      %% Special case:
      if (nargin == 0) || (numel(vec) == 1) && (vec == 0)
        % This happens during nlfilter allocation
        return
      end      
      %% Regular case:
      obj.MAX = max(vec(:));       
      obj.MIN = min(vec(:));
      obj.MEA = mean(vec(:));
      obj.MAD = mad(vec(:));
      obj.MED = median(vec(:));
      obj.RMS = rms(vec(:));
      obj.STD = std(vec(:));
      obj.VAR = var(vec(:));
      obj.RAN = obj.MAX - obj.MIN;
    end % default constructor
  end % public methods
end % classdef

And here's how you can use it:

function imF = q35693068(outputAsStruct)
if nargin == 0 || ~islogical(outputAsStruct) || ~isscalar(outputAsStruct)
  outputAsStruct = false;
end

rng(35693068); % Set the random seed, for repeatability
WINDOW_SZ = 3;
im = randn(100);
imF = nlfilter(im, [WINDOW_SZ WINDOW_SZ], @MyStatsClass);

% If output is strictly needed as a struct:
if outputAsStruct
  warning off MATLAB:structOnObject
  imF = arrayfun(@struct,imF);
  warning on MATLAB:structOnObject
end

Notice that I have added an optional input ( outputAsStruct ) that can force the output to be a struct array (and not an array of the type of our custom class, which is functionally identical to a read-only struct ).

Notice also that by default nlfilter pads your array with zeros, which means that the (1,1) output will operate on an array that looks like this (assuming WINDOW_SZ=3 ):

[0    0      0    
 0  1.8096 0.5189 
 0 -0.3434 0.6586]

and not on im(1:WINDOW_SZ,1:WINDOW_SZ) which is:

[ 1.8096 0.5189 0.2811
 -0.3434 0.6586 0.8919
 -0.1525 0.7549 0.4497]

the "expected result" for im(1:WINDOW_SZ,1:WINDOW_SZ) will be found further "inside" the output array (in the case of WINDOW_SZ=3 at index (2,2) ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM