WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Vektorisieren von for-Schleifen

 

Thomas K
Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 21.08.2012, 15:04     Titel: Vektorisieren von for-Schleifen
  Antworten mit Zitat      
Hallo,

ich habe ein paar sehr zeitaufwendige for-Schleifen in meinem Programm laufen, und möchte das Programm gerne beschleunigen. Dabei habe ich an Vektorisieren gedacht, allerdings habe ich das noch nicht hinbekommen.

Folgende for-Schleifen sollen vektorisiert werden:

Code:
for i=1:length(x)
    for j=1:length(y)
        if round(yO(j)) < sizeY && round(xO(i)) < sizeX && round(yO(j)) > 2 && round(xO(i)) > 2
            if round(yN(i,j)) < sizeY && round(xN(i,j)) < sizeX && round(yN(i,j)) > 2 && round(xN(i,j)) > 2
                %______________________________________________________
                %Bilineare Interpolation:
                xN1 = floor(xN(i,j));   %x-Koord. des 1. Stuetzpunktes
                xN2 = ceil(xN(i,j));   %x-Koord. des 2. Stuetzpunktes
                yN1 = floor(yN(i,j));   %y-Koord. des 1. Stuetzpunktes
                yN2 = ceil(yN(i,j));   %y-Koord. des 2. Stuetzpunktes

                Q = [R(yN1,xN1),R(yN1,xN2);R(yN2,xN1),R(yN2,xN2)];      %Matrix mit den Werten der Stuetzpunkte
                p = [(xN2-xN(i,j))/(xN2-xN1);(xN(i,j)-xN1)/(xN2-xN1)];   %Vektor mit Gewichtungsfunktionen fuer x-Richt.
                o = [(yN2-yN(i,j))/(yN2-yN1),(yN(i,j)-yN1)/(yN2-yN1)];   %Vektor mit Gewichtungsfunktionen fuer y-Richt.    

                H(round(yO(j)),round(xO(i))) = o*(Q*p); %Bilineare Interpolation in Matrixschreibweise                  
            end
        end
    end
end
und:

for k=1:size(CoordBrake,1)
    if CoordBrake(k,1) < sizeX && CoordBrake(k,2) < sizeY && CoordBrake(k,1) > 0 && CoordBrake(k,2) > 0
        Matrix(CoordBrake(k,2),CoordBrake(k,1)) = Replace(CoordBrake(k,2),CoordBrake(k,1));
    end
end
 

Wie gesagt, was ich bisher probiert habe hat nicht funktioniert, wäre für Hilfe sehr dankbar. Vielleicht weiß jemand auch eine andere Möglichkeit diesen Code zu beschleunigen.

Freundliche Grüße, Thomas.
Private Nachricht senden Benutzer-Profile anzeigen


Thomas K
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.08.2012, 14:03     Titel:
  Antworten mit Zitat      
Hallo nochmal,

ich habs leider immer noch nicht hinbekommen. Zwar konnte ich durch ändern der Reihenfolge der for-Schleifen und vordefinieren der sinus- und cosinus-Werte diese eine geschachtelte Schleife etwas beschleunigen, bei der Vektorisierung bin ich jedoch noch nicht weiter gekommen. Ich frage mal anders:
Code:
co = cos(theta);
si = sin(theta);

for j=1:length(y)                                                   %Hier Drehrichtung im Uhrzeigersinn!
    for i=1:length(x)
        xN(i,j) = round(x(i)*co+y(j)*si+origin(1));   %minus sinus in dieser Zeile: Gegenuhrzeigersinn
        yN(i,j) = round(y(j)*co-x(i)*si+origin(2));   %minus sinus in dieser Zeile: Uhrzeigersinn
    end
end

Ich habe eine Matrix, die ich um einen Winkel theta rotieren möchte. Jetzt brauche die Koordinaten der neuen (rotierten) Matrix.
xN und yN sind ähnlich wie beim Befehl meshgrid zwei Matrizen die einem alten Koordinatenpaar ein neues (rotiertes) Paar zuordnen.Die oben angeführte Schleife liefert diese Koordinaten auch korrekt allerdings würde ich das gerne beschleunigen.
Ist hier eine Vektorisierung in dieser Form überhaupt möglich? Könnte man diese Rotation effizienter gestalten?

