当我使用nlfilter函数时如何输出结构数组? [英] How to output a struct array when I use the nlfilter function?
问题描述
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);
其中:
-
value
是0
。 -
size
是输入图像的size()
,例如[100,100]
。
class
是'struct'
。 ...因为 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
is0
.size
is thesize()
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屋!