当我使用nlfilter函数时如何输出结构数组? [英] How to output a struct array when I use the nlfilter function?

查看:272
本文介绍了当我使用nlfilter函数时如何输出结构数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下函数来计算统计参数。我想将这个函数传递给 nlfilter 来完成整个图像的计算。但是 nlfilter 的输出必须是标量。



如何将其转换为适合使用的函数句柄使用 nlfilter ,所以我可以保存函数的输出 getStatistics2



getStatistics2 函数的输出是一个 struct 数组。

  function [out] = getStatistics2(D)
D = double(D);
%out.MAX = max(D);%最大
%out.MIN = min(D);%最小
out.MEA =均值(D);%均值
out.MAD = mad(D);%平均绝对偏差y =平均值(abs(X-mean(x)))
out.MED = median(D);%median
out.RAN = D(D) - min(D);%范围
out.RMS = rms(D);%均方根
out.STD = std(D);%标准偏差
out.VAR = var(D);%variance


解决方案

这是个有趣的问题。有趣的是你的方法几乎是完美的。它失败的唯一原因是因为 struct 不能使用数字标量输入(即 struct(3))来构造。我提到这个的原因是因为在执行 nlfilter (具体在 mkconstarray.m ),它会调用下面的代码:

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

其中:


    class 'struct'
  • value 0

  • size 是输入图像的 size(),例如 [100,100]



...因为 feval('struct',0),这相当于 struct(0) - 这个我们已经知道是无效的了。

那么我们该怎么做?创建一个可以用这种方式构造 的自定义类!



下面是一个这样的类的例子:

  classdef MyStatsClass%Value类

(GetAccess = public,SetAccess = private)
MAX @ double scalar = NaN; %最大
MIN @ double scalar = NaN; %最小
MEA @ double scalar = NaN; %均值
MAD @ double scalar = NaN; %平均绝对偏差y =平均值(abs(X-mean(x)))
MED @ double scalar = NaN; %中位数
RMS @ double scalar = NaN; %均方根
STD @ double scalar = NaN; %标准差
VAR @ double scalar = NaN; %差异
RAN @ double scalar = NaN; %范围
结束%属性

方法(Access = public)
%%构造函数:
函数obj = MyStatsClass(vec)
%%特例:
if(nargin == 0)|| (numel(vec)== 1)&& (vec == 0)
%nlfilter分配过程中发生
返回
结束
%%常规情况:
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;
结束%默认构造函数
结束%公共方法
结束%classdef



<

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

rng(35693068); %设置随机种子,重复性
WINDOW_SZ = 3;
im = randn(100);
imF = nlfilter(im,[WINDOW_SZ WINDOW_SZ],@MyStatsClass);

如果输出是严格需要的结构:
如果outputAsStruct
警告关闭MATLAB:structOnObject
imF = arrayfun(@ struct,imF);
在MATLAB的警告:structOnObject
结束

请注意,我添加了一个可选输入( outputAsStruct )可以强制输出为 struct 数组(而不是我们类型的数组自定义类,它在功能上与只读 struct )相同。



注意,默认情况下 nlfilter 用零填充数组,这意味着(1,1)输出将在一个看起来像这样的数组上运行(假设 WINDOW_SZ = 3 ):

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

而不是 im(1:WINDOW_SZ,1:WINDOW_SZ)即:

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

预期结果for im(1:WINDOW_SZ,1:WINDOW_SZ)将在outp ut数组(在 WINDOW_SZ = 3 的情况下,在索引(2,2))。


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 (i.e. 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, e.g. [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)).

这篇关于当我使用nlfilter函数时如何输出结构数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