Simulationsumgebung für die Objekt- und Spurerkennung
Autoren: Hagen Heuer, Tim Kruse, Marius Köhler, Stefan Arndt
Betreuer: Prof. Schneider
Einleitung
Autoren: Hagen Heuer, Tim Kruse
Um die Hauptnutzungszeit der Kamera für Funktionstests zu verringern, soll eine Simulationsumgebung in Visual Studio programmiert werden. Ziel ist es hierbei die Weiterverarbeitung der Bilder, welche die Kamera bereitstellt, zu implementieren und zu testen.
Es sollen hierbei folgende Funktionen der Bildverarbeitung implementiert und getestet werden.
- Erstellung eines Binärbildes, um die Rechenleistung zu optimieren
- Festlegen der Region of Interest, um die Rechenleistung weiter zu optimieren
- Filterung von Reflektionen durch den Einfall von Licht
- Transformation des Kamerabildes in Vogelperspektive, um die Objekt- und Spurerkennung zu vereinfachen
Anforderungen
Autoren: Hagen Heuer, Tim Kruse
Auf Basis der gestellten Anforderungen aus dem Lastenheft konnten folgende Pflichten für die Simulationsumgebung abgeleitet werden.
-
Abb. 1: Pflichtenheft
Um die Zusammenarbeit beider Teams zu vereinfachen wurden weitere Anforderungen an die Bildvorverarbeitung gestellt. Diese werden nachfolgend ausgelistet und erörtert.
Binärbild
Zur vereinfachten Objekt und Spurerkennung sollte das RGB-Farbbild in ein Binärbild gewandelt werden. Dieses stellt die Farben lediglich in Schwarz und Weiß dar. Somit sollen die Fahrbahnlinien in Weiß dargestellt werden und die Umgebung in Schwarz.
Reflektionen filtern
Zudem sollen Reflektionen nach Möglichkeit heraus gefiltert werden, da diese sonst auf Grund ihrer Helligkeit weiß dargestellt werden und somit die Objekt- und Spurerkennung beeinträchtigen können. Im Zweifelsfalls soll die Fahrspur unterbrochen werden, um Reflektionen sicher zu filtern.
Region of Interest anpassen
Um die benötigte Rechenleistung zu verringern, sollte zudem der gezeigte Bildausschnitt angepasst werden. Die Bedeutet, dass das Fahrzeug nicht mehr zu sehen sein soll und die Sicht in die Ferne eingeschränkt werden soll.
Transformartion in Vogelperspektive
Desweiteren sollen die einzelnen Bilder in Vogelperspektive transformiert werden und möglichst ohne Verzerrungen dargestellt werden.
Konzeptentwicklung
Autoren: Hagen Heuer, Tim Kruse
Die Programmierung der Simulationsumgebung erfolgt in Visual Studio 2019, da die bisherige Implementierung der Kamera ebenfalls in Visual Studio erfolgte. Zudem stellen die Bibliotheken von OpenCV Funktionen bereit, welche die Simulation der VRmagic Kamera vereinfachen.
Als Grundlage für die Simulation der VRmagic Kamera dient ein Video, welches die Strecke inklusive der Stopp-Kreuzungen beinhaltet. Zudem Berücksichtigt das Fahrzeug in dem Video die Anforderungen an das Verhalten an Stopp-Kreuzungen, welches der Spurerkennung zu gute kommt.
Da zwei Teams an der Simulationsumgebung arbeiten bietet es sich an, dass Programm modular aufzubauen. Die Programmstruktur ist nachfolgend erläutert.
- main.cpp
- Hauptprogramm der Simulationsumgebung
- Implementierung der Konsolenanwendung
- Frame_lesen.cpp und Frame_lesen.h
- Einlesen des Videos
- Nächsten Frame aus dem Video extrahieren
- Bildtransformation.cpp und Bildtransformation.h
- Anpassen der Region of Interest
- Graustufenbild erstellen
- Binärbild erstellen
- Reflektionen filtern
- Transformation in Vogelperspektive
- Frame_ausgeben.cpp und Frame_ausgeben.h
- Ausgabefenster öffnen
- Video ausgeben
- ConfigLesenSchreiben
- string in eine .ini Datei schreiben
- string aus einer .ini Datei lesen
Programmablaufpläne für die Simulationsumgebung
Autoren: Hagen Heuer, Tim Kruse
Um die Programmierung der Simulationsumgebung zu vereinfachen, wurden ein Programmablaufplan für das Hauptprogramm entwickelt. Zudem wurden Programmablaufpläne für die benötigten Funktionen entworfen. Diese werden nachfolgend erläutert.
Programmablaufplan für das Hauptprogramm
-
Abb. 2: Hauptprogramm Teil 1
-
Abb. 3: Hauptprogramm Teil 2
Im Hauptprogramm werden zunächst alle Variablen initialisiert. Anschließend folgt die erste while-Schleife. In der Konsole wird nun ein Text ausgegeben und auf die Eingabe durch den Benutzer gewartet.
Wurde die Simulation ausgewählt so folgt eine weitere Ausgabe in der Konsole und man wartet auf die Eingabe durch den Benutzer. Hat dieser nun Simulation starten ausgewählt, so wird zunächst die Funktion FA_InitVideo aufgerufen. Anschließend folgt einer weitere while-Schleife, in der der jeweils nächste Frame geladen und transformiert wird. Hierfür wird zunächst die Funktion FL_GetFrame aufgerufen und abgefragt, ob ein Frame vorhanden ist. Anschließend wird die Funktion BTF_imgTranf aufgerufen. Für den Fall das keine Taste für den Abbruch gedrückt wurde, wird der nächste Frame geladen. Falls doch abgebrochen wird oder aber kein Frame vorhanden ist, werden alle Ausgabefenster geschlossen und der Inhalt der Konsole gelöscht.
Wurde innerhalb der Simulation stattdessen Dateipfad ändern ausgewählt, so folgt eine weitere Ausgabe in der Konsole. Außerdem wird auf eine Eingabe in der Konsole gewartet. Anschließend wird die Funktion CLS_Stringschreiben aufgerufen um den Dateipfad zu sichern. Nun wird der Inhalt der Konsole gelöscht. Wurde Zurück ausgewählt, so wird ebenfalls der Inhalt der Konsole gelöscht. Falls die Eingabe ungültig war so wird dies in der Konsole ausgeben und anschließend der Inhalt gelöscht.
Statt der Auswahl der Simulation kann auch die extrinsische oder intrinsische Kalibrierung ausgewählt werden. Hierbei wird lediglich etwas in der Konsole ausgegeben.
Bei ungültiger Eingabe erfolgt wieder eine Textausgabe und der Inhalt wird gelöscht.
Falls das Programm beendet werden soll wird die Eingabe erneut abgefragt. Fall auch hier ja ausgewählt wird, das Programm beendet. Andernfalls erfolgt eine Textausgabe und der Inhalt wird gelöscht, oder es wird lediglich der Inhalt gelöscht.
Im Anschluss an das Inhalt löschen erfolgt ein Sprung an das Ende der while-Schleife.
Programmablaufpläne für die Ausgabe
-
Abb. 4: FA_InitVideo
-
Abb. 5: FA_Ausgabe
In der Funktion FA_InitVideo werden die Ausgabefenster, welche bei Übergabe festgelegt wurden, geöffnet. In diesen Fenstern wird das später Video dargestellt. Die Funktion FA_Ausgabe gibt letztlich das Video in dem jeweiligen Ausgabefenster aus.
Programmablaufpläne für das Lesen
-
Abb. 6: load
-
Abb. 7: FL_GetFrame
In der Funktion load wird zunächst der Dateipfad mit Hilfe der Funktion CLS_StringLesen eingelesen. Anschließend wird das Video geladen. Für den Fall, dass das Einlesen nicht erfolgreich war, wird ein Text ausgegeben und die Transformation abgebrochen.
In der Funktion FL_GetFrame werden zunächst die Variablen initialisiert. Falls noch kein Video geladen wurde, wird zunächst die Funktion load aufgerufen. Anschließend wird der nächste Frame des Videos geladen und in eine Matrix geschrieben. Falls der Frame nicht geladen werden konnte, erfolgt eine Textausgabe und das Programm wird beendet.
Programmablaufpläne für die Bildtransformation
-
Abb. 8: BTF_ImgTransf
-
Abb. 9: regionOfInterest
-
Abb. 10: binarisierung
-
Abb. 11: imageTransformation
Die eigentliche Bildtransformation fällt im Gegensatz zu den anderen Modulen etwas größer aus.
Die Funktion BTF_ImgTransf wird aus dem Hauptprogramm aufgerufen und regelt die Transformation in Vogelperspektive. Zu Beginn wird abgefragt, ob ein RGB-Farbvideo ausgegeben werden soll. Falls ja erfolgt die Ausgabe des Videos. Anschließend wird die Funktion regionOfInterest aufgerufen, in der der Bildausschnitt angepasst wird. Anschließend wird die Funktion binarisierung aufgerufen, um ein Schwarz-Weiß Bild zu erhalten. Im letzen Schritt erfolgt die eigentliche Transformation in Vogelperspektive mit Hilfe der Funktion imageTransformation.
Mit Hilfe der Funktion regionOfInterest wir zunächst der Dargestellte Bereich des Bildes angepasst. Hierbei wird sowohl das Fahrzeug aus dem Bild geschnitten, sowie der obere Teil des Bildes verkleinert. Hierfür werden als erstes Variablen initialisiert. Anschließend wird das Bild zugeschnitten. Im letzten Schritt erfolgt die Abfrage, ob das Video ausgegeben werden soll, sowie der Funktionsaufruf FA_Ausgabe.
Mit der Funktion binarisierung wird aus dem RGB-Bild ein Binärbild erstellt. Dieses ist ein Schwarz-Weiß Bild. OpenCV bietet hierfür keine direkte Funktion an, weswegen zunächst ein Graustufenbild erstellt wird. Danach erfolgt die Abfrage, ob das Graustufenbild ausgegeben werden soll inklusive dem Funktionsaufruf FA_Ausgabe. Anschließend werden Parameter für die Binarisierung mit Hilfe der Funktionen CLS_DoubleLesen und CLS_IntLesen eingelesen. Nun kann aus dem Graustufenbild das eigentliche Binärbild erstellt werden. Auch hier folgt die Abfrage, ob das Video ausgegeben werden soll.
Im letzten Schritt wird das Binärbild mit der Funktion imageTransformation in die Vogelperspektive transformiert. Hierfür werden zunächst die Variablen initialisiert. Anschließend werden die Source- und Destination-Punkte festgelegt. Danach wird die Transformationsmatrix erstellt und im letzten Schritt die Transformation durchgeführt. Anschließend erfolgt wieder die Abfrage, ob das Video ausgegeben werden soll.
Die Funktion imageTransformation führt nun die Transformation des Binärbildes in Vogelperspektive durch. Hierfür werden zunächst Variablen initialisiert. Nun werden die Source und Destination Punkt festgelegt und die Transformationsmatrix erstellt. Nun wird die Transformation in Vogelperspektive durchgeführt. Abschließend erfolgt die Abfrage, ob das Video ausgegeben werden soll mit dem Funktionsaufruf FA_Ausgabe.
Programmablaufpläne um die ini-Datei lesen und zu schreiben
-
Abb. 12: Double schreiben
-
Abb. 13: Integer schreiben
-
Abb. 14: String schreiben
-
Abb. 15: Double lesen
-
Abb. 16: Integer lesen
-
Abb. 17: String lesen
Diese Sechs Programmablaufpläne dienen wie oben bereits beschrieben zum lesen und schreiben einer ini-Datei. Um in die ini-Datei schreiben zu können, muss zunächst die Information, welche gespeichert werden soll, in eine LPCSTR gewandelt werden. Anschließend kann dieser Wert gespeichert werden. Beim Lesen eines double Wertes aus der ini-Datei erhält man einen String welcher anschließend zu einem double konvertiert werden muss. Beim String lesen erhält man einen char, welcher für die weitere Verwendung in einen String formatiert wird. Nur beim lesen eines Integer ist keine Konvertierung nötig, da Integer direkt ausgelesen werden können.
Umsetzung und Ergebnis der Simulationsumgebung
Autoren: Hagen Heuer, Tim Kruse
Die Umsetzung der Simulationsumgebung erfolgte in Visual Studio 2019 Community. Für die Bild- und Videoverarbeitung wurde auf die Bibliotheken von OpenCV zurück gegriffen. Das Einbinden dieser Bibliothek ist in dem Artikel Installation von OpenCV in Visual Studio beschrieben.
Die Implementierung erfolgt wie oben beschrieben in einzelnen Modulen, welche mehrere Funktionen beinhalten. Bei der Programmierung musste darauf geachtet werden, dass kein using namespace cv verwendet wird. Dies sorgte häufiger für Probleme. Stattdessen muss die Implementierung wie in Abbildung 18 zu sehen erfolgen und der Vorsatz cv:: verwendet werden.
Das Ergebnis der Transformation ist in der Abbildung 13 zu sehen. Links ist das Original Video zu sehen und Rechts das Binärbild in Vogelperspektive. Außerdem lässt sich erkennen, dass das Fahrzeug im Binärbild nicht mehr zu sehen ist. Zudem wurde der Bildausschnitt oben verkleinert.
Umsetzung des Live-Modus
Der Live-Modus wurde in den Dateien Kamera.cpp und Kamera.h implementiert und richtet sich an der Arbeit des Vorsemesters. der Aufruf geschieht über Kamera::connect(); Kamera::init(); in der Main-Datei
Unit-Test
Autoren: Hagen Heuer, Tim Kruse
Im Folgenden sind Ergebnisse der Unit-Tests von den einzelnen Modulen zu sehen. Durch die Eingabe von Parametern konnten folgende Testfälle geprüft werden.
Bild ausgeben
ID | Testfallbeschreibung | Eingänge(Benötigtes Ausgabefenster, Ausgabebild) | Ausgang(figure, ausgegebene Video) | Erwartetes Ergebnis | Testergebnis | Testperson | Datum |
---|---|---|---|---|---|---|---|
1 | Es soll kein Ausgabefenster erstellt werden und kein Video ausgegeben werden. | Benötigtes Ausgabefenster = 0, Ausgabebild = 0 | Kein figure, kein Bild/Video | Kein figure, Kein Bild/Video | Kein Bild/Video | Heuer, Kruse | 16.06.2020 |
2 | Ausgabefenster soll geöffnet werden, jedoch kein Bild ausgegeben werden. | Benötigtes Ausgabefenster = RGB-Bild, Ausgabebild = 0 | figure RGB-Bild, kein Ausgabebild | figure ohne Ausgabebild | geöffnetes figure ohne Ausgabebild | Heuer, Kruse | 16.06.2020 |
3 | Ausgabefenster soll geöffnet werden und ein Bild ausgegeben werden. | Benötigtes Ausgabefenster = RGB-Bild, Ausgabebild = Matrix | figure RGB-Bild, dargestelltes Bild | figure mit Ausgabebild | geöffnetes figure mit einem Ausgabebild | Heuer, Kruse | 16.06.2020 |
Frame lesen
ID | Testfallbeschreibung | Eingänge(Video) | Ausgang(nächste Bild des Video) | Erwartetes Ergebnis | Testergebnis | Testperson | Datum |
---|---|---|---|---|---|---|---|
1 | Video nicht lesbar | Video = 0 | Kein Bild | Fehlermeldung | Video konnte nicht geladen werden | Heuer, Kruse | 16.06.2020 |
2 | Video vorhanden und nächste Frame verfügbar | Video = vorhanden | Ausgabe des Bildes | nächste Frame des Videos kann ausgegeben werden | Bild ausgegeben | Heuer, Kruse | 16.06.2020 |
3 | Letzte Frame des Videos wurde im Aufruf davor ausgegeben | Video = 0 | kein Bild | Fehlermeldung | Ausgabe von Frame konnte nicht geladen werden | Heuer, Kruse | 16.06.2020 |
Bildtransformation
ID | Testfallbeschreibung | Eingänge(RGB-Bild) | Ausgang(bearbeitetes Bild) | Erwartetes Ergebnis | Testergebnis | Testperson | Datum |
---|---|---|---|---|---|---|---|
1 | Es wird kein Bild ausgegeben, wenn kein RGB-Bild vorhanden ist. | RGB-Bild = 0 | Ausgabebild = 0 | Kein Bild | 0 | Heuer, Kruse | 16.06.2020 |
2 | Region of Interest wird angepasst, wenn ein RGB-Bild vorhanden ist | RGB-Bild = Matrix | Bild Region of Interest | Bild mit angepasster Region of Interest | Region of Interest angepasst | Heuer, Kruse | 16.06.2020 |
3 | RGB-Bild wird in ein Binär-Bild gewandelt | RGB-Bild = Matrix | Binär-Bild | Konvertierung von RGB- zu Binär-Bild | Binär-Bild aus RGB-Bild | Heuer, Kruse | 16.06.2020 |
4 | RGB-Bild wird in die Vogelperspektive transformiert | RGB-Bild = Matrix | Bild in Vogelperspektive | Bild mit angepasster Betrachtung | Vogelperspektive des RGB-Bilds | Heuer, Kruse | 16.06.2020 |
Config lesen und schreiben
ID | Testfallbeschreibung | Eingänge(Daten) | Ausgang(Daten) | Erwartetes Ergebnis | Testergebnis | Testperson | Datum |
---|---|---|---|---|---|---|---|
1 | Daten sollen in der ini.Datei gespeichert werden | Daten = 100 | 100 in der ini-Datei | Eintrag in der ini-Datei | Wert 100 wurde in der ini-Datei eingetragen | Heuer, Kruse | 16.06.2020 |
2 | Daten sollen aus der ini-Datei gelesen werden | ini-Datei = 50 | Gelesener Wert = 50 | Wert aus ini-Datei gelesen | Wert 50 wurde aus der ini-Datei gelesen | Heuer, Kruse | 16.06.2020 |
Konzept für dir Fahrspurerkennung und Approximation
Autoren: Stefan Arndt, Marius Köhler
Die Requirements aus Abb. 19 werden wir folgt in ein Programmablaufplan überführt. Dabei wird grundlegend folgendes Konzept angewandt:
- Kantendetektion durchführen
- Die Spur finden und per Sliding-Window die Spur verfolgen
- Punktparameter aus den Boxen extrahieren
- Per Polyfit eine Funktion 2. Grades approximieren
Anforderungen ans Modul und Testvorgänge:
-
Abb. 20: Programmablaufplan für die Fahrspurerkennung
-
Abb. 21: Programmablaufplan für die Boxberechnung
In der Abb. 22 ist das ausgeführte Programm zu sehen. Hierbei stellen die Rechtecke die Boxen aus der Sliding-Window Methode dar. Gelbe Boxen enthalten eine valide Linie. Rote Boxen sind nicht valide. Diese spielen bei der mittleren Linie eine große Rolle, da sie dort einen y-Offset verursachen um die unterbrochene Linienführung zu berechnen.
Die blauen Punkte die aus der approxmierten Funktion berechnet.
Statische Codeanalyse
Da Polyspace nicht mehr für Stundenten kostenlos ist, wurde die statische Codeanalyse mit dem kostenlosen Tool cppcheck durchgeführt.
Ergebnis: Der Bericht in Abb. 23 zeigt ausschließlich stilistische Anmerkungen. Diese sollten erst bei der Endversion überarbeitet werden, da diese zum Teil noch fürs Debuggen notwendig sind.
Dynamische Codeanalyse
Die dynamische Codeanalyse wurde mit den Codeanalyse-Tools von Visual Studio 2019 durchgeführt. Einmal für die Verbrauch des Arbeitsspeicher (RAM) und der Prozessorauslastung (CPU).
Ergebnis: Die RAM-Auslastung ist konstant, das heißt Speicherlecks sind im Programm nicht vorhanden.
Ergebnis: Auch die CPU-Auslastung ist beinahe konstant. Die größten Verbraucher der CPU-Zeit sind I/O-Funktionen und die Darstellungsfunktionen.
Diskussion
Autoren: Hagen Heuer, Tim Kruse
Binär-Bild genauer spezifizieren. Binärbild in Vogelperspektive
Äußere Schleife „Für jeden Frame“ überflüssig, da die Funktion für jeden Frame neu aufgerufen wird. (Echtzeitbetrieb) Falls noch nicht geschehen, kann der Programmablaufplan in unserem Programmablaufplan Projekt ergänzt werden. (Siehe Teamordner Heuer Kruse)
Offener Pfeil bei Abbruch. Dieser ist nicht mit dem Ende verbunden.
Reviewer: Hagen Heuer, Tim Kruse
Datum: 17.06.2020
Ausblick
Autoren: Hagen Heuer, Tim Kruse
Zurück zum Hauptartikel: OSE - Objekt - und Spurerkennung
→ zurück zur Übersicht: SDE-Team_2020/21