Gruß, Thomas.
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.08.2012, 14:23     Titel:
  Antworten mit Zitat      
Währe das nicht http://de.wikipedia.org/wiki/Rotationsmatrix !?

Eine Matrix kannst Du nicht rotieren. Du hast in der Matrix entweder ein
http://de.wikipedia.org/wiki/Orthogonalsystem oder http://de.wikipedia.org/wiki/Orthonormalsystem oder Du hast Spalten- oder Zeilenvektoren (Bei den Ortho-Systemen hast Du letztendlich auch Vektoren). Du kannst jetzt jeden einzelnen Vektor um einen Winkel routieren, wobei allgemein für R^n keine Rotation existiert, sondern dies dann eine affine Abbildung ( http://de.wikipedia.org/wiki/Affine_Abbildung ) ist.

D.h. eine Matrix ist die Abbildungsmatrix, die man mit den Daten einmal nur initialisieren muss und dann kann man mit Hilfe der entsprechenden Zugriffsoperatoren auf die Spalten / Zeilen der Datenmatrix zugreifen und die Daten der Matrix abbilden

In Deinem ersten Post steht etwas von Interpolation, dies bietet Matlab auch fertig an http://www.mathworks.de/help/techdoc/ref/interp1.html
Private Nachricht senden Benutzer-Profile anzeigen
 
Thomas K
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.08.2012, 14:44     Titel:
  Antworten mit Zitat      
Hallo,

ich rotiere auch nicht die Matrix, da hab ich mich schlecht ausgedrückt, sondern das Koordinatensystem. Ich habe eine dreidim. Matrix mit 240x320x3000 Einträgen. Jede dieser 240x320 Matrizen entspricht einem Bild, welches mit der Zeit rotiert. Die Winkel sind mir bekannt, auch gelingt es mir mit dem obigen Skript die Koordinaten im neuen Bild zu ermitteln (d.h, das Koordinatensystem so zu drehen, dass ich aus dem ehemals rotierendem Bild ein stehendes erzeugen kann): Ich rotiere das Koordinatensystem greife die Werte an den neuen Positionen ab und schreibe sie auf die Positionen im nicht-rotierten Koordinatensystem.

Das Skript erfüllt also seinen Zweck, ich hätte nur gerne gewusst, ob dies auch schneller, effizienter geht.

Gruß, Thomas.
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.08.2012, 16:03     Titel:
  Antworten mit Zitat      
Jede Spalte (Bild) Deiner Matrix ist ein Vektor und wenn Du die Winkel kennst, dann kannst Du es auch rotieren. Du wirst ja das ganze Bild rotieren und nicht nur einen Teilbereich, d.h. jedes Pixel (Element des Vektors) wird um den gleichen Winkel verändert.

D.h. Du musst die Rotationsmatrix passend bestimmen und dann auf die Datenmatrix anwenden (ggf, wenn sich die Matrix von Vektor zu Vektor bzw. Bild zu Bild ändert, brauchst Du eine Schleife)
Matematisch
Code:

rotate = vector * R
 


Wobei R die Rotationsmatrix ist
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 23.08.2012, 23:48     Titel:
  Antworten mit Zitat      
Hallo Thomas,

Welches ist nun der Code, den Du beschleunigen möchtest?
In dem Code, den Du zeigst, werden die Ausgaben nicht pre-alloziert. Dies wäre ein dramatischer Nachteil. Beispiel:
Code:
co = cos(theta);
si = sin(theta);
xN = zeros(length(x), length(y));  % Pre-allocate!
yN = zeros(length(x), length(y));
for j=1:length(y)
    xN(:, j) = round(x(1:length(x))*co+y(j)*si+origin(1));
    yN(:, j) = round(y(j)*co-x(1:length(x))*si+origin(2));
end

