2016-02-29 24 views
4

我有以下計算統計參數的函數。我想將這個函數傳遞給nlfilter來完成整個圖像的計算。但nlfilter的輸出必須是標量。當我使用nlfilter函數時如何輸出結構數組?

如何將其轉換爲適用於nlfilter的功能手柄,以便我可以保存功能getStatistics2的輸出?

getStatistics2函數的輸出是一個struct數組。

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 
+0

你不能直接做,因爲(如你所寫),'nlfilter'接受一個標量函數句柄。您可以爲'out'結構的每個字段編寫一次調用'nlfilter'的封裝器。 –

+0

什麼是包裝?我無法理解。你能爲我編輯一個示例代碼嗎?現在,我有一個想法,我可以將out結構數組保存爲mat文件。但是如果我這樣做,將會有太多的mat文件。如果我想使用輸出結果,加載這些文件需要很長時間mat文件。我只是想將輸出保存到一個mat文件中。你有什麼好主意嗎?謝謝! @Itamar Katz –

+0

目前尚不清楚您的期望輸出是什麼。 'nlfilter'返回一個矩陣,如果你的結構體具有'n'字段,並且你有一個這樣的長度爲'm'的結構體的數組,那麼你就得到了m * n'矩陣。你想如何存儲它們? –

回答

4

這是一個有趣的問題。有趣的是你的方法幾乎完美。它失敗的唯一原因是因爲struct不能使用數字標量輸入(即struct(3))構造。我提到這一點的原因是因爲nlfilter(特別是在mkconstarray.m)的執行過程中的某個地方,它調用下面的代碼:

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

其中:

  • class'struct'
  • value0
  • size是輸入圖像的size(),例如, [100,100]

...並且因爲feval('struct', 0),這相當於struct(0) - 這是我們已知的無效。

那麼我們該怎麼做?創建一個自定義類,可以這樣構建!

這裏有一個這樣的類的實例:

classdef MyStatsClass % Value class 

    properties (GetAccess = public, SetAccess = private) 
    [email protected] scalar = NaN; % Maximum 
    [email protected] scalar = NaN; % Minimum 
    [email protected] scalar = NaN; % Mean 
    [email protected] scalar = NaN; % Mean absolute deviation y = mean(abs(X-mean(x))) 
    [email protected] scalar = NaN; % Median 
    [email protected] scalar = NaN; % Root mean square 
    [email protected] scalar = NaN; % Stardard deviation 
    [email protected] scalar = NaN; % Variance 
    [email protected] 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 

而且這裏是你如何使用它:

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 

注意,我添加了一個可選的輸入(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] 

「預期結果」爲im(1:WINDOW_SZ,1:WINDOW_SZ)將在索引中找到進一步的「內部」的輸出陣列(在WINDOW_SZ=3的情況下)。

+2

使用'nlfilter'來輸出一個類的實例而不是一個標量輸出是完全想不到的! – rayryeng

相關問題