next up previous contents
Nächste Seite: 3D-Visualisierung Aufwärts: report Vorherige Seite: Offline-Algorithmen zur Objektsegmentierung   Inhalt

Unterabschnitte


Programminterna

Dieses Kapitel stellt den internen Ablauf der Scanner-Applikation näher vor: die parallele Architektur, die Klassenhierarchie sowie das JAVA-Interface zur benutzerfreundlichen Bedienung des Programmes.


Ablauf-Skizze

Das Programm verläuft in folgenden Schritten:

Zu Beginn werden für den weiteren Programmablauf relevante Einstellungen aus der Konfigurationsdatei scanner.cfg gelesen. Diese Parameter lassen sich grob in zwei Gruppen unterteilen:

Die nächsten Schritte dienen der Vorbereitung der Parallelisierung des Programmes (siehe dazu auch Abbildung 5.1): es werden zwei Pipes geöffnet, die die Kommunikation zwischen den parallelen Prozessen gewährleisten. Über die erste Pipe werden während eines 3D-Scans die laufenden Daten geschickt, so daß die Scannpunkte online angezeigt werden können. Der Benutzer kann somit den Scan online auf dem Bildschirm verfolgen. Das Anzeigeprogramm 2show (näher beschrieben in Abschnitt 6), welches diese Daten im Empfang nimmt, wird daraufhin mittels fork als paralleler Prozeß gestartet.

Die zweite Pipe dient der Kommunikation zwischen dem Hauptprozeß, der die Daten verarbeitet (siehe unten), und dem Kindprozeß, der die Daten liefert. Haupt- und Kindprozeß werden daraufhin gestartet, sobald die Pipe bereitsteht. Per Kommandozeilenparameter kann dem Programm mitgeteilt werden, aus welcher Quelle die Daten stammen sollen (intern wird dazu lediglich ein anderer Kindprozeß geforkt):

  1. Bei der neuen Aufnahme eines 3D-Scans ist es Aufgabe des entsprechenden Kindprozesses, die Daten, die der Scanner liefert, von der seriellen Schnittstelle abzugreifen und sie an den Hauptprozeß weiterzuleiten sowie gleichzeitig in eine Abfolge von Dateien abzuspeichern. Damit es es nachfolgend möglich, einen 3D-Scan zu simulieren, also auch ohne laufenden Scanner durchzuführen.

    Ferner muß der Motor gesteuert werden, der den Scanner um seine horizontale Achse dreht, und es muß die Kamera ausgelöst werden, deren Bilder später als Quellen der Texturen in dem Anzeigeprogramm dienen. Schließlich hat der Prozeß dafür Sorge zu tragen, ,,Ausrutscher`` zu eliminieren, indem er bei einem Scan die Anzahl der Punkte, die eindeutig als Meßfehler klassifizierbar sind, mitzählt, korrigiert bzw., falls dies nicht mehr möglich ist, diesen Scan wiederholt.

  2. Die zweite Möglichkeit des Aufrufes benutzt die bei einem früheren 3D-Scan gespeicherten Daten-Dateien, d.h. dieser Kindprozeß muß lediglich die Dateien einlesen und sie an den Hauptprozeß senden.

Der Hauptprozeß übernimmt die Verarbeitung der Daten. Dies sind im Einzelnen:

  1. Die von dem Kindprozeß ankommenden Daten werden im ersten Schritt scanweise online verarbeitet:
  2. Die nachfolgenden Aufgaben müssen offline durchgeführt werden, da im folgenden alle Datensätze benötigt werden:

Abbildung: Überblick über die parallele Architektur der Scanner-Applikation
\includegraphics {overview}

Abbildung 5.2: Klassenhierarchie
\includegraphics {classes}

Klassenhierarchie

Einen Überblick über die Klassenhierarchie liefert Abbildung 5.2.


Benutzer-Interface

An dieser Stelle soll das Benutzer-Interface kurz dargestellt werden. Zwar ist es möglich, sowohl das OpenGL- als auch das Scanner-Programm von der Kommandozeile aus zu starten. Die vom Benutzer modifizierbaren Parameter werden dann - wie bereits in Abschnitt 5.1 beschrieben - aus der Konfigurationsdatei scanner.cfg gelesen.

Eine sehr viel komfortablere Möglichkeit der Modifikation besagter Parameter und Kontrolle der externen Programme bietet jedoch das graphische Benutzerinterface, geschrieben in der Sprache JAVA.

Abbildung 5.3: JAVA-Benutzerinterface: Hauptfenster
\includegraphics {java1}

Hauptfenster

Das Hauptfenster (vergleiche Abbildung 5.3) ist gegliedert in drei Bereiche, abgeschlossen durch die Buttons Scan, Display und Motor.

Innerhalb des Scan-Bereiches lassen sich all jene Parameter einstellen, welche den eigentliche Scan-Vorgang beeinflussen. Die Betätigung des Scan-Buttons startet die Scanner-Applikation unter den spezifizierten Parametern.

