2016-02-29 4 views
4

J'ai la fonction suivante qui calcule les paramètres statistiques. Je voudrais passer cette fonction à nlfilter pour faire le calcul pour une image entière. Mais la sortie de nlfilter doit être un scalaire.Comment générer un tableau struct lorsque j'utilise la fonction nlfilter?

Comment est-ce que je peux convertir ceci en une poignée de fonction appropriée pour l'usage avec nlfilter ainsi je peux enregistrer la sortie de la fonction getStatistics2? La sortie de la fonction getStatistics2 est une baie 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

Vous ne pouvez pas le faire directement car, comme vous l'écrivez, 'nlfilter' accepte une poignée de fonction scalaire. Vous pouvez écrire une enveloppe qui appelle 'nlfilter' une fois pour chaque champ de la structure' out'. –

+0

quel est l'emballage? Je ne comprends pas bien. Pouvez-vous éditer un exemple de code pour moi? Maintenant, j'ai une idée, je peux enregistrer le tableau de structure out comme un fichier mat.Mais si je fais cela, il y aura trop de fichiers mat.Si je veux utiliser le résultat de sortie, il faudra beaucoup de temps pour charger ces fichiers mat.Je veux juste enregistrer la sortie à un fichier mat. Avez-vous une bonne idée? Merci! @Itamar Katz –

+0

On ne sait pas quelle est la sortie désirée. 'nlfilter' renvoie une matrice, si votre structure a' n' champs, et vous avez un tableau de telles structures de longueur 'm', alors vous obtenez des matrices' m * n'. Comment voulez-vous les stocker? –

Répondre

4

Ceci est une question intéressante. Ce qui est intéressant, c'est que votre approche est presque parfaite. La seule raison pour laquelle cela échoue est que struct ne peut pas être construit en utilisant une entrée scalaire numérique (c'est-à-dire struct(3)). La raison pour laquelle je mentionne cela est parce que quelque part lors de l'exécution de nlfilter (en particulier dans mkconstarray.m), il appelle le code suivant:

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

Où:

  • class est 'struct'.
  • value est 0.
  • size est le size() de l'image d'entrée, par ex. [100,100].

... et cela échoue parce feval('struct', 0), ce qui équivaut à struct(0) - et ce que nous savons déjà invalide.

Alors, que faisons-nous? Créez une classe personnalisée que peut être construite de cette façon!

Voici un exemple d'une telle classe:

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 

Et voici comment vous pouvez l'utiliser:

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 

Notez que j'ai ajouté une entrée en option (outputAsStruct) qui peut forcer la sortie pour être un tableau struct (et non un tableau du type de notre classe personnalisée, qui est fonctionnellement identique à une lecture seule struct).

Notez également que par défaut nlfilter PADS tableau avec des zéros, ce qui signifie que la sortie (1,1) fonctionnera sur un tableau qui ressemble à ceci (en supposant WINDOW_SZ=3):

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

et non sur im(1:WINDOW_SZ,1:WINDOW_SZ) qui est:

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

le « résultat attendu » pour im(1:WINDOW_SZ,1:WINDOW_SZ) on trouvera plus loin « intérieur » de la matrice de sortie (dans le cas de WINDOW_SZ=3 à l'indice (2,2)).

+2

L'utilisation de 'nlfilter' pour sortir des instances d'une classe plutôt qu'une seule sortie scalaire est totalement hors des sentiers battus! – rayryeng