2009-05-25 9 views
8

Ich habe eine riesige 2D Matrix und möchte 15 verschiedene 100x100 Teile daraus extrahieren. Ich habe zwei Vektoren x und y, wo die oberen linken Indizes der Teile gespeichert werden. Ich habe etwas wie folgt verwendet:MATLAB: Extrahiere mehrere Teile einer Matrix, ohne Schleifen zu verwenden

result = cam1(x(1:end):(x(1:end)+99), y(1:end):(y(1:end)+99)); 

aber das Ergebnis ist nur eine Matrix 100x100 anstelle von 15x100x100. Warum?

Ich weiß, es könnte leicht mit einer Schleife gemacht werden, aber wir dürfen keine Schleifen verwenden (es ist Teil einer Bildverarbeitung). Eine andere Möglichkeit wäre, alle 15 Zeilen zu schreiben, aber das ist irgendwie hässlich.

Haben Sie eine elegante Lösung? Vielen Dank.

Antwort

6

Es gibt eine Reihe von Möglichkeiten, dies ohne Schleifen zu tun. Die meisten Lösungen umfassen das Erweitern der Vektoren x und y in größere Matrizen von Indizes und würden wahrscheinlich eine oder mehrere der Funktionen REPMAT, BSXFUN oder SUB2IND verwenden. Ein gutes Tutorial zur Matrix-Indexierung finden Sie unter here.

Da Sie jedoch nach einer eleganten Lösung gefragt haben, hier ist eine, die etwas ungewöhnlich ist. Es nutzt anonymous functions sowie die Funktionen ARRAYFUN und CAT:

indexFcn = @(r,c) cam1(r:(r+99),c:(c+99)); 
result = arrayfun(indexFcn,x,y,'UniformOutput',false); 
result = cat(3,result{:}); 

ERKLÄRUNG:

Die erste Zeile erstellt eine anonyme Funktion. Dies ist eine einfache Ein-Zeilen-Funktion, die im Handumdrehen erstellt werden kann, ohne sie in eine M-Datei schreiben zu müssen. Die Funktion definiert zwei Eingänge r und c, die verwendet werden, um eine 100-by-100 Submatrix von cam1 zu extrahieren. Die Variable indexFcn speichert eine function handle, mit der die Funktion aufgerufen wird.Beachten Sie, dass die von der anonymen Funktion verwendeten Werte cam1statisch sind. Auch wenn sich die Werte in der Variablen cam1 ändern, verwendet die anonyme Funktion immer noch die Werte, die beim Erstellen der Funktion in cam1 waren.

Die zweite Zeile ruft ARRAYFUN auf, die eine Funktion auf jedes Element eines Arrays anwendet. ARRAYFUN führt eine Schleife über jeden Eintrag in x und y und übergibt die Werte an indexFcn. Die Ausgabe wird in Ergebnis, einem 15-Element-Zellenarray gespeichert, wobei jede Zelle eine 100-mal-100-Matrix enthält.

Die dritte Zeile verwendet die CAT-Funktion zum Verketten der 100-by-100-Matrizen in einer 100-mal-100-mal-15-Matrix.

+1

nach der Frage, die ich etwas mehr Forschung hat geschrieben zu haben und fand die arrayfun Funktion und ich kam mit den folgenden: digval1 = arrayfun (@ (i) Summe (Summe (cam1 (y (i) :(y (i) +99), x (i) :(x (i) +99))))/10000, 1:15); Dies beinhaltet bereits den nächsten Schritt, den ich machen musste: Berechnen Sie den Durchschnitt über die Teile. aber vielen Dank für Ihre Hilfe, ich weiß jetzt, dass ich das Richtige getan habe und ich habe Ihren Code verwendet, um eine schönere Linie zu bekommen: digval1 = arrayfun (@ (i, j) Summe (Summe (cam1 (j: j +99, i: i + 99)))/10000, x, y); –

+0

Gut zu helfen! Zu Ihrer Information: Wenn Sie Zugriff auf die Image Processing Toolbox haben, gibt es eine Funktion namens MEAN2 (http://www.mathworks.com/access/helpdesk/help/toolbox/images/mean2.html), die Ihre Funktion vereinfachen würde: digval1 = arrayfun (@ (i, j) mean2 (cam1 (j: j + 99, i: i + 99)), x, y); Alternativ können Sie Ihre eigene MEAN2-Funktion schreiben: mean2 = @ (A) mean (A (:)); – gnovice

+1

jetzt das ist sexy :) –

4

Da dies offensichtlich Hausaufgaben ist, werde ich Ihnen nicht die vollständige Antwort geben.

Es gibt mehrere Möglichkeiten, in eine Matrix zu indizieren. Wenn Sie einen verstreuten Index festgelegt haben, müssen Sie einen einzelnen Index verwenden. Wenn also

A = rand(5,6) 
A = 
     0.81472  0.09754  0.15761  0.14189  0.65574  0.75774 
     0.90579  0.2785  0.97059  0.42176  0.035712  0.74313 
     0.12699  0.54688  0.95717  0.91574  0.84913  0.39223 
     0.91338  0.95751  0.48538  0.79221  0.93399  0.65548 
     0.63236  0.96489  0.80028  0.95949  0.67874  0.17119 

A(3:4,3:4) 

eine 2x2-Untermatrix von A. ergeben Wir können aber auch, dass die Submatrix als

reshape(A([13 14 18 19]),[2 2]) 
ans = 
     0.95717  0.91574 
     0.48538  0.79221 

finden Warum habe ich diesen Index Set wählen? Für die Antwort müssen Sie über sub2ind lesen.

[I,J] = ndgrid(3:4,3:4); 
sub2ind([5 6],I(:),J(:)) 
ans = 
    13 
    14 
    18 
    19 

Am Ende sieht es so aus, als ob Sie ein 15x100x100 Array aus den extrahierten Teilen wollen. Also baue aus den gezeigten Teilen das notwendige Index-Array auf. Sie müssen am Ende eine letzte Umformung vornehmen, um die richtige Form zu erhalten.

Dies sollte Ihnen genug von einem Start geben, um Ihre Hausaufgaben zu beenden.

0

Sie denken alle viel zu schwer, versuchen Sie dieses: mat2cell

+1

würde 'mat2cell' auch in Fällen funktionieren, in denen die Untermatrizen innerhalb der größeren Matrix nicht gleichmäßig verteilt sind? Die ursprüngliche Frage besagt, dass die oberen linken (x, y) Indizes der Untermatrizen als Eingabeparameter bereitgestellt werden, so dass die Untermatrizen höchstwahrscheinlich nicht gleichmäßig beabstandet sind. h. es ist nicht einfach ein Prozess, bei dem die größere Matrix gleichmäßig zersetzt wird. – cjh

Verwandte Themen