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

Tic Toc- Funktion liefert seltsame Werte

 

Gepps

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.11.2012, 17:16     Titel: Tic Toc- Funktion liefert seltsame Werte
  Antworten mit Zitat      
Hallo alle Zusammen

Ich hab ein keines Verständnissproblem mit der Tic-Toc Funktion von Matlab.

Ich bin gerade dabei für eine Bildverarbeitungsaufgabe einen eigenen Objekterkennungsalgorythmus zu programmieren. (Mir ist klar dass es da natürlich eine eigene FUnktin gibt ...)

Der wichtige Teil dabei sieht so aus:

Code:

tic % starte Messung 1
for zeile=1:zeilen
   
    for spalte=1:spalten
       
        if (bw(zeile,spalte)==1) && (bw2(zeile, spalte)~=1)   % Wenn der Wert 1 ist...
                tic % start Messung 2
                [Konturzeile, Konturspalte, Areazeile, Areaspalte, objektanzahl, bw2]=konturverfolgung3(bw, bw2, R, zeile, spalte, objektanzahl);
               
                % Ergebnis Speichern
                Konturzeilen{objektanzahl}=Konturzeile;
                Konturspalten{objektanzahl}=Konturspalte;
                Areazeilen{objektanzahl}=Areazeile;
                Areaspalten{objektanzahl}=Areaspalte;
                A_z=[A_z Areazeile];
                A_s=[A_s Areaspalte];
                toc % ende Messung 2
        end      
    end
   
end
toc % Ende Messung 1
 


Die Zeitmessungen mit Tic-Toc habe ich nicht (wie im Code gezeigt) gleichzeit verwendet sondern immer einzeln.

Wenn ich den Inhalt in der if-Funktion auskommentiere und die Messung 1 ausgeben lasse, bekomme ich einen Messwert von 0,026 Sekunden. (Das ist scheinbar die Zeit die Matlab benötigt um für Jeden Punkt im Bild (bw) den Pixelwert mit der if-Funkion zu überprüfen). (In der If- FUnktion wird jedoch keine Operation durchgeführt)

Wenn ich nun den If-Schleifeninhalt wieder einblende und die Messung 2 beobachte, erhalte ich 10 Messwerte (Da die if-Funktion 10mal erfüllt wird) mit 0,001 sekunden. Somit wären das in Summe rund 0,01sekunden.

Für mich wäre es nun logisch wenn die Messung 1 mit eingeblendeter if-Struktur 0,036 sekunden benötigen würde.
Jedoch dauert dass dann unglaubliche 2,15 sekunden.

Wo ist denn hier mein Denkfehler?


dmjr
Forum-Century

Forum-Century


Beiträge: 199
Anmeldedatum: 02.10.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.11.2012, 17:24     Titel:
  Antworten mit Zitat      
Den Denkfehler kann ich dir nicht erklären, dazu müsste ich wissen was konturverfolgung3 macht. Schau dir doch mal "profile" an, damit siehst du in welcher Zeile der Code wieviel Zeit benötigt.
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: 25.11.2012, 22:52     Titel: Re: Tic Toc- Funktion liefert seltsame Werte
  Antworten mit Zitat      
Hallo Gepps,

Manchmal ist Matlabs JIT sehr schlau und optimiert die inneren Schleifenaufrufe weg, wenn es erkennt, dass die Werte nirgendwo benutzt werden. Deshalb ist eine Laufzeitmessung mit einer (fast) leeren Schleife nicht unbedingt nachvollziehbar.

Aber ich vermute es liegt an etwas anderem:
Code:
A_s=[A_s Areaspalte]

Hier, und bei den anderen Variablen wahrscheinlich auch, wird der Output in jeder Iteration vergrößert. Dies ist als "fehlende Pre-allocation" bekannt und es ollten entsprechende MLint-Warnungen im Editor erscheinen - sind da welche?

Wenn ein Array iterativ vergrößert wird, bis es n Elemente enthält, muss Matlab nicht n*8 Bytes allocieren (ein DOUBLE hat 8 Byte), sondern SUM(1:n)*8. Bei n==10 sollte das allerdings nicht zu 2.15 Sekunden Laufzeit führen, denn auch SUM(1:10) ist nur 55. Aber SUM(1:1000) ist schon 500500.