Der Display-Bereich beinhaltet dementsprechend Parameter, welche die Anzeige beeinflussen. Desweiteren existiert ein Textfenster, in welchem der textuelle Output der Scanner-Applikation ausgegeben wird (siehe auch Abbildung 5.4). Dies sind Informationen, welche die einzelnen Algorithmen als Statusmeldungen dem Benutzer übermitteln, wie beispielsweise die Anzahl erkannter Linien pro Scan. Diese Statusmeldungen werden bei manuellem Start der Scanner-Applikation auf der Textkonsole ausgegeben. Der Display-Button startet das Anzeigeprogramm 2show, welches den zuletzt durchgeführten Scan visualisiert.

Die Betätigung des Motor-Buttons gibt einen Schieberegler frei, mit dessen Hilfe sich die Scanner-Hardware manuell direkt um den eingestellten Winkel drehen läßt.

Parameter

Abbildung 5.4: JAVA-Benutzerinterface: Konfigurationsfenster
\includegraphics {java2}


Menüstruktur

File
Es stehen folgende Untermenüs zur Verfügung:
Load
Lädt eine zuvor gespeicherte Konfigurationsdatei.
Save as...
Die aktuellen Einstellungen der Oberfläche lassen sich unter einem anderen Namen abspeichern.
Save
Sofern zuvor eine Konfigurationsdatei geladen oder der aktuelle Zustand unter einem anderen Namen gespeichert worden ist, so lassen sich mit diesem Menüpunkt Modifikationen speichern.
Exit
Beendet die Oberfläche.
Options
Es stehen folgende Untermenüs zur Verfügung:
Colors
Die Farben der Oberfläche können neben den Standard-Einstellungen noch in einen Präsentationsmodus gesetzt werden, der sich insbesondere für die Präsentation mittels eines Beamers eignet, sowie in einen Modus, der die Farbe der Scanner-Hardware nachahmt.
Configuration
Hier öffnet sich ein weiteres Fenster (vergleiche Abbildung 5.4), in dem die bereits beschriebenen Konfigurations-Parameter einstellbar sind.
Demonstration
Der Benutzer kann hier zwischen 4 verschiedenen Demos auswählen (siehe Abbildung 5.5): Bei Betätigung eines der vier Demo-Buttons wird die entsprechende Konfigurationsdatei samt den zugehörigen Datendateien geladen. Der Input ist fest auf ,,File``, der Output auf ,,normal`` gesetzt. Desweiteren wird der Scanvorgang automatisch gestartet.

Sobald das Demonstrationsfenster geschlossen ist, werden die vor dem Demobetrieb geltenden Einstellungen wieder hergestellt, die Applikation kann wie gewohnt bedient werden.

Help
Zu guter letzt führt dieser Menüpunkt zu einer kurzen Hilfe-Einblendung.

Implementationsdetails

Im folgenden sei kurz auf die Implementation des Aufrufes der Scanner-Applikation von dem JAVA-Benutzerinterface aus eingegangen.

Das externe Programm scanner wird mittels Runtime.getRuntime().exec() gestartet. Dabei ist es möglich, die Ausgaben des aufgerufenen Programmes auf den Standardausgabestream abzufangen und als InputStream weiterzuverarbeiten: wie in Abbildung 5.5 zu sehen, wird die Ausgabe in das Textfenster der Applikation geschrieben. Aus Performancegründen wird dabei über den Inputstream noch ein BufferedReader gelegt.

Damit die Ausgabe schon während der Laufzeit des aufgerufenen Programmes angezeigt wird - und nicht erst nach Verlassen der Funktion, wenn die Bildschirmanzeige neu gezeichnet wird - war es notwendig, diese Funktion als eigenständigen Thread zu realisieren.

Abbildung 5.5: JAVA-Benutzerinterface: Demonstrationssfenster
\scalebox {.8}{\includegraphics{java3}}


class startScanner extends Thread {
   Frame father;
   startScanner(Frame f) { father = f; }

   public void run() {
      Process scanner;
      try {
         // save the current values
         father.writeValues(new File(System.getProperty(üser.dir") +
                                     "/bin/scanner.cfg"),true);
         // compose command string
         String exec = "bin/scanner " + 
            ("File".equals(father.InputComboBox.getSelectedItem()) ? 
            "f" : ("dump only".equals(father.OutputComboBox.
	          getSelectedItem()) ? "d" : ß"));

         // start the scanner
         scanner = Runtime.getRuntime().exec(exec);

         // catch scanner output via 'getInputStream()'
         BufferedReader inStrm = new BufferedReader(
                                 new InputStreamReader(
                                     scanner.getInputStream()));
         String c;
         while ( (c = inStrm.readLine()) != null) {
            father.jTextArea1.append(c + "\n");
         };
      } catch (Exception e) { 
         System.err.println("Error: " + e); 
         e.printStackTrace();
      }
   }
}


next up previous contents
Nächste Seite: 3D-Visualisierung Aufwärts: report Vorherige Seite: Offline-Algorithmen zur Objektsegmentierung   Inhalt