2015-09-15 4 views
9

Wie der Titel sagt, wie kann ich eine nachlaufende Singleton-Dimension zu einer Matrix in Matlab hinzufügen?Wie kann ich eine nachlaufende Singleton Dimension zu einer Matrix hinzufügen

A=ones(3,3,1); gibt eine 3x3-Matrix, während A=ones(1,3,3); eine Matrix 1x3x3 gibt

auf das spezifische Problem hinzu:

Ich habe eine Anwendung, wo ich N M · M-Matrizen haben und ich brauche sie zu stapeln, ist das Ergebnis immer eine MxMxN-Matrix. Allerdings kann N 1 sein, und wenn es so ist, muss die Matrix MxMx1 sein.

Hinweis: Mir ist bewusst, dass dies für Matlab-Skripte, wie Loren suggested, wenig Sinn macht. In Matlab gibt es unendlich viele Singleton-Dimensionen nach Nicht-Singleton-Einsen. Dies ist jedoch ansonsten in der Mex-Umgebung, wo mxGetNumberOfDimensions verwendet wird.

+0

Ich dachte, eine 3x3 Matrix und ein 3x3x1 3D Array wären in Matlab wirklich gleich. Ist das nicht der Fall in Mex-Dateien? –

+0

Haben Sie versucht, es einfach auf '[M M 1]' umzuformen? –

+0

@LuisMendo In Mex-Dateien sind alle Daten (wie es intern in Matlab ist) ein 1D-Array mit Dimensionsdaten. Wenn Sie während der Kodierung eines mex-Wrappers überprüfen müssen, ob die Daten korrekt eingegeben wurden, benötigen Sie Funktionen wie 'mxGetNumberOfDimensions' oder' mxGetDimensions'. Wenn eine Eingabe 3D sein muss, aber eine der Dimensionen 1 sein kann, kann 'mxGetNumberOfDimensions == 3' nicht verwendet werden! –

Antwort

7

Das abschließende Singleton wird von MATLAB sogar aus der Sicht der MEX-API gelöscht. Die docs for mxSetDimensions sagen so viel:

MATLAB® entfernt automatisch alle nachgestellten Singleton Dimensionen angegeben im dims Argument. Wenn beispielsweise ndim gleich 5 und dims gleich [4 1 7 1 1] ist, hat das resultierende Array die Dimensionen 4-mal-1-mal-7.

Auch dies ist von der mxSetDimensions docs.

Hier ist ein Test, dies zu versuchen, mit mxSetDimensions oder mxCreateNumericArray:

// mexSizeTest.cpp 
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]) 
{ 
    if (nrhs!=1) 
     mexErrMsgTxt("Just one input please."); 

    mxArray *M = mxDuplicateArray(prhs[0]); 
    const mwSize ndimsOrig = mxGetNumberOfDimensions(M); 
    const mwSize *dimsOrig = mxGetDimensions(M); 

    mexPrintf("Number of dimensions (input): %d\n\n", ndimsOrig); 

    const mwSize ndims = ndimsOrig + 1; 
    mwSize *dims = (mwSize*) mxMalloc(ndims*sizeof(mwSize)); 
    for (int i=0; i<ndimsOrig; ++i) dims[i] = dimsOrig[i]; 
    dims[ndims-1] = 1; 

    mexPrintf("Target dimensions: ["); 
    for (int i=0; i<ndims-1; ++i) mexPrintf("%d ",dims[i]); 
    mexPrintf("%d]\n\n",dims[ndims-1]); 

    mexPrintf("Reshaping to #dims = %d with trailing singleton.\n", ndims); 
    mxSetDimensions(M, dims, ndims); 
    mexPrintf("Number of Dimensions: %d\n\n", mxGetNumberOfDimensions(M)); 

    // Let's be dangerous to see if the 1 is just hiding under the hood 
    const mwSize *dimsSet = mxGetDimensions(M); 
    mexPrintf("Being dangerous: %d\n\n", dimsSet[ndims-1]); // !!! 
    mxDestroyArray(M); 

    mexPrintf("Creating fresh mxArray of #dims = %d with trailing singleton.\n", 
      ndims); 
    M = mxCreateNumericArray(ndims, dims, mxDOUBLE_CLASS, mxREAL); 
    mexPrintf("Number of Dimensions: %d\n",mxGetNumberOfDimensions(M)); 
    mxDestroyArray(M); mxFree(dims); 
} 

Der MATLAB-Test:

>> M = rand(24,55,1); 
>> size(M) 
ans = 
    24 55 
>> ndims(M) 
ans = 
    2 
>> size(M,454235) % note we can check the 454235th dimension 
ans = 
    1 

Randbemerkung mit diesem size(M,454235) Test: Das, was ist die ndim docs meinen, wenn sie sagen, Trailing singleton dimensions are ignored. Sie werden wirklich nicht ignoriert, sie sind einfach nicht wirklich da!

Das MEX-Test (mexSizeTest.cpp):

>> mexSizeTest(M) 
Number of dimensions (input): 2 

Target dimensions: [24 55 1] 

Reshaping to #dims = 3 with trailing singleton. 
Number of Dimensions: 2 

Being dangerous: -994713024 

Creating fresh mxArray of #dims = 3 with trailing singleton. 
Number of Dimensions: 2 

Ich schlage vor, den Code anzupassen, den Fall zu behandeln, in denen mxGetNumberOfDimensions kehrt 2.

+0

Fantastische Antwort. –

+0

@AnderBiguri Schön das hilft. Hinweis Ich habe einen Fehler behoben (es ist jetzt so, als ob es auf meiner Maschine wäre, nicht eine Ausschneide-Paste von Frankenstein, also sind die Ergebnisse immer noch korrekt). – chappjc

1

Sie permute ein Singleton injizieren können.

A = rand(50,50); %50 x 50 
B = permute(A, [1 3 2]); %50 x 1 x 50 

3 bezieht sich auf den Standard-Singleton. Eine "4" referenziert nichts, so dass Sie für mehrere Injektionen iterieren müssen (Sie können auch nicht "3" wiederholen).

+0

Es tut mir leid, Sie haben den Punkt der Frage verpasst. Außerdem wurde es vor 2 Jahren beantwortet und angenommen. –

+1

Nein, ich beantworte die Frage im Titel, den Google mir hierher gebracht hat, bevor ich die Antwort hatte. Du verstehst SO nicht, wenn du denkst, dass es wichtig ist, dass eine Antwort vor zwei Jahren akzeptiert wurde. Ich werde Downvotes von Leuten wie dir erleiden, damit ich dem nächsten Googler helfen kann. – jiggunjer

+1

Sorry, ich wollte dich nicht beleidigen. Ich habe die Frage gestellt, ich weiß, dass es wichtig ist, denn das ist die Antwort auf die Frage im Körper. Ich sollte ein Wort zum Titel hinzufügen, um es vielleicht klarer zu machen, aber der Körper fragt nach einer * abschließenden * Singleton-Dimension. Ich habe mich geweigert, weil unabhängig davon, was Google sagt, dies die Frage, die ich gestellt habe, nicht beantwortet. –

Verwandte Themen