Im Endeffekt ist also dmjr's Empfehlung des Profilers wohl am besten. Allerdings schaltet der Profiler leider die JIT ab. Es kann deshalb sein, dass eine sehr effizient ausgeführte Schleife im Profiler plötzlich lahm aussieht.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Geppsl

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 26.11.2012, 19:43     Titel:
  Antworten mit Zitat      
Danke für die schnellen Antworten.

Ich bin heute leider ein bisschen Zeitlich eingespannt aber konnte mal einen kurzen Blick auf den Profiler werfen. Ist ziemlich nützlich. Morgen werde ich mir den Code in Ruhe nochmal anschauen können um die Schwachstelle zu suchen.

Bezüglich der Sache mit dem interativen Vergrößern:
Ich hab die Warnung eh auch schon von Matlab bemerkt. Jedoch wüsste ich nicht wie man es anders programmieren könnte.
Ich hab gelesen, dass es schneller wäre zuerst eine Varibale mit Nullen zu initiallisieren und anschließend die Werte zu überschreiben. Wie wird dass jedoch gehandhabt wenn ich nicht weiß, wie offt meine Schleife durchlaufen wird? (Ist nämlich von der Objektanzahl im Bild abhängig)
 
Jan S
Moderator

Moderator


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

Wenn man eine akzeptabele Obergrenze kennt, ist es im Allgemeinen billiger dies zu verwenden und die ungenutzten Elemente hinterher zu verwerfen. Das Allozieren von 1000 Elementen ist billiger als 45 Elemente iterative zu vergrößern.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Gepps

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.11.2012, 00:06     Titel:
  Antworten mit Zitat      
Hallo Leute

Ich bin langsam ziemlich am verzweifeln.
Ich bin nun noch auf eine Möglichkeit gekommen den Code deutlich zu vereinfachen. (Ich erspare mir nun einige Hilfsvariablen und unnötige if-Abfragen)
Weiters hab ich alle vorkommenden interaitven Variablen-Vergrößerungen durch eine Vorinitialisierung ersetzt.

Der wichtige Teil des Codes sieht nun so aus:

Code:

...
Konturzeilen=cell(1,10);
Konturspalten=cell(1,10);
Areazeilen=cell(1,10);
Areaspalten=cell(1,10);

for zeile=1:zeilen
    for spalte=1:spalten
        if (bw(zeile,spalte)==1)    % Wenn der Wert 1 ist...        
           if (bw2(zeile,spalte)==0)      
               tic
               [Konturzeile, Konturspalte, Areazeile, Areaspalte, objektanzahl, bw2]=konturverfolgung3(bw, bw2, R, zeile, spalte, objektanzahl);
               
                % Ergebnis Speichern
                Konturzeilen{objektanzahl}=Konturzeile;
                Konturspalten{objektanzahl}=Konturspalte;
                Areazeilen{objektanzahl}=Areazeile;
                Areaspalten{objektanzahl}=Areaspalte;
                toc
           end  
        end      
    end
end


%% Flächenschwerpunkt
S=zeros(2,10);
for k=1:objektanzahl
   S(1,k)=sum(Konturspalten{k})/numel(Konturspalten{k});
   S(2,k)=sum(Konturzeilen{k})/numel(Konturzeilen{k});
end
 


(Vor diesem Code werden wird lediglich ein Testbild geladen und ein paar Werte initialisiert)

Sowohl Tic Toc als auch der Profiler zeigen mir, dass meine Unterfunktion (Konturverfolgung3) nicht die Engstelle ist. (Siehe Anhang)

Die Größte Zeitverzögerung liegt an dem Children "Self time"
Was bedeutet das?

Gruß Geppsl

Zeitliste.PNG
 Beschreibung:

Download
 Dateiname:  Zeitliste.PNG
 Dateigröße:  41.9 KB
 Heruntergeladen:  623 mal
Zeitliste.PNG
 Beschreibung:

Download
 Dateiname:  Zeitliste.PNG
 Dateigröße:  41.9 KB
 Heruntergeladen:  630 mal
 
dmjr
Forum-Century