Ich habe also einfach nur den Index aus der "for i"-Schleife in die Berechnung einbezogen. Dann kann man natürlich auch statt "x(1:length(x))" einach "x" schreiben. Eventuell muss man jedoch x noch transponieren.
Und die zweite Schleife läßt sich auch noch vermeiden:
Code:
xN = round(bsxfun(@plus, x * co + y' * si) + origin(1);
yN = round(bsxfun(@minus, y * co - x' * si) + origin(2);

Dann ist die Pre-allocation nicht hilfreich. Eventuell müssen auch hier wieder x und y anders transponiert werden. Aber das kannst Du am besten selbst testen.

Es ist immer hilfreich, genau den Code zu posten, der optimiert werden soll und passende Test-Daten mitzuliefern, damit wir die direkt laufen lassen können.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Thomas K
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 24.08.2012, 09:42     Titel:
  Antworten mit Zitat      
Hallo Jan,

herzlichen Dank für deine Hilfe, habe den Code von dir eingebaut. Dieser Teil arbeitet bei mir jetzt etwa 5 mal schneller!

Das zweite Code-Segment, wo ich denke dass noch mehr Optimierungspotential drinnen ist, ist folgendes:

Code:

%Testdaten:
R = reshape(randperm(100,10*10),10,10);

x = -200:0.5:200;
y = -200:0.5:200;
xO = x+origin(1);
yO = y+origin(2);
origin = [150 120];
[sizeX sizeY sizeZ] = size(R);
lx = length(x);
ly = length(y);
theta = 0.1*pi;
co = cos(theta);
si = sin(theta);

xN = round(bsxfun(@plus,x'*co,y*si)+origin(1));
yN = round(bsxfun(@minus,y*co,x'*si)+origin(2));

%__________________________________________________________________________
%Zu optimieren:

for i=1:lx
    for j=1:ly
        if round(yO(j)) < sizeY && round(xO(i)) < sizeX && round(yO(j)) > 2 && round(xO(i)) > 2
            if round(yN(i,j)) < sizeY && round(xN(i,j)) < sizeX && round(yN(i,j)) > 2 && round(xN(i,j)) > 2
                %______________________________________________________
                %Bilineare Interpolation:
                xN1 = floor(xN(i,j));   %x-Koord. des 1. Stuetzpunktes
                xN2 = ceil(xN(i,j));   %x-Koord. des 2. Stuetzpunktes
                yN1 = floor(yN(i,j));   %y-Koord. des 1. Stuetzpunktes
                yN2 = ceil(yN(i,j));   %y-Koord. des 2. Stuetzpunktes

                Q = [R(yN1,xN1),R(yN1,xN2);R(yN2,xN1),R(yN2,xN2)];      %Matrix mit den Werten der Stuetzpunkte
                p = [(xN2-xN(i,j))/(xN2-xN1);(xN(i,j)-xN1)/(xN2-xN1)];   %Vektor mit Gewichtungsfunktionen fuer x-Richt.
                o = [(yN2-yN(i,j))/(yN2-yN1),(yN(i,j)-yN1)/(yN2-yN1)];   %Vektor mit Gewichtungsfunktionen fuer y-Richt.    

                H(round(yO(j)),round(xO(i))) = o*(Q*p); %Bilineare Interpolation in Matrixschreibweise                  
            end
        end
    end
end


Dabei werden die Daten von R mit Hilfe der rotierten Koordinaten in xN und yN in eine neue Matrix H geschrieben, dabei wird noch eine bilineare Interpolation durchgeführt. Ich weiß Matlab bietet eine eigene Funktion dafür, konnte diese aber noch nicht erfolgreich einbauen, also hab ich es so programmiert.

Wäre super wenn du auch hierfür ein paar Tips zum Beschleunigen hättest. Vielen Dank schon mal und freundliche Grüße,

Thomas.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 26.08.2012, 01:13     Titel:
  Antworten mit Zitat      
Hallo Thomas,

Die Definition von "origin" muss vor der Benutzung erfolgen.
Mit den Testdaten wird die eigentliche Berechnung nicht erreicht und H nicht definiert. Kannst Du etwas passenderes angeben?

Ein paar Dinge lassen sich trotzdem finden:
Code:

match =  round(yO) < sizeY && round(yO) > 2;  % Nur einmal testen!
for i=1:lx
  if round(xO(i)) < sizeX && round(xO(i)) > 2  % Ausserhalb der Schleife!
    for j=1:ly
        if match(j)
            % yN und xN sind bereits gerundet!
             if yN(i,j) < sizeY && xN(i,j) < sizeX && yN(i,j) > 2 && xN(i,j) > 2
                ...

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Thomas K
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.08.2012, 09:10     Titel:
  Antworten mit Zitat      
Hallo Jan,

vielen Dank für deine Hilfe, ich lerne dabei gerade wieder eine Menge dazu.


Leider konnte ich keine Dateien anhängen (funktionierte bei mir aus irgendeinem Grund nicht), deshalb habe ich eine Testmatrix im richtigen Format mit Zahlen zwischen 200 und 800 in dieser Schleife erzeugt:
Code:

M = zeros(240,320);
for i=1:320
    for j=1:240
        r = 200+(800-200).*rand(1,1);
        M(j,i) = r;
    end
end
 


Hier noch einmal der originale Code:

Code:

origin = [154 120];
R = M;
[sizeX sizeY] = size(R');
x = -200:0.5:200;
y = -200:0.5:200;
xO = x+origin(1);
yO = y+origin(2);
 

lx = length(x);
ly = length(y);
theta = 0.1*pi;
co = cos(theta);
si = sin(theta);

%xN und yN müssen hier nicht gerundet werden
xN = bsxfun(@plus,x'*co,y*si)+origin(1);
yN = bsxfun(@minus,y*co,x'*si)+origin(2);
%%{
tic

for i=1:length(x)
    for j=1:length(y)
        if round(yO(j)) < sizeY && round(xO(i)) < sizeX && round(yO(j)) > 2 && round(xO(i)) > 2
            if yN(i,j) < sizeY && xN(i,j) < sizeX && yN(i,j) > 2 && xN(i,j) > 2
                %______________________________________________________
                %Bilineare Interpolation:
                xN1 = floor(xN(i,j));   %x-Koord. des 1. Stuetzpunktes
                xN2 = ceil(xN(i,j));   %x-Koord. des 2. Stuetzpunktes
                yN1 = floor(yN(i,j));   %y-Koord. des 1. Stuetzpunktes
                yN2 = ceil(yN(i,j));   %y-Koord. des 2. Stuetzpunktes

                Q = [R(yN1,xN1),R(yN1,xN2);R(yN2,xN1),R(yN2,xN2)];      %Matrix mit den Werten der Stuetzpunkte
                p = [(xN2-xN(i,j))/(xN2-xN1);(xN(i,j)-xN1)/(xN2-xN1)];   %Vektor mit Gewichtungsfunktionen fuer x-Richt.
                o = [(yN2-yN(i,j))/(yN2-yN1),(yN(i,j)-yN1)/(yN2-yN1)];   %Vektor mit Gewichtungsfunktionen fuer y-Richt.    

                H1(round(yO(j)),round(xO(i))) = o*(Q*p); %Bilineare Interpolation in Matrixschreibweise
            end
        end
    end
end
 

Habe deinen Code schon ausprobiert, er läuft mit der oben angeführten Testmatrix auch etwas schneller, denke dass das meiste Potetial aber in der Berechnung im Schleifenkörper steckt.

Freundliche Grüße, Thomas.
Private Nachricht senden Benutzer-Profile anzeigen
 
Thomas K
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.08.2012, 10:21     Titel:
  Antworten mit Zitat      
Hallo,

habe versucht diese bipolare Interpolation mit der Matlab-Funktion interp2 umzusetzen, was mir aber nicht gelungenist:

ZI = interp2(X,Y,Z,XI,YI)

X und Y enthalten die Koordinaten der Stützstellen, was bei mir xN und yN entsprechen sollte, Z die oben angegebene Matrix. Ich scheitere leider schon daran xN und yN in ein passendes Format zu wandeln, sodass ich interp2 darauf anwenden kann, dann müssen diese Koordinaten in xN und yN ja noch mit ceil bzw. floor bearbeitet werden (wie oben im Code).

Dann habe ich da noch eine weitere Frage zur Vektorisierung:
Code:

rIn = 10;
zeta = linspace(0,pi/2,100);
origin = [154 120];        
Matrix = abs(randn(500,500)*100);
xR = round((rIn+10)*cos(zeta)+origin(1));
yR = round((rIn+10)*sin(zeta)+origin(2));
for j=1:size(zeta,2)          
    celsius2(j) = Matrix(yR(j),xR(j));
end
 

Gibt es eine Möglichkeit Schleifen dieses Typs durch Matrixoperationen zu ersetzen?

Schöne Grüße, Thomas.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 28.08.2012, 11:55     Titel:
  Antworten mit Zitat      
Hallo Thomas,

Ich kam gestern nicht dazu es unter Matlab laufen zu lassen. Heute zunächst mal ein paar Ideen, die ich aber nicht testen kann:

Testdaten ohne Schleife:
Code:
M = 200 + 600 * rand(240, 320);


Was geschieht eigentlich, wenn xN(i,j) ein Integer ist? Dann ist "floor(xN(i,j)) == ceil(xN(i,j))". Ist das so gewollt?

Code:
origin = [154, 120];
R = M;
[sizeY, sizeX] = size(R);  % TRANSPOSE costs time
x = -200:0.5:200;
y = -200:0.5:200;
xO = x + origin(1);
yO = y + origin(2);

lx = length(x);
ly = length(y);
theta = 0.1 * pi;
co = cos(theta);
si = sin(theta);

% "xN und yN müssen hier nicht gerundet werden"
% Das sollten sie aber! Ansonsten muss dies wiederholt in der Schleife
% gemacht werden!
xN = bsxfun(@plus, x'*co, y * si) + origin(1);
yN = bsxfun(@minus, y*co, x' * si) + origin(2);

f_xN = floor(xN);
c_xN = ceil(xN);
f_yN = floor(yN);
c_yN = ceil(yN);
r_xO = round(xO);
r_yO = round(yO);

match_O = r_yO' < sizeY & r_yO' > 2;
for i = 1:length(x)
    if r_xO(i) < sizeX  && r_xO(i) > 2
      match = and(match_O, ...
                          yN(i,:) < sizeY & xN(i,:) < sizeX & ...
                          yN(i,:) > 2 & xN(i,:) > 2)
      for j = 1:length(y)
        if match(j)
                %Bilineare Interpolation:
                xN1 = f_xN(i,j);   %x-Koord. des 1. Stuetzpunktes
                xN2 = c_xN(i,j);   %x-Koord. des 2. Stuetzpunktes
                yN1 = f_yN(i,j);   %y-Koord. des 1. Stuetzpunktes
                yN2 = c_yN(i,j);   %y-Koord. des 2. Stuetzpunktes

                Q = [R(yN1,xN1),R(yN1,xN2);R(yN2,xN1),R(yN2,xN2)];      %Matrix mit den Werten der Stuetzpunkte
                p = [(xN2-xN(i,j))/(xN2-xN1);(xN(i,j)-xN1)/(xN2-xN1)];   %Vektor mit Gewichtungsfunktionen fuer x-Richt.
                o = [(yN2-yN(i,j))/(yN2-yN1),(yN(i,j)-yN1)/(yN2-yN1)];   %Vektor mit Gewichtungsfunktionen fuer y-Richt.    

                H1(r_yO(j), r_xO(i)) = o*(Q*p); %Bilineare Interpolation in Matrixschreibweise
        end
    end
  end
end

Dann würde ich noch versuchen "o*Q*p" elementweise auszudrücken. Das Erstellen der kleinen temporären Vektoren benötigt einen unangemessen großen Overhead und der Aufruf einer BLAS-Funktion für so kleine Vektoren und Matrizen ist ebenfalls ineffizient.
Code:
a1 = xN2-xN(i,j);
a2 = xN(i,j)-xN1;
b1 = yN2-yN(i,j);
b2 = yN(i,j)-yN1;

H1(r_yO(j), r_xO(i)) = b1 * (R(yN1,xN1) * a1 + R(yN1,xN2) * a2) + ...
                                 b2 * (R(yN2,xN1) * a1 + R(yN2,xN2) * a2) / ...
                                 ((xN2-xN1) * (yN2-yN1));

Bitte ausgiebig testen, da ich das nur im Forum-Editor zusammengestückelt habe.

Meine Strategie ist also zunächstmal das De-Vektorisieren, also das genau Gegenteil von dem Gewünschten. Ich gehe aber davon aus, dass dies bereits schneller ist, da Matlab Schleifen sehr effizient bearbeiten kann. Wieviel bringt dies?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Thomas K
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 15.04.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.08.2012, 15:53     Titel:
  Antworten mit Zitat      
Hallo Jan,

nocheinmal recht herzlichen Dank an dieser Stelle für deine Hilfe! Ich habe deinen Code jetzt ausprobiert, musste dabei ein paar Sachen ändern: Erstens, für unser Problem eigentlich unwesentlich, habe ich zwei Einträge in der Matrix Q (bzw. dann auch in der ausgeschriebenen Form) vertauscht. Zweitens: Danke für den Hinweis, wenn xN(i,j) (oder yN(i,j)) ein Integer ist sind ceil und floor gleich, d.h. aber das der Punkt für den interpoliert werden soll mit einem bekannten Datenpunkt zusammenfällt (es muss also gar nicht interpoliert werden, man kann den Punkt so nehmen wie er ist). Das hat in der ursprünglichen Version zu NaN-Einträgen geführt! Jetzt wird das einfach durch eine if-Abfrage verhindert.

Ich poste hier noch einmal verschiedene Versionen des Codes:
Code:

M = zeros(240,320);
for i=1:320
    for j=1:240
        r = 200+(800-200).*rand(1,1);
        M(j,i) = r;
    end
end
origin = [154 120];
[sizeX sizeY] = size(M');
x = -200:0.5:200;
y = -200:0.5:200;
xO = x+origin(1);
yO = y+origin(2);
lx = length(x);
ly = length(y);
theta = 0.1*pi;
co = cos(theta);
si = sin(theta);
xN = bsxfun(@plus,x'*co,y*si)+origin(1);
yN = bsxfun(@minus,y*co,x'*si)+origin(2);
tic
H1 = zeros(240,320);
for i=1:lx
    for j=1:ly
        if round(yO(j)) < sizeY && round(xO(i)) < sizeX && round(yO(j)) > 1 && round(xO(i)) > 1
            if yN(i,j) < sizeY && xN(i,j) < sizeX && yN(i,j) > 1 && xN(i,j) > 1
                %______________________________________________________
                %Bilineare Interpolation:
                xN1 = floor(xN(i,j));   %x-Koord. des 1. Stuetzpunktes
                xN2 = ceil(xN(i,j));   %x-Koord. des 2. Stuetzpunktes
                yN1 = floor(yN(i,j));   %y-Koord. des 1. Stuetzpunktes
                yN2 = ceil(yN(i,j));   %y-Koord. des 2. Stuetzpunktes
                if xN1 == xN2 || yN1 == yN2
                    H1(round(yO(j)),round(xO(i))) = M(yN1,xN1);
                else
                    Q = [M(yN1,xN1),M(yN2,xN1);M(yN1,xN2),M(yN2,xN2)];      %Matrix mit den Werten der Stuetzpunkte
                    p = [(xN2-xN(i,j))/(xN2-xN1);(xN(i,j)-xN1)/(xN2-xN1)];   %Vektor mit Gewichtungsfunktionen fuer x-Richt.
                    o = [(yN2-yN(i,j))/(yN2-yN1),(yN(i,j)-yN1)/(yN2-yN1)];   %Vektor mit Gewichtungsfunktionen fuer y-Richt.    
                    H1(round(yO(j)),round(xO(i))) = o*(Q*p);                 %Bilineare Interpolation in Matrixschreibweise
                end
            end
        end
    end
end
toc
xN = bsxfun(@plus,x'*co,y*si)+origin(1);
yN = bsxfun(@minus,y*co,x'*si)+origin(2);
tic
H = zeros(240,320);
r_xO = round(xO);
r_yO = round(yO);
f_xN = floor(xN);
c_xN = ceil(xN);
f_yN = floor(yN);
c_yN = ceil(yN);
 
for i=1:lx
    for j=1:ly
        if round(yO(j)) < sizeY && round(xO(i)) < sizeX && round(yO(j)) > 1 && round(xO(i)) > 1
            if yN(i,j) < sizeY && xN(i,j) < sizeX && yN(i,j) > 1 && xN(i,j) > 1
                xN1 = f_xN(i,j);   %x-Koord. des 1. Stuetzpunktes
                xN2 = c_xN(i,j);   %x-Koord. des 2. Stuetzpunktes
                yN1 = f_yN(i,j);   %y-Koord. des 1. Stuetzpunktes
                yN2 = c_yN(i,j);   %y-Koord. des 2. Stuetzpunktes
                if xN1 == xN2 || yN1 == yN2
                    H(round(yO(j)),round(xO(i))) = M(yN1,xN1);
                else
                    a1 = xN2-xN(i,j);
                    a2 = xN(i,j)-xN1;
                    b1 = yN2-yN(i,j);
                    b2 = yN(i,j)-yN1;
                    H(r_yO(j),r_xO(i)) = (b1*(M(yN1,xN1)*a1+M(yN2,xN1)*a2)+b2*(M(yN1,xN2)*a1+M(yN2,xN2)*a2))/((xN2-xN1)*(yN2-yN1));
                end
            end
        end
    end
end
toc
xN = bsxfun(@plus,x'*co,y*si)+origin(1);
yN = bsxfun(@minus,y*co,x'*si)+origin(2);
tic
H = zeros(240,320);
f_xN = floor(xN);
c_xN = ceil(xN);
f_yN = floor(yN);
c_yN = ceil(yN);
r_xO = round(xO);
r_yO = round(yO);
match_O = r_yO < sizeY & r_yO > 1;
for i = 1:lx
    if r_xO(i) < sizeX  && r_xO(i) > 1
        match = and(match_O,yN(i,:) < sizeY & xN(i,:) < sizeX & yN(i,:) > 1 & xN(i,:) > 1);
        for j = 1:ly
            if match(j)
                xN1 = f_xN(i,j);   %x-Koord. des 1. Stuetzpunktes
                xN2 = c_xN(i,j);   %x-Koord. des 2. Stuetzpunktes
                yN1 = f_yN(i,j);   %y-Koord. des 1. Stuetzpunktes
                yN2 = c_yN(i,j);   %y-Koord. des 2. Stuetzpunktes
                if xN1 == xN2 || yN1 == yN2
                    H(round(yO(j)),round(xO(i))) = M(yN1,xN1);
                else
                    a1 = xN2-xN(i,j);
                    a2 = xN(i,j)-xN1;
                    b1 = yN2-yN(i,j);
                    b2 = yN(i,j)-yN1;
                    H(r_yO(j),r_xO(i)) = (b1*(M(yN1,xN1)*a1+M(yN2,xN1)*a2)+b2*(M(yN1,xN2)*a1+M(yN2,xN2)*a2))/((xN2-xN1)*(yN2-yN1));
                end
            end
        end
    end
end
toc
 


Die erste Version benötigt bei mir ca. 2.68 s, die zweite ist 25 mal schneller und die dritte ist sogar 29 mal schneller als die erste Version (mit der oben im Code erstellten Matrix getestet).

Interessant ist, dass hier De-Vektorisieren der richtige Weg ist. Kannst du vielleicht ein paar Richtlinien nennen, wann Vektorisieren einer Schleife vorzuziehen ist, bzw. wann Vektorisieren einen zu hohen Datenverkehr oder Speicherkapazität erfordert?

Vielen Dank und schöne Grüße,
Thomas.
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.08.2012, 17:58     Titel:
  Antworten mit Zitat      
Ich gebe mal hier den Hinweis, dass Code, der länger als eine Bildschirmseite ist, dringend (!) überarbeitet werden sollte, denn das kann niemand mehr nach 2 Jahren lesen bzw. verstehen. Vor allem können Kommentare helfen und ich rate ganz dringend dazu, dass man das einmal inhaltlich strukturiert
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 28.08.2012, 22:23     Titel:
  Antworten mit Zitat      
Hallo flashpixx,

Während ich ansonsten jeden Sinnabschnitt mit einem Kommentar versehe und mit Leerzeilen abtrenne, find ich hier im Forum oft einen möglichst mageren Code sinnvoll. Ansonsten muss ich so viel scrollen.
Deshalb hatte ich mir auch die freiheit genommen, Kommentare aus Thomas' Orginalcode zu entfernen, um das eigentliche Problem möglichst kompakt behandeln zu können.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.08.2012, 23:05     Titel:
  Antworten mit Zitat      
@Jan: Dein Code ist überschaubar, ich habe mich auf den Code im vorhergehenden Post von Thomas bezogen. Der Code von Thomas in der Forendarstellung ist mehr als eine Bildschirmseite bei Full HD Auflösung und da fehlen noch Kommentare usw
Es sind bei mir 2 B
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.