Forum-Century


Beiträge: 199
Anmeldedatum: 02.10.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.11.2012, 00:54     Titel:
  Antworten mit Zitat      
Wie oft ist "if (bw(zeile,spalte)==1)" überhaupt wahr?

Ansonsten ist der Haken an dem Code dass die Funktion konturverfolgung3 bw2 zurückgibt, dadurch lässt sich vorab nicht bestimmen für welche Werte die Schleife durchlaufen wird (was Optimierungspotential bieten würde).
Private Nachricht senden Benutzer-Profile anzeigen
 
Geppsl

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.11.2012, 00:30     Titel:
  Antworten mit Zitat      
Hallo dmjr

Die erste If- Abfrage wird bei jedem Pixel erfüllt auf dem der Pixelwert 1 ist (Ich schätze 100 - 200 mal)
die zweite if-Abfrage wird pro Objekt nur einmal erfüllt. In meinem Fall sind es 10 Objekte.

Ich hab nun nochmals meinen Code noch weiter reduziert. Anstelle des bw2 Bildes arbeite ich nun nur noch mit dem bw-Bild.

Code:

Konturzeilen=cell(1,10);
Konturspalten=cell(1,10);

for zeile=1:zeilen
    for spalte=1:spalten
        if (bw(zeile,spalte)==1)    % Wenn der Wert 1 ist...        
               [bw, Konturzeile, Konturspalte, objektanzahl] = konturverfolgung4(bw, R, zeile, spalte, objektanzahl);
                % Ergebnis Speichern
                Konturzeilen{objektanzahl}=Konturzeile;
                Konturspalten{objektanzahl}=Konturspalte;
        end      
    end
end
 


Der Code macht nichts anderes als im Bild bw die Pixel abzusuchen bis er auf das erste Pixel stößt indem ein 1er steht (somit ein Objekt detektiert wird). Sobald er das gefunden hat verfolgt meine Unterfunktion Konturverfolgung4 die Kontur und löscht die entsprechenden Pixel aus dem bw. (Ist notwendig, da sonst ein Objekt mehrmals detektiert wird).

Der Code benötigt noch immer über 3 Sekunden.
Ich wüsste nicht wie ich um das Überschreiben von bw herum kommen könnte.

Ich hab mal versucht den Inhalt der If-Abfrage auszukommentieren und ohne Unterfunktion die gefundenen Pixel im BW einfach zu überschreiben.

Code:

Konturzeilen=cell(1,10);
Konturspalten=cell(1,10);

for zeile=1:zeilen
    for spalte=1:spalten
        if (bw(zeile,spalte)==1)    % Wenn der Wert 1 ist...        
              bw(zeile,spalte)=0;
        end      
    end
end
 


Verblüffender weise schafft Matlab das in unglaublichen 0,2 Sekunden. Ich versteh den Unterschied nicht ?
 
Jan S
Moderator

Moderator


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

Es ist effizienter ein Array in Splatenrichtung zu bearbeiten. Tausche also mal die FOR-Schleifen gegeneinander aus:
Code:

Konturzeilen=cell(1,10);
Konturspalten=cell(1,10);

for spalte=1:spalten
    for zeile=1:zeilen
       ...


Aus dem Code ohne IF macht Matlab's JIT wahrscheinlich intern etwas wie:
Code:

temp = bw(1:zeilen, 1:spalten);
index = (temp == 1);
temp(index) = 0;
bw(1:zeilen, 1:spalten) = temp;

Das sollte nun viel schneller laufen als 0.2 sec. Verblüffend ist die Geschwindigkeit also nicht wirklich. Dass der gesamte Code viel länger benötigt, liegt wohl daran dass "konturverfolgung4" viel Zeit benötigt. Deshalb ist es sinnvoll, sich bei der Optimierung des Codes auf diese funktion zu konzentrieren.
Regel: Optimier immer nur ein einziges Bottleneck.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Geppsl

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.11.2012, 18:24     Titel:
  Antworten mit Zitat      
Hallo Jan

Das austauschen der Schleifen ändert leider auch nichts.

Laut Tic Toc und Profiler benötigt die Konturverfolgung4 rund 0,001s - 0,003s (Je nach Objektgröße). Da die If- Schleife 10 Mal erfüllt wird sind wir da bei ca 0,03 Sekunden. Somit kann es daran nicht liegen.

Für mich hat es den Eindruck als hätte Matlab irgend eine Art von Aktualisierungsproblem (Dadurch dass bw bei jeder if- Erfüllung geändert wird)

Hat jemand vielleicht eine Ahnung wie Matlab dieses Problem mit dem fertigen Befehl "regionprops(bw, {'Centroid'})" löst? .... Es muss ja scheinbar einen schnelleren Ansatz dafür geben das Bild abzusuchen ....

(Ich hab den Algorithmus so aufgebaut wie er in nahezu jedem Literaturbuch beschrieben ist. (Eine gute Erklärung findet man auch unter :
http://www.fbmn.fh-darmstadt.de/hom.....ng/konturcode/kontur.html
 
Geppsl

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.11.2012, 18:29     Titel:
  Antworten mit Zitat      
Der Code ist natürlich auch kein Geheimnis:

Code:


function [bw, Konturzeile, Konturspalte, objektanzahl] = konturverfolgung4(bw, R, zeile, spalte, objektanzahl)
   
%% Kontur verfolgen
objektanzahl=objektanzahl+1;
Startwert=[zeile,spalte]; % Startwert definieren

Konturzeile=zeros(1,100); % Initiallisierung
Konturspalte=zeros(1,100);

Konturzeile(1)=zeile;
Konturspalte(1)=spalte;
Neuwert=[zeile,spalte];
vector=0;  %Startrichtung nach unten
vk=1;   %Korrigierter Vektor
n=2;

while ((Startwert(1) ~= Neuwert(1)) || (Startwert(2) ~= Neuwert(2)) || (n<=3)) % Solange der Neuwert nicht der Startwert ist ...
    Wert1=bw((Neuwert(1)+R(1,1,vk)),(Neuwert(2)+R(2,1,vk)));
    Wert2=bw((Neuwert(1)+R(1,2,vk)),(Neuwert(2)+R(2,2,vk)));
    Wert3=bw((Neuwert(1)+R(1,3,vk)),(Neuwert(2)+R(2,3,vk)));

    if Wert1==1
       Konturzeile(n)=Neuwert(1)+R(1,1,vk); %In Kontur speichern
       Konturspalte(n)=Neuwert(2)+R(2,1,vk);
       vector=mod(vector-2,8);        %Tichtungsvektor um 2 reduzieren
       Neuwert=[Konturzeile(n),Konturspalte(n)];
       n=n+1;
    else
       if (Wert2==1)
           Konturzeile(n)=Neuwert(1)+R(1,2,vk); %In Kontur speichern
           Konturspalte(n)=Neuwert(2)+R(2,2,vk);
           Neuwert=[Konturzeile(n),Konturspalte(n)];
           n=n+1;
       else
           if (Wert3==1)
               Konturzeile(n)=Neuwert(1)+R(1,3,vk); %In Kontur speichern
               Konturspalte(n)=Neuwert(2)+R(2,3,vk);
               Neuwert=[Konturzeile(n),Konturspalte(n)];
               n=n+1;
           else
               vector=mod(vector+2,8); %Tichtungsvektor um 2 reduzieren
           end
       end
    end
    vk=vector+1;
end  

%Löschen des letzten Eintrages
Konturspalte(numel(Konturspalte))=[];
Konturzeile(numel(Konturzeile))=[];


Konturzeile(Konturzeile==0)=[]; % überflüssige Nullen löschen
Konturspalte(Konturspalte==0)=[];

%% Detektion der Fläche

n=1; % Laufvariable für die Area-Werte
for k= min(Konturzeile) : max(Konturzeile)  % Zeilenweise Kontur Prüfen
    fuellstart=find(Konturzeile==k);        % Suche Konturpunkte mit aktuellen Zeilenwert              
    for i= min(Konturspalte(fuellstart)) : max(Konturspalte(fuellstart)) % Zwischenwerte ausfüllen und in Area abspeichern
        bw(k,i)=0;
        n=n+1;
    end
end

 
 
Neues Thema eröffnen Neue Antwort erstellen



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.