OSE Softwareumgebung: Unterschied zwischen den Versionen
(Hinzufügen von PAP für Spurbreitenerkennung) |
|||
(55 dazwischenliegende Versionen von 8 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
<!-- Kopieren Sie diesen Header in Ihren Artikel, damit er aufgelistet wird. --> | <!-- Kopieren Sie diesen Header in Ihren Artikel, damit er aufgelistet wird. --> | ||
'''Autoren:''' [[Benutzer:Hendrik_Steffen| Hendrik Steffen]], [[Benutzer:Sven_Posner| Sven Posner]] <br> | '''Autoren:''' [[Benutzer:Hendrik_Steffen| Hendrik Steffen]], [[Benutzer:Sven_Posner| Sven Posner]] <br> | ||
'''Bearbeitet von:''' [[Benutzer:Florian Brinkmann| Florian Brinkmann]] <br> | '''Bearbeitet von:''' [[Benutzer:Florian Brinkmann| Florian Brinkmann]], [[Benutzer:Jan Müller| Jan Müller]], [[Benutzer:Yannick Schmidt| Yannick Schmidt]] <br> | ||
'''Betreuer:''' [[Benutzer:Ulrich_Schneider| Prof. Schneider]]<br/> | '''Betreuer:''' [[Benutzer:Ulrich_Schneider| Prof. Schneider]]<br/> | ||
<br> | |||
→ zurück zum Hauptartikel: [[OSE - Objekt - und Spurerkennung]] <br> | |||
→ zurück zum Hauptartikel: [[Praktikum SDE]] <br> | |||
<br> | |||
= Quick Start= | = Quick Start= | ||
[[Datei:Uebersicht Tool Landschaft Wiki.png|right|600px|thumb|Abb. 1: Toolübersicht über den autonomen mobilen Roboter (AMR, jetzt CCF)]] | |||
# Visual Studio installieren [https://www.microsoft.com/de-de/techwiese/aktionen/visual-studio-kostenlos.aspx Visual Studio Community 2019] <br> | # Visual Studio installieren [https://www.microsoft.com/de-de/techwiese/aktionen/visual-studio-kostenlos.aspx Visual Studio Community 2019] <br> | ||
# In Visual Studio mit Studentenemail-Adresse Account erstellen und kostenlos anmelden | # In Visual Studio mit Studentenemail-Adresse Account erstellen und kostenlos anmelden | ||
# C++ Erweiterung herunterladen und installieren | # C++ Erweiterung herunterladen und installieren | ||
# Vr Cam Lab installieren um die Treiber zu erhalten [https://www.vrmagic-imaging.com/service/downloads/usb-platform-downloads Vr Cam Lab] <br> | # Vr Cam Lab installieren um die Treiber zu erhalten [https://www.vrmagic-imaging.com/service/downloads/usb-platform-downloads Vr Cam Lab] <br> | ||
# | # [[Einrichten_von_OpenCV_in_Visual_Studio|OpenCV]] in der Version 3.0.0 installieren und auf der Festplatte D entpacken. '''Wichtig: Oberordner muss opencv heißen (D:\opencv\...)''' | ||
# Svn auschecken. Die aktuelle Software liegt unter dem Pfad: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/OSE_Draufsicht_Spurpolynom_RS232 <br> | # Svn auschecken. Die aktuelle Software liegt unter dem Pfad: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/OSE_Draufsicht_Spurpolynom_RS232 <br> | ||
# Videopfad in der Config.ini Datei auf den lokalen Speicherort ändern. Das Video für die Simulation befindet sich unter: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/OSE_Draufsicht_Spurpolynom_RS232/Video/Rundkurs.mp4<br> | # Videopfad in der Config.ini Datei auf den lokalen Speicherort ändern. Das Video für die Simulation befindet sich unter: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/OSE_Draufsicht_Spurpolynom_RS232/Video/Rundkurs.mp4<br> | ||
Zeile 19: | Zeile 22: | ||
[[Einrichten von OpenCV in Visual Studio | Einrichten von OpenCV in Visual Studio]] <br/> | [[Einrichten von OpenCV in Visual Studio | Einrichten von OpenCV in Visual Studio]] <br/> | ||
[[Inbetriebnahme der VRmagic Kamera |Implementierung der Kamera in Visual Studio]] | [[Inbetriebnahme der VRmagic Kamera |Implementierung der Kamera in Visual Studio]] | ||
<br clear=all> | |||
=Programmstruktur= | =Programmstruktur= | ||
[[Datei:Pap Sim Live.png|800px|thumb|right|Abb. 2: PAP der Programmstruktur]] | |||
Die Softwareumgebung ermöglicht es, in einer Umgebung die Simulation und das Livebild anzuzeigen und die Koeffizienten des Spurpolynoms auszugeben. Zusätzlich soll die Kalibrierung der Kamera auch möglich werden (im Aufbau). In der untenstehenden Abbildung ist die Struktur dieser Softwareumgebung dargestellt. | Die Softwareumgebung ermöglicht es, in einer Umgebung die Simulation und das Livebild anzuzeigen und die Koeffizienten des Spurpolynoms auszugeben. Zusätzlich soll die Kalibrierung der Kamera auch möglich werden (im Aufbau). In der untenstehenden Abbildung ist die Struktur dieser Softwareumgebung dargestellt. | ||
Zu Beginn kann zwischen der Simulation, dem Livebild oder dem Beenden des Programms ausgewählt werden. Wenn das Programm nicht beendet wurde, werden im nächsten Schritt die Variablen initialisiert. Je nach Auswahl der Bildquelle wird das Bild unterschiedlich eingelesen. Wichtig ist dass sich nur das Einlesen der Bilder unterscheidet danach verläuft die Auswertung wieder über den gleichen Code. Das ermöglicht die Optimierung der Spurerkennung in der Simulation und das Testen in der Live-Anwendung. | Zu Beginn kann zwischen der Simulation, dem Livebild oder dem Beenden des Programms ausgewählt werden. Wenn das Programm nicht beendet wurde, werden im nächsten Schritt die Variablen initialisiert. Je nach Auswahl der Bildquelle wird das Bild unterschiedlich eingelesen. Wichtig ist dass sich nur das Einlesen der Bilder unterscheidet danach verläuft die Auswertung wieder über den gleichen Code. Das ermöglicht die Optimierung der Spurerkennung in der Simulation und das Testen in der Live-Anwendung. | ||
Zeile 36: | Zeile 40: | ||
Nach der Initialisierung wird zyklisch ein neues Bild aus dem Videopuffer gelesen in ein Alpha-RGB-Bild umgewandelt, da dies mit dem Mat-Format von openCV kompatibel ist. Am Ende eines Zyklus steht, genau wie in der Simulation ein Mat-Bild zur Verfügung. Dieses wird in der Bildtransformation und Spurerkennung weiterverarbeitet. | Nach der Initialisierung wird zyklisch ein neues Bild aus dem Videopuffer gelesen in ein Alpha-RGB-Bild umgewandelt, da dies mit dem Mat-Format von openCV kompatibel ist. Am Ende eines Zyklus steht, genau wie in der Simulation ein Mat-Bild zur Verfügung. Dieses wird in der Bildtransformation und Spurerkennung weiterverarbeitet. | ||
<br><br> | <br> | ||
<br clear=all> | |||
=Simulationsumgebung= | =Simulationsumgebung= | ||
In der Simulationsumgebung wird ein vorher aufgezeichnetes Videobild genutzt, um das Kamerabild zu simulieren. Dazu wird im ersten Schritt, sobald die Simulation ausgewählt wurde, der Dateipfad des Videos eingelesen. In der config.ini kann eingestellt werden, welches Video für die Simulation verwendet werden soll. Es reicht dabei lediglich den Dateinamen zu ändern, das Standard Video ist "Rundkurs.mp4" und sollte auf jeden Fall im Ordner enthalten sein. Im SVN müssen die Videos unter: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/Simulation_Bildverarbeitung_und_Spurerkennung/Videos/Rundkurs.mp4 hinterlegt sein. Falls der Dateiname in der Config.ini falsch hinterlegt ist, wird in der Konsole kurz "Ungültige Eingabe!" angezeigt, bevor dann wieder die Auswahlseite für Simulation, das Live-Bild usw. angezeigt wird. Sobald der Dateipfad zum Video richtig hinterlegt wurde, sollte diese Fehlermeldung nicht mehr erscheinen und die Simulation starten. | In der Simulationsumgebung wird ein vorher aufgezeichnetes Videobild genutzt, um das Kamerabild zu simulieren. Dazu wird im ersten Schritt, sobald die Simulation ausgewählt wurde, der Dateipfad des Videos eingelesen. In der config.ini kann eingestellt werden, welches Video für die Simulation verwendet werden soll. Es reicht dabei lediglich den Dateinamen zu ändern, das Standard Video ist "Rundkurs.mp4" und sollte auf jeden Fall im Ordner enthalten sein. Im SVN müssen die Videos unter: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/Simulation_Bildverarbeitung_und_Spurerkennung/Videos/Rundkurs.mp4 hinterlegt sein. Falls der Dateiname in der Config.ini falsch hinterlegt ist, wird in der Konsole kurz "Ungültige Eingabe!" angezeigt, bevor dann wieder die Auswahlseite für Simulation, das Live-Bild usw. angezeigt wird. Sobald der Dateipfad zum Video richtig hinterlegt wurde, sollte diese Fehlermeldung nicht mehr erscheinen und die Simulation starten. | ||
==Anpassung der Bildausgabe durch Skalierung== | |||
In der OSE-Softwareumgebung wird das erkannte Polynom visuell in einem separaten Fenster dargestellt. Auf Laptops mit hochauflösenden Displays kann es jedoch vorkommen, dass das Ausgabe-Fenster durch die systemseitige Windows-Skalierung zu groß dargestellt wird und nicht mehr vollständig sichtbar ist. | |||
Um dieses Problem zu lösen, wurde die Funktion BildAnzeigen() implementiert. Diese passt die Größe des angezeigten Bildes dynamisch an, indem das Bild vor der Ausgabe entsprechend skaliert wird. Der Skalierungsfaktor kann in der config.ini angepasst werden und wird dort in Prozent angegeben. Dadurch lässt sich die Anzeige flexibel auf verschiedene Bildschirmauflösungen abstimmen, ohne dass die Bildverarbeitung selbst beeinflusst wird. | |||
Diese Erweiterung verbessert die Nutzbarkeit der OSE-Software insbesondere auf hochauflösenden Displays und ermöglicht eine individuelle Anpassung der Darstellung je nach Systemkonfiguration. | |||
Mit der Funktion '''FA_InitVideo''' werden die Ausgabefenster der Bilder angepasst. Welche Bilder Ausgegeben werden sollen, kann ebenfalls in der Config-Datei festgelegt werden. | Mit der Funktion '''FA_InitVideo''' werden die Ausgabefenster der Bilder angepasst. Welche Bilder Ausgegeben werden sollen, kann ebenfalls in der Config-Datei festgelegt werden. | ||
Zeile 80: | Zeile 91: | ||
==Schritt 1: Transformation== | ==Schritt 1: Transformation== | ||
[[Datei:OSE_ROI_Fahrzeug_1.png|200px|thumb|right|Lage des ROI im Fahrzeug-KOS (Wagen 1)]] | |||
Die Transformation des Bildes findet in der Funktion '''cv::Mat BTF_ImgTransf(cv::Mat img_Mat, bool ausgabe_abit[])''' statt. Diese befindet sich in der Datei '''Bildtransformation.cpp. | Die Transformation des Bildes findet in der Funktion '''cv::Mat BTF_ImgTransf(cv::Mat img_Mat, bool ausgabe_abit[])''' statt. Diese befindet sich in der Datei '''Bildtransformation.cpp. | ||
In dieser Funktion werden zunächst die intrinsischen Kameraparameter eingegeben, die mithilfe der Matlab Toolbox Camera Calibrator erstellt wurden. Dazu wurde ein Schachbrettmuster genutzt, dass in verschiedenen Perspektiven vor die Kamera gehalten wurde. Wie man an diese Parameter dann kommt ist in der Matlab Hilfe hier '''[https://de.mathworks.com/help/vision/camera-calibration.html Camera Calibration]''' | In dieser Funktion werden zunächst die intrinsischen Kameraparameter eingegeben, die mithilfe der Matlab Toolbox Camera Calibrator erstellt wurden. Dazu wurde ein Schachbrettmuster genutzt, dass in verschiedenen Perspektiven vor die Kamera gehalten wurde. Wie man an diese Parameter dann kommt ist in der Matlab Hilfe hier '''[https://de.mathworks.com/help/vision/camera-calibration.html Camera Calibration]''' , im Wiki Artikel '''[[Kameraparametrierung | Kamerakalibrierung]]''' oder im Wiki-Artikel '''[[Kalibrierung der Kamera | Kalibrierung der Kamera]]''' beschrieben. | ||
Dann erfolgt die Umwandlung des Bildes in ein Graustufenbild, was in der Funktion '''binarisierung(img_Mat, ausgabe_abit[2], ausgabe_abit[3]);''' stattfindet. Rückgabewert ist dann ein schwarz weiß Bild der Kamera in der Ursprungsgröße. | Dann erfolgt die Umwandlung des Bildes in ein Graustufenbild, was in der Funktion '''binarisierung(img_Mat, ausgabe_abit[2], ausgabe_abit[3]);''' stattfindet. Rückgabewert ist dann ein schwarz weiß Bild der Kamera in der Ursprungsgröße. | ||
Zeile 91: | Zeile 103: | ||
Abschließend wird das Bild noch mithilfe eines Kantenerkennungsalgorithmus durch die '''cv::Canny(OSE_zielBild_st, OSE_filterBild_st, 100, 200, 3);''' Funktion in ein Kantenbild überführt, dass zurückgegeben wird. | Abschließend wird das Bild noch mithilfe eines Kantenerkennungsalgorithmus durch die '''cv::Canny(OSE_zielBild_st, OSE_filterBild_st, 100, 200, 3);''' Funktion in ein Kantenbild überführt, dass zurückgegeben wird. | ||
== | Für die weitere Verwendung der Vogelperspektive wird nur ein bestimmter Region of Interest (ROI) benötigt. Die nebenstehende Abbildung zeigt die Lage und Größe des ROI im Fahrzeug-Koordinatensystem. Gemessen wurde vom Ursprung des Fahrzeug-KOS aus, also ohne Berücksichtigung des vorderen Bumpers (siehe auch [[Fahrzeughardware#Konstruktion_und_Gesamtaufbau | Fahrzeughardware]]). Somit beträgt der Abstand zwischen ROI und Fahrzeug <math> 520\,mm </math>. Zur Umrechnung von (Bild-)Pixel (px) in mm ergeben sich folgende Faktoren: | ||
* x-Richtung (längs): <math> \frac{2710\,mm}{1113\,px} = 2,4\,\frac{mm}{px} </math> | |||
* y-Richtung (quer): <math> \frac{1200\,mm}{752\,px} = 1,6\,\frac{mm}{px} </math> | |||
[[Datei:KosTrafo Funktion.PNG|400px|thumb|right|KosTrafo-Funktion]] | |||
Die ermittelten Transformations-Parameter müssen in der Funktion "KosTrafo" hinterlegt werden. Diese Funktion befindet sich in der Spurerkennung.cpp, die innerhalb der main() aufgerufen wird. | |||
Die benötigten Parameter heißen "UmrechungsfaktorX", "UmrechungsfaktorY" und "AbstandROI". Diese sind vor einer swtich-case-Anwendung deklariert und werden abhängig von der Wahl des Fahrzeuges beim Start des Programms, entsprechend initialisiert (siehe Abbildung: KosTrafo-Funktion). | |||
==Schritt 2: Spurerkennung== | |||
Die Spurerkennung erfolgt durch den Funktionsaufruf '''Spurerkennung''', diese Funktion ist in der Datei '''Spurerkennung.cpp''' implementiert. | Die Spurerkennung erfolgt durch den Funktionsaufruf '''Spurerkennung''', diese Funktion ist in der Datei '''Spurerkennung.cpp''' implementiert. | ||
[[Datei:PAP Spurerkennung.png|200px|thumb|right|Ablauf der Spurerkennung]] | [[Datei:PAP Spurerkennung.png|200px|thumb|right|Ablauf der Spurerkennung]] | ||
Zeile 109: | Zeile 129: | ||
Die Berechnung der Schnittpunktkoordinaten erfolgt, wie in der Abbildung dargestellt. Nachdem die Variablen initialisiert wurden, wird das aktuelle Bild durchlaufen. Dabei wird von unten nach oben zeilenweise vorgegangen. Der Abstand der Zeilen erhöht sich mit zunehmender Bildhöhe, da die näheren Punkte relevanter sind. In dieser Schleife werden als erstes die nicht gefundenen Punkte aus dem vorherigen Zyklus eingezeichnet. Das ermöglicht eine bessere Analyse der Ergebnisse. Für jede Zeile wurde ein Gate festgelegt in dem der nächste Spurpunkt zu finden ist. Dieses Gate ergibt sich aus dem letzten gefundenen Punkt. | Die Berechnung der Schnittpunktkoordinaten erfolgt, wie in der Abbildung dargestellt. Nachdem die Variablen initialisiert wurden, wird das aktuelle Bild durchlaufen. Dabei wird von unten nach oben zeilenweise vorgegangen. Der Abstand der Zeilen erhöht sich mit zunehmender Bildhöhe, da die näheren Punkte relevanter sind. In dieser Schleife werden als erstes die nicht gefundenen Punkte aus dem vorherigen Zyklus eingezeichnet. Das ermöglicht eine bessere Analyse der Ergebnisse. Für jede Zeile wurde ein Gate festgelegt in dem der nächste Spurpunkt zu finden ist. Dieses Gate ergibt sich aus dem letzten gefundenen Punkt. | ||
In diesem Gate wird ein Spurpunkt mittels der Funktion Spursuchen ermittelt. In dieser Funktion werden die Punkte im Gate durchgegangen. Wird eine Wechsel von Schwarz auf Weiß detektiert, werden die weißen Pixel gezählt. Stimmen diese mit einer festgelegten Toleranz mit der Spurbreite überein, gilt die Spur als gefunden. Die letzte gefundene Spur wird als rechte Spur gespeichert. | In diesem Gate wird ein Spurpunkt mittels der Funktion Spursuchen ermittelt. In dieser Funktion werden die Punkte im Gate durchgegangen. Wird eine Wechsel von Schwarz auf Weiß detektiert, werden die weißen Pixel gezählt. Stimmen diese mit einer festgelegten Toleranz mit der Spurbreite überein, gilt die Spur als gefunden. Die letzte gefundene Spur wird als rechte Spur gespeichert. Die Abbildung Spurbreite_PAP zeigt den PAP für diese Funktion. | ||
[[Datei:Spurbreite pap.png|600px|mini|links|Spurbreite_PAP]] | |||
<br clear=all> | |||
Wenn kein Spurpunkt gefunden wurde, wird nichts gespeichert, aber der letzte gefundene Punkt (vorheriger Zyklus) wird für das neue Gate verwendet. Gefundene Punkte werden gespeichert und eingezeichnet. Wenn es der erste Schnittpunkt des Bildes ist, wird dieser als Startpunkt für das nächste Bild gespeichert. Die Gefundenen Schnittpunkte werden gezählt. Sobald die Arraygröße überschritten wird oder das ende des Bilds erreicht wird, wird das Suchen abgebrochen. Die Anzahl der gefundenen Punkte wird übergeben, um nur daraus das Polynom zu berechnen. | Wenn kein Spurpunkt gefunden wurde, wird nichts gespeichert, aber der letzte gefundene Punkt (vorheriger Zyklus) wird für das neue Gate verwendet. Gefundene Punkte werden gespeichert und eingezeichnet. Wenn es der erste Schnittpunkt des Bildes ist, wird dieser als Startpunkt für das nächste Bild gespeichert. Die Gefundenen Schnittpunkte werden gezählt. Sobald die Arraygröße überschritten wird oder das ende des Bilds erreicht wird, wird das Suchen abgebrochen. Die Anzahl der gefundenen Punkte wird übergeben, um nur daraus das Polynom zu berechnen. | ||
<br> | <br> | ||
<br> | <br> | ||
[[Datei:PAP Spurwechsel.png|300px|thumb|right|Vorgehen Spuränderung]] | |||
'''Erweiterung um dynamische Spurzuordnung'''<br> | '''Erweiterung um dynamische Spurzuordnung'''<br> | ||
Damit die Spurerkennung auch während Kurven zuverlässig (zumindest) eine Spur erkennen kann, wird u.U. ein Sprung von einer Fahrbahnmarkierung zu einer anderen benötigt. Um dies zu ermöglichen wurde der im folgende erläuterte Algorithmus an das Ende der Schnittpunktberechnung implementiert. | Damit die Spurerkennung auch während Kurven zuverlässig (zumindest) eine Spur erkennen kann, wird u.U. ein Sprung von einer Fahrbahnmarkierung zu einer anderen benötigt. Um dies zu ermöglichen wurde der im folgende erläuterte Algorithmus an das Ende der Schnittpunktberechnung implementiert. | ||
Zeile 122: | Zeile 145: | ||
Mit dem nächsten Frame wird nun nach der gegenüberliegenden Fahrbahn gesucht. Damit auch definitiv die äußere Markierung gefunden wird wird die for Schleife zum suchen der Spur entweder von rechts nach links im Bild (für die linke Markierung) oder von links nach rechts (für die rechte Markierung) durchlaufen. Der restliche Algorithmus bleibt von dieser Änderung unbetroffen, sodass auch mit geänderter Spur die Gate-Berechnung etc. einwandfrei funktioniert. | Mit dem nächsten Frame wird nun nach der gegenüberliegenden Fahrbahn gesucht. Damit auch definitiv die äußere Markierung gefunden wird wird die for Schleife zum suchen der Spur entweder von rechts nach links im Bild (für die linke Markierung) oder von links nach rechts (für die rechte Markierung) durchlaufen. Der restliche Algorithmus bleibt von dieser Änderung unbetroffen, sodass auch mit geänderter Spur die Gate-Berechnung etc. einwandfrei funktioniert. | ||
==Schritt 3: Stopplinienerkennung== | <br clear=all> | ||
==Schritt 3: Koordinatentransformation== | |||
[[Datei:SDE Praktikum KOS Transformation Konzept.png|500px|thumb|rechts|KOS-Transformation Skizze]] | |||
Gemäß Schnittstellendokumentation muss eine Koordiantentransformation vom Kamerafesten-KOS in das Fahrzeugfeste-KOS erfolgen.<br> | |||
{| class="wikitable" | |||
|+ Schnittstellendokumentation Koordinatensysteme | |||
|- | |||
! Koordinatensystem !! Kamerafest !! Fahrzeugfest | |||
|- | |||
| Index || V (Videofest) || K (Kamerafest) | |||
|- | |||
| Einheit || Pixel || Millimeter | |||
|- | |||
| Ursprung || Linke, obere Ecke || Mitte Vorderkante des vorderen Stoßfängers (z=0) | |||
|- | |||
| X-Achse || Nach rechts || Nach vorne (in Fahrtrichtung) | |||
|- | |||
| Y-Achse || Nach unten || Nach links | |||
|- | |||
| Z-Achse || keine vorhanden || Nach oben | |||
|} | |||
Dafür wurde die Funktion '''KosTrafo(real_T xWerte[], real_T yWerte[], int& laengeArray)''' in die '''Spurerkennung.cpp''' implementiert, welche die X- und Y-Positionen der erkannten Spurpunkte vom Bild-KOS in das Fahrzeug-KOS umrechnet. | |||
Für einen möglichst geringen Rechenaufwand wurde eine zweidimensionale Transformationsmatrix verwendet und die festen Werte der Drehung und Spiegelung der Y-Achse eingetragen. | |||
Die Transformationsmatrix sieht wie folgt aus: | |||
{| class="wikitable" | |||
|+ Transformationsmatrix | |||
|- | |||
| cos(90) = 0 || -sin(90) = -1 || AbstandROI+Bildlänge | |||
|- | |||
| sin(90) * -1 = -1 || cos(90) = 0 || Bildbreite/2 | |||
|- | |||
| 0 || 0 || 1 | |||
|} | |||
Zuletzt folgt noch eine Umrechnung von Pixel in mm nach den in Schritt 1 vorgestellten Parametern. | |||
<br clear=all> | |||
==Schritt 4: Kalman-Filter== | |||
'''Autor:''' [[Benutzer:Jan Müller|Jan Müller]] | |||
<br> | |||
'''Die Implementierung des Kalman-Filters ist im folgenden Artikel beschrieben''' [[Datei:Ezgif-3-aa149494be25.gif]] [[Kalman-Filterung der Spurerkennung]] | |||
==Schritt 5: Stopplinienerkennung== | |||
'''Autor:''' [[Benutzer:Florian Brinkmann|Florian Brinkmann]] | '''Autor:''' [[Benutzer:Florian Brinkmann|Florian Brinkmann]] | ||
[[Datei: | Die Beschreibung der Stopplinienerkennung wurde aufgrund der Komplexität in einen eigenen Artikel ausgelagert. <br> | ||
< | '''Hier geht es zum Artikel''' [[Datei:Ezgif-3-aa149494be25.gif]] [[OSE Stopplinienerkennung]] | ||
==Schritt 6: Rücktransformation des gefilterten Polynoms in Bildkoordinaten== | |||
'''Autor:''' Daniel Block | |||
Im Rahmen der Spurverfolgung innerhalb der OSE-Softwareumgebung wird das erkannte Polynom zunächst von den Bildkoordinaten in das Fahrzeugkoordinatensystem überführt. In diesem System erfolgt die Verarbeitung, unter anderem durch die Anwendung eines Kalman-Filters zur Glättung und Optimierung der Spurführung. Damit das gefilterte Polynom auch visuell korrekt dargestellt werden kann, muss es anschließend wieder in das Bildkoordinatensystem zurücktransformiert werden. | |||
Die Funktion backTransformPolynomial() übernimmt diese Rücktransformation, indem sie die ursprüngliche Transformation invers durchführt. Dabei werden die Fahrzeugkoordinaten so umgerechnet, dass das gefilterte Polynom im Bildkoordinatensystem dargestellt werden kann. Grundlage für diese Umrechnung sind fahrzeugspezifische Skalierungsfaktoren sowie ein fester Translationsvektor. | |||
Nach der Umrechnung wird das transformierte Polynom erneut angepasst, sodass es in das bestehende Bildkoordinatensystem integriert werden kann. Diese Rücktransformation stellt sicher, dass die erkannte Spur auch nach der Filterung korrekt im Kamerabild visualisiert wird und eine präzise Überlagerung mit der realen Fahrbahnmarkierung möglich ist. | |||
Im folgenden ist der C++ Code für die Rücktransformation gezeigt: | |||
<div class="mw-collapsible mw-collapsed" style="float:left; margin-left:0; margin-right:1em;"> | |||
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:small"> | |||
void backTransformPolynomial( | |||
double a_in, double b_in, double c_in, // Fahrzeug-Polynom-Parameter | |||
int fahrzeug_auswahl, // Fahrzeugtyp zur Paraminitialisierung | |||
double& a_out, double& b_out, double& c_out // Output: Bild-Polynom-Parameter | |||
) | |||
{ | |||
static bool first = true; // Fahrzeugparameter geladen? | |||
//Umrechnungsfaktoren, siehe Schritt 1 unter https://wiki.hshl.de/wiki/index.php/OSE_Softwareumgebung | |||
static float UmrechnungsfaktorX; | |||
static float UmrechnungsfaktorY; | |||
static float AbstandROI; | |||
// Parameter laden | |||
if (first) | |||
{ | |||
switch (fahrzeug_auswahl) | |||
{ | |||
case 1: | |||
UmrechnungsfaktorX = 1.44; // in mm/px | |||
UmrechnungsfaktorY = 1.33; // in mm/px | |||
AbstandROI = 430 / UmrechnungsfaktorX; // in mm | |||
break; | |||
case 2: | |||
UmrechnungsfaktorX = 2.11; // in mm/px | |||
UmrechnungsfaktorY = 1.6; // in mm/px | |||
AbstandROI = 580 / UmrechnungsfaktorX; // in mm | |||
break; | |||
default: | |||
cout << endl << "Falsche Fahrzeugauswahl" << endl; | |||
cout << endl << "Press the enter button, to close the program" << endl; | |||
cin.get(); | |||
exit(-1); | |||
break; | |||
} | |||
first = false; | |||
} | |||
//Translationsvektor T = [T1, T2] | |||
static float T1 = 1113 + AbstandROI; | |||
static float T2 = 752 / 2; | |||
// Bereich für x im Fahrzeugkoordinatensystem definieren (Meter) | |||
// Dies muss an Ihren Anwendungsfall angepasst werden. | |||
double xStart = -5.0; | |||
double xEnd = 20.0; | |||
int numPoints = 100; | |||
double step = (xEnd - xStart) / (numPoints - 1); | |||
std::vector<double> xBildWerte(numPoints), yBildWerte(numPoints); | |||
for (int i = 0; i < numPoints; i++) { | |||
double xFzg = xStart + i * step; | |||
double yFzg = a_in * xFzg * xFzg + b_in * xFzg + c_in; | |||
// Inverse Transformation: | |||
// yBild = T1 - (xFzg / UmrX) | |||
// xBild = T2 - (yFzg / UmrY) | |||
double yBild = T1 - (xFzg / UmrechnungsfaktorX); | |||
double xBild = T2 - (yFzg / UmrechnungsfaktorY); | |||
xBildWerte[i] = xBild; | |||
yBildWerte[i] = yBild; | |||
} | |||
// Nun haben wir Punkte (xBildWerte, yBildWerte) im Bildkoordinatensystem. | |||
// Passe nun erneut ein Polynom an: | |||
//fitPolynomial(xBildWerte, yBildWerte, a_out, b_out, c_out); | |||
emxArray_real_T* OSE_xWerteMatlabDLL_ast; | |||
emxArray_real_T* OSE_yWerteMatlabDLL_ast; | |||
OSE_xWerteMatlabDLL_ast = emxCreateWrapper_real_T(&xBildWerte[0], 1, numPoints); | |||
OSE_yWerteMatlabDLL_ast = emxCreateWrapper_real_T(&yBildWerte[0], 1, numPoints); | |||
polynom(OSE_yWerteMatlabDLL_ast, OSE_xWerteMatlabDLL_ast, &a_out, &b_out, &c_out); //Berechnen des Spurpolynoms anhand der Matlab Funktion | |||
} | |||
</syntaxhighlight> | |||
</pre> | |||
</div> | |||
Durch diese Rücktransformation des Polynoms ist es möglich, das Polynom im Ausgabefenster darzustellen. Die folgende Abbildung zeigt das Ausgabefenster mit dem gefilterten Polynom, welches so an die dSPACE-Karte übertragen wird. | |||
[[Datei:AnzeigeFinaleSpur.png|600px|mini|links|Anzeige des finalen Spurpolynoms]] | |||
<br clear = all> | |||
= Visualisierung der erkannten Spurpunkte = | |||
'''Autor:''' Daniel Block | |||
Für eine verbesserte Darstellung der erkannten Fahrbahnmarkierung werden die berechneten Spurpunkte direkt in das Bild eingezeichnet. Dies ermöglicht eine visuelle Überprüfung der detektierten Spur und erleichtert die Fehleranalyse sowie die Optimierung der Spurverfolgungsalgorithmen. | |||
Die erkannten Punkte werden mit der OpenCV-Funktion circle() als rote Markierungen in das Bild eingezeichnet. Dabei wird für jeden gefundenen Punkt ein Kreis mit einem definierten Radius gezeichnet. | |||
Diese Visualisierung dient nicht nur zur Debugging-Zwecken, sondern auch zur Verbesserung der Nutzerfreundlichkeit der OSE-Software, da sie eine unmittelbare Rückmeldung über die erkannten Fahrbahnmarkierungen liefert. | |||
Die folgende Abbildung zeigt das Ausgabefenster mit eingezeichneten Spurpunkten: | |||
[[Datei:EingezeichneteSpurpunkte.png|600px|mini|links|Anzeige der Spurpunkte]] | |||
<br clear = all> | |||
= Dynamische Anpassung der Region of Interest (ROI) in Kurven = | |||
In der OSE-Softwareumgebung wurde die Spurerkennung so erweitert, dass die Region of Interest (ROI) dynamisch an die Fahrsituation angepasst wird. Insbesondere in Kurven wird der ROI verkleinert, um eine präzisere Erkennung der Fahrbahn zu ermöglichen. | |||
== Funktionsweise der Anpassung == | |||
Die Anzahl der Gates für die Berechnung der Spur-Schnittpunkte wird basierend auf dem Spurparameter OSE_SpurparamterA_f32 reguliert. Dieser Wert beschreibt die Krümmung der Fahrspur. | |||
Kurvige Streckenabschnitte: | |||
Wenn OSE_SpurparamterA_f32 größer als 0.2 ist, wird angenommen, dass sich das Fahrzeug in einer Kurve befindet. In diesem Fall wird die maximale Anzahl der Gates (maxArrayGroesse) schrittweise verringert, jedoch nicht unter einen Mindestwert von 8, um eine stabile Erkennung zu gewährleisten. | |||
Gerade Streckenabschnitte: | |||
Wenn der Spurparameter unter 0.2 liegt, wird die Anzahl der Gates wieder schrittweise erhöht, bis der ursprüngliche Maximalwert von 13 erreicht ist. Dadurch wird sichergestellt, dass auf geraden Strecken ein weiterer Bereich für die Spurerkennung genutzt wird. | |||
Diese Anpassung der ROI verbessert die Spurverfolgung in Kurven erheblich, da unnötige Bildbereiche ausgeschlossen und die Berechnung effizienter durchgeführt wird. | |||
Der Quellcode für diese Anpassung: | |||
<div class="mw-collapsible mw-collapsed" style="float:left; margin-left:0; margin-right:1em;"> | |||
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:small"> | |||
static int maxArrayGroesse = 13; | |||
if (OSE_SpurparamterA_f32 > 0.2) | |||
{ | |||
if (maxArrayGroesse > 8) | |||
{ | |||
maxArrayGroesse = maxArrayGroesse - 1; | |||
} | |||
} | |||
else | |||
{ | |||
if (maxArrayGroesse < 13) | |||
{ | |||
maxArrayGroesse = maxArrayGroesse + 1; | |||
} | |||
} | |||
</syntaxhighlight> | |||
</pre> | |||
</div> | |||
<br clear = all> | |||
== Programmablaufdiagramm == | |||
Das nachfolgende Programmablaufdiagramm (PAP) veranschaulicht die Funktionsweise der dynamischen Anpassung der ROI anhand der aktuellen Werte von OSE_SpurparamterA_f32 und maxArrayGroesse: | |||
[[Datei:ROIAnpassung pap.png|600px|mini|links|Anpassung des ROI in Kurven PAP]] | |||
<br clear = all> | |||
Diese Erweiterung sorgt für eine präzisere Spurerkennung, insbesondere in engen Kurven, und trägt zur Verbesserung der Fahrstabilität bei. | |||
<br clear = all> | |||
= Daten senden = | |||
[[ | Im letzten Teil nach Einlesen und Verarbeiten der Daten werden diese über die RS232 Schnittstelle gesendet. Dies ist aber nicht mehr Teil unserer Arbeit sondern ist im Wiki Artikel [[Kommunikation_zwischen_PC_und_dSpace-Karte_via_RS232 |Kommunikation zwischen PC und dSpace-Karte via RS232]] <!--https://wiki.hshl.de/wiki/index.php/Kommunikation_zwischen_PC_und_dSpace-Karte_via_RS232--> beschrieben. | ||
= Testkonzept = | |||
Das [[SDE-Team 2021/22]] hat im Rahmen des Praktikums verschiedene Testfälle entwickelt, die fortlaufend genutzt und angepasst werden. Für die OSE Softwareumgebung sind die Testfälle auf den beiden folgenden Wiki-Seiten zu finden: | |||
* [[OSE - Objekt - und Spurerkennung: Test der Spurparameter-Ermittlung in der Simulation| OSE: Test der Spurparameter-Ermittlung in der Simulation]] | |||
* [[OSE - Objekt - und Spurerkennung: Test der Spurparameter-Ermittlung am Fahrzeug | OSE: Test der Spurparameter-Ermittlung am Fahrzeug]] | |||
Alle anderen Wiki-Seiten sind auf der [[SDE-Team_2021/22#Testkonzept|Teamseite]] verlinkt. | |||
= | = Literatur = | ||
<references /> | |||
<br> | <br> |
Aktuelle Version vom 31. Januar 2025, 12:28 Uhr
Autoren: Hendrik Steffen, Sven Posner
Bearbeitet von: Florian Brinkmann, Jan Müller, Yannick Schmidt
Betreuer: Prof. Schneider
→ zurück zum Hauptartikel: OSE - Objekt - und Spurerkennung
→ zurück zum Hauptartikel: Praktikum SDE
Quick Start
![](/wiki/images/thumb/e/e6/Uebersicht_Tool_Landschaft_Wiki.png/600px-Uebersicht_Tool_Landschaft_Wiki.png)
- Visual Studio installieren Visual Studio Community 2019
- In Visual Studio mit Studentenemail-Adresse Account erstellen und kostenlos anmelden
- C++ Erweiterung herunterladen und installieren
- Vr Cam Lab installieren um die Treiber zu erhalten Vr Cam Lab
- OpenCV in der Version 3.0.0 installieren und auf der Festplatte D entpacken. Wichtig: Oberordner muss opencv heißen (D:\opencv\...)
- Svn auschecken. Die aktuelle Software liegt unter dem Pfad: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/OSE_Draufsicht_Spurpolynom_RS232
- Videopfad in der Config.ini Datei auf den lokalen Speicherort ändern. Das Video für die Simulation befindet sich unter: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/OSE_Draufsicht_Spurpolynom_RS232/Video/Rundkurs.mp4
- Kamera mit LAN und Netzteil verbinden. Bis die Kamera gestartet hat kann über eine Minute vergehen.
Wichtig: Wenn in den Projekteinstellungen nichts verändert wird und alle oben genannten Punkte korrekt durchlaufen wurde, werden alle notwendigen Bibliotheken gefunden
Werden die Pfade geändert, und nur dann nach den folgenden Anleitungen vorgehen:
Einrichten von OpenCV in Visual Studio
Implementierung der Kamera in Visual Studio
Programmstruktur
![](/wiki/images/thumb/0/00/Pap_Sim_Live.png/800px-Pap_Sim_Live.png)
Die Softwareumgebung ermöglicht es, in einer Umgebung die Simulation und das Livebild anzuzeigen und die Koeffizienten des Spurpolynoms auszugeben. Zusätzlich soll die Kalibrierung der Kamera auch möglich werden (im Aufbau). In der untenstehenden Abbildung ist die Struktur dieser Softwareumgebung dargestellt.
Zu Beginn kann zwischen der Simulation, dem Livebild oder dem Beenden des Programms ausgewählt werden. Wenn das Programm nicht beendet wurde, werden im nächsten Schritt die Variablen initialisiert. Je nach Auswahl der Bildquelle wird das Bild unterschiedlich eingelesen. Wichtig ist dass sich nur das Einlesen der Bilder unterscheidet danach verläuft die Auswertung wieder über den gleichen Code. Das ermöglicht die Optimierung der Spurerkennung in der Simulation und das Testen in der Live-Anwendung.
Struktur der Simulation
In der Simulation wird das Bild Frame für Frame ausgelesen und in ein Bild vom Datentyp Mat (openCV) konvertiert. Sobald das Video zu Ende ist, beendet sich das Programm selbstständig. Die So erzeugten Einzelbilder werden in dem gemeinsamen Programmzweig weiterverarbeitet. Die Weiterverarbeitung findet hauptsächlich in den Funktionen Bildtransformation und Spurerkennung statt. In der Bildtransformation wird das Bild entzerrt, in Schwarz/Weiß gewandelt und in die Vogelperspektive transformiert. In der Spurerkennung wird die rechte Spur durch regelmäßige Punkte erfasst und daraus das Spurpolynom berechnet.
Struktur des Live-Bildes
Bei dem Live-Bild wird die Kamera einmalig initialisiert. In diesem Schritt werden die wichtigsten Parameter eingestellt und eine Verbindung hergestellt. Nach dem erstmaligen Starten der Kamera kann es bis zu zwei Minuten dauern, bis der PC eine Verbindung mit der Kamera hergestellt hat. Erst dann kann diese Initialisierung erfolgreich ausgeführt werden.
Nach der Initialisierung wird zyklisch ein neues Bild aus dem Videopuffer gelesen in ein Alpha-RGB-Bild umgewandelt, da dies mit dem Mat-Format von openCV kompatibel ist. Am Ende eines Zyklus steht, genau wie in der Simulation ein Mat-Bild zur Verfügung. Dieses wird in der Bildtransformation und Spurerkennung weiterverarbeitet.
Simulationsumgebung
In der Simulationsumgebung wird ein vorher aufgezeichnetes Videobild genutzt, um das Kamerabild zu simulieren. Dazu wird im ersten Schritt, sobald die Simulation ausgewählt wurde, der Dateipfad des Videos eingelesen. In der config.ini kann eingestellt werden, welches Video für die Simulation verwendet werden soll. Es reicht dabei lediglich den Dateinamen zu ändern, das Standard Video ist "Rundkurs.mp4" und sollte auf jeden Fall im Ordner enthalten sein. Im SVN müssen die Videos unter: https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/Software/Simulation_Bildverarbeitung_und_Spurerkennung/Videos/Rundkurs.mp4 hinterlegt sein. Falls der Dateiname in der Config.ini falsch hinterlegt ist, wird in der Konsole kurz "Ungültige Eingabe!" angezeigt, bevor dann wieder die Auswahlseite für Simulation, das Live-Bild usw. angezeigt wird. Sobald der Dateipfad zum Video richtig hinterlegt wurde, sollte diese Fehlermeldung nicht mehr erscheinen und die Simulation starten.
Anpassung der Bildausgabe durch Skalierung
In der OSE-Softwareumgebung wird das erkannte Polynom visuell in einem separaten Fenster dargestellt. Auf Laptops mit hochauflösenden Displays kann es jedoch vorkommen, dass das Ausgabe-Fenster durch die systemseitige Windows-Skalierung zu groß dargestellt wird und nicht mehr vollständig sichtbar ist.
Um dieses Problem zu lösen, wurde die Funktion BildAnzeigen() implementiert. Diese passt die Größe des angezeigten Bildes dynamisch an, indem das Bild vor der Ausgabe entsprechend skaliert wird. Der Skalierungsfaktor kann in der config.ini angepasst werden und wird dort in Prozent angegeben. Dadurch lässt sich die Anzeige flexibel auf verschiedene Bildschirmauflösungen abstimmen, ohne dass die Bildverarbeitung selbst beeinflusst wird.
Diese Erweiterung verbessert die Nutzbarkeit der OSE-Software insbesondere auf hochauflösenden Displays und ermöglicht eine individuelle Anpassung der Darstellung je nach Systemkonfiguration.
Mit der Funktion FA_InitVideo werden die Ausgabefenster der Bilder angepasst. Welche Bilder Ausgegeben werden sollen, kann ebenfalls in der Config-Datei festgelegt werden.
FL_GetFrame() liest ein neues Frame aus der Videodatei aus und speichert es in der Matrix.
Live Bild
Kamera einrichten
![](/wiki/images/thumb/e/ee/CamLab.png/300px-CamLab.png)
Um einen ersten Funktionstest der Kamera durchzuführen, wurde die Kamera über einen Ethernetkabel mit dem Laborrechner verbunden und das zugehörige Netzteil für die Stromversorgung angeschlossen. Als Netzteil wird dabei ein 5V und 4A Netzteil von Phigong verwendet.
Das VRmagic Programm zum ausgeben des Kamerabildes "CamLab" ist auf allen Laborrechnern bereits installiert.
Falls es nicht installiert sein sollte, kann das Programm von der VRmagic Homepage heruntergeladen werden:
https://www.vrmagic-imaging.com/service/downloads/usb-platform-downloads/
Der richtige Typ der Software, für den entspechenden Rechner kann unter dem Punkt "USBPlattform/Software" ausgewählt und heruntergeladen werden, siehe Bild.
Nachdem das Programm heruntergeladen wurde, muss die ZIP-Datei entpackt werden und die "Setup"-Datei ausgeführt werden. Für nähere Informationen zur Installation, ist in der ZIP-Datei eine README-Dokument enthalten.
"WICHTIG: Admin-Rechte von Nöten!!!"
Nachdem die Installation erfolgreich abgeschlossen wurde, kann das Programm "CamLab" ausgeführt werden.
Nachdem das Programm geöffnet wurde kann die VRmagic Kamera mit dem CamLab kommunizieren. Die angeschlossene Kamera kann in dem Dropdown-Menü ausgewählt werden. Dies kann nach dem ersten mal anschließen etwas dauern, bis das Programm die Ethernetverbindung zur Kamera findet. Da ruhig 1-2 Minuten warten. Im Anschluss daran kann die Bildausgabe gestartet werden.
Wenn die Kamera ausgewählt wurde, öffnet sich ein erweiteretes Menü. In diesem Menü können alle möglichen Konfigurationen vorgenommen werden, die die VRmagic Kamera anbietet (Format, Timing, Sensor, Filter etc.). Mit einem Klick auf den Button "Grab" kann die Bildwiedergabe gestartet werden. Es können auch Snapshots erstellt werden, die auf dem Rechner gespeichert werden können.
Mit diesem Programm wurde ein erster Funktionstest der Kamera durchgeführt, welcher Grundlage für weitere Ansterungskonzepte mit Visual Studio ist.
Kamera in Softwareumgebung verwenden
Im Programm werden die notwendigen Schritte zum Starten der Kamera und der Bildausgabe durchlaufen. Dabei ist es ebenfalls wichtig, dass nach einem erneuten Anschließen der Kamera 1-2 Minuten gewartet werden muss, bis die Kamera tatsächlich die Ethernet Verbindung aufgebaut hat und verbunden ist. Dann stellt das Programm die Verbindung aber her und ein Live Bild der Kamera wird angezeigt, wenn Menüpunkt 2 ausgewählt wurde.
die wichtigen Schritte, die das Programm durchläuft, bis ein OpenCV Bild entsteht, dass dann für die Bildverarbeitung und Spurerkennung weiterverwendet werden kann sind die folgenden:
- 1. Anlegen eines neues Kameradevices mithilfe von OSE_device_st = Vrm_OpenDevice();
- 2. Belichtungszeit zuweisen mithilfe von: !VRmUsbCamSetPropertyValueF(OSE_device_st, VRM_PROPID_CAM_EXPOSURE_TIME_F, &OSE_belichtungszeit_s32)
- 3. Erstellen eines Bildformates, indem die Bildgröße und das Farbformat eingestellt wird.
- 4. Das erstellte Eingabebild dem neuen Format zuweisen mithilfe von VRmUsbCamNewImage(&OSE_ARGB_EingabeBild_st, OSE_ARGB_Format_st)
- 5. In der loop werden dann Schrittweise Bilder aufgenommen mithilfe von VRmUsbCamLockNextImageEx(OSE_device_st, port, &OSE_rawQellBild_st, &OSE_bilderAufgenommen_st)
- 6. Das aufgenommene Bild wird in ein Alpha RGB Bild gewandelt mithilfe von VRmUsbCamConvertImage(OSE_rawQellBild_st, OSE_ARGB_EingabeBild_st)
- 7. Die Belichtungszeit wird dem aufgenommenen Bild zugewiesen mithilfe von VRmUsbCamGetPropertyValueF(OSE_device_st, VRM_PROPID_CAM_EXPOSURE_TIME_F, &OSE_belichtungszeit_s32)
- 8. Das VRM Color Format wird erstellt, um es im nächsten Schitt für die Umwandlung zu nutzen
- 9. Das Bild wird in ein OpenCV Bild umgewandelt mithilfe von cv::Mat OSE_srcImage_st(cvSize(OSE_ARGB_EingabeBild_st->m_image_format.m_width, OSE_ARGB_EingabeBild_st->m_image_format.m_height), toCvType(OSE_colorFormatsrc_st), (void*)OSE_ARGB_EingabeBild_st->mp_buffer, OSE_ARGB_EingabeBild_st->m_pitch);
Bildverarbeitung
Nachdem das Bild sowohl von der Kamera als auch von dem eingelesenen Video als gleiches openCV Bild im Farbschema Alpha RGB vorliegt, werden die nun erläuterten Schritte mit de Bild durchlaufen, um am Ende die drei Spurparameter a,b, und c zu erhalten.
Schritt 1: Transformation
![](/wiki/images/thumb/5/57/OSE_ROI_Fahrzeug_1.png/200px-OSE_ROI_Fahrzeug_1.png)
Die Transformation des Bildes findet in der Funktion cv::Mat BTF_ImgTransf(cv::Mat img_Mat, bool ausgabe_abit[]) statt. Diese befindet sich in der Datei Bildtransformation.cpp.
In dieser Funktion werden zunächst die intrinsischen Kameraparameter eingegeben, die mithilfe der Matlab Toolbox Camera Calibrator erstellt wurden. Dazu wurde ein Schachbrettmuster genutzt, dass in verschiedenen Perspektiven vor die Kamera gehalten wurde. Wie man an diese Parameter dann kommt ist in der Matlab Hilfe hier Camera Calibration , im Wiki Artikel Kamerakalibrierung oder im Wiki-Artikel Kalibrierung der Kamera beschrieben.
Dann erfolgt die Umwandlung des Bildes in ein Graustufenbild, was in der Funktion binarisierung(img_Mat, ausgabe_abit[2], ausgabe_abit[3]); stattfindet. Rückgabewert ist dann ein schwarz weiß Bild der Kamera in der Ursprungsgröße.
Als nächster Schritt findet die Transformation in die Vogelperspektive statt. Dazu wird das Bild zunächst vom Fischaugeneffekt durch die Funktion cv::undistort(img_Mat, KalibriertesBild_st, OSE_IntrinsicMatrix_as32, OSE_dist_s32); befreit und wird anschließend durch die Opencv Funktion cv:: warpPerspective Transformiert. Wie die Punkte zur Kalibrierung zustandekommen ist in diesem Wiki Artikel Transformation beschrieben.
Abschließend wird das Bild noch mithilfe eines Kantenerkennungsalgorithmus durch die cv::Canny(OSE_zielBild_st, OSE_filterBild_st, 100, 200, 3); Funktion in ein Kantenbild überführt, dass zurückgegeben wird.
Für die weitere Verwendung der Vogelperspektive wird nur ein bestimmter Region of Interest (ROI) benötigt. Die nebenstehende Abbildung zeigt die Lage und Größe des ROI im Fahrzeug-Koordinatensystem. Gemessen wurde vom Ursprung des Fahrzeug-KOS aus, also ohne Berücksichtigung des vorderen Bumpers (siehe auch Fahrzeughardware). Somit beträgt der Abstand zwischen ROI und Fahrzeug . Zur Umrechnung von (Bild-)Pixel (px) in mm ergeben sich folgende Faktoren:
- x-Richtung (längs):
- y-Richtung (quer):
Die ermittelten Transformations-Parameter müssen in der Funktion "KosTrafo" hinterlegt werden. Diese Funktion befindet sich in der Spurerkennung.cpp, die innerhalb der main() aufgerufen wird. Die benötigten Parameter heißen "UmrechungsfaktorX", "UmrechungsfaktorY" und "AbstandROI". Diese sind vor einer swtich-case-Anwendung deklariert und werden abhängig von der Wahl des Fahrzeuges beim Start des Programms, entsprechend initialisiert (siehe Abbildung: KosTrafo-Funktion).
Schritt 2: Spurerkennung
Die Spurerkennung erfolgt durch den Funktionsaufruf Spurerkennung, diese Funktion ist in der Datei Spurerkennung.cpp implementiert.
![](/wiki/images/thumb/4/4e/PAP_Spurerkennung.png/200px-PAP_Spurerkennung.png)
Spurerkennung(imgT, OSE_SpurparamterA_f32, OSE_SpurparamterB_f32, OSE_SpurparamterC_f32, OSE_Spurzuordnung_bit); Die Parameter sind:
- imgT: Gefiltertes Bild in der Vogelperspektive
- OSE_SpurparamterA_f32: Spurparameter A (Wird beschrieben)
- OSE_SpurparamterB_f32: Spurparameter B (Wird beschrieben)
- OSE_SpurparamterC_f32: Spurparameter C (Wird beschrieben)
- OSE_Spurzuordnung_bit: Noch keine Funktion
In der Spurerkenneung Wird im ersten Schritt ein Array für die gefundenen Punkte initialisierte. Dann wird die Funktion Berechnung Schnittpunkt Koordinaten aufgerufen. Dort werden die Koordinaten der Schnittpunkte berechnet. die Polynomberechnung erfolgt mit einer aus Matlab generierten Funktion. Deshalb muss das Array erst in einen kompatiblen Datentyp umgewandelt werden. Nach der Berechnung des Spurpolynoms wird dieses ausgegeben.
Berechnung Schnittpunkt Koordinaten
![](/wiki/images/thumb/6/69/PAP_BerechnungSchnittpunktKoordinaten.png/200px-PAP_BerechnungSchnittpunktKoordinaten.png)
Die Berechnung der Schnittpunktkoordinaten erfolgt, wie in der Abbildung dargestellt. Nachdem die Variablen initialisiert wurden, wird das aktuelle Bild durchlaufen. Dabei wird von unten nach oben zeilenweise vorgegangen. Der Abstand der Zeilen erhöht sich mit zunehmender Bildhöhe, da die näheren Punkte relevanter sind. In dieser Schleife werden als erstes die nicht gefundenen Punkte aus dem vorherigen Zyklus eingezeichnet. Das ermöglicht eine bessere Analyse der Ergebnisse. Für jede Zeile wurde ein Gate festgelegt in dem der nächste Spurpunkt zu finden ist. Dieses Gate ergibt sich aus dem letzten gefundenen Punkt.
In diesem Gate wird ein Spurpunkt mittels der Funktion Spursuchen ermittelt. In dieser Funktion werden die Punkte im Gate durchgegangen. Wird eine Wechsel von Schwarz auf Weiß detektiert, werden die weißen Pixel gezählt. Stimmen diese mit einer festgelegten Toleranz mit der Spurbreite überein, gilt die Spur als gefunden. Die letzte gefundene Spur wird als rechte Spur gespeichert. Die Abbildung Spurbreite_PAP zeigt den PAP für diese Funktion.
![](/wiki/images/thumb/b/be/Spurbreite_pap.png/600px-Spurbreite_pap.png)
Wenn kein Spurpunkt gefunden wurde, wird nichts gespeichert, aber der letzte gefundene Punkt (vorheriger Zyklus) wird für das neue Gate verwendet. Gefundene Punkte werden gespeichert und eingezeichnet. Wenn es der erste Schnittpunkt des Bildes ist, wird dieser als Startpunkt für das nächste Bild gespeichert. Die Gefundenen Schnittpunkte werden gezählt. Sobald die Arraygröße überschritten wird oder das ende des Bilds erreicht wird, wird das Suchen abgebrochen. Die Anzahl der gefundenen Punkte wird übergeben, um nur daraus das Polynom zu berechnen.
![](/wiki/images/thumb/f/f4/PAP_Spurwechsel.png/300px-PAP_Spurwechsel.png)
Erweiterung um dynamische Spurzuordnung
Damit die Spurerkennung auch während Kurven zuverlässig (zumindest) eine Spur erkennen kann, wird u.U. ein Sprung von einer Fahrbahnmarkierung zu einer anderen benötigt. Um dies zu ermöglichen wurde der im folgende erläuterte Algorithmus an das Ende der Schnittpunktberechnung implementiert.
Das Vorgehen ist recht simpel und läuft gemäß dem abgebildeten PAP ab. Mit dem ersten Funktionsaufruf wird die eine statische Variable angelegt, welche die aktuelle Spur speichert. Initial wird hier von der rechten Spur ausgegangen, da diese auch überwiegend erkannt wird.
Mit jedem Frame wird die Funktion BerechneSchnittpunkt aufgerufen. In dieser Funktion werden alle gefundenen Schnittpunkte für das Frame gesammelt und gezählt. Wird ein vorher eingestellter Schwellenwert an gefundenen Schnittpunkte in einem Frame unterschritten, wird ein statischer Counter erhöht. Wurde ausreichend viele Schnittpunkte gefunden, so wird der Counter wieder auf 0 gesetzt. Überschreitet der Counter allerdings die vorher bestimmte maximale Anzahl an erlaubten Frames mit weniger Schnittpunkten, wird ein Spurwechsel ausgelöst.
Der spur-Parameter wird also invertiert und das Gate wird neu bestimmt (es wird dabei um die Breite der Fahrbahn nach links oder rechts verschoben).
Mit dem nächsten Frame wird nun nach der gegenüberliegenden Fahrbahn gesucht. Damit auch definitiv die äußere Markierung gefunden wird wird die for Schleife zum suchen der Spur entweder von rechts nach links im Bild (für die linke Markierung) oder von links nach rechts (für die rechte Markierung) durchlaufen. Der restliche Algorithmus bleibt von dieser Änderung unbetroffen, sodass auch mit geänderter Spur die Gate-Berechnung etc. einwandfrei funktioniert.
Schritt 3: Koordinatentransformation
![](/wiki/images/thumb/0/05/SDE_Praktikum_KOS_Transformation_Konzept.png/500px-SDE_Praktikum_KOS_Transformation_Konzept.png)
Gemäß Schnittstellendokumentation muss eine Koordiantentransformation vom Kamerafesten-KOS in das Fahrzeugfeste-KOS erfolgen.
Koordinatensystem | Kamerafest | Fahrzeugfest |
---|---|---|
Index | V (Videofest) | K (Kamerafest) |
Einheit | Pixel | Millimeter |
Ursprung | Linke, obere Ecke | Mitte Vorderkante des vorderen Stoßfängers (z=0) |
X-Achse | Nach rechts | Nach vorne (in Fahrtrichtung) |
Y-Achse | Nach unten | Nach links |
Z-Achse | keine vorhanden | Nach oben |
Dafür wurde die Funktion KosTrafo(real_T xWerte[], real_T yWerte[], int& laengeArray) in die Spurerkennung.cpp implementiert, welche die X- und Y-Positionen der erkannten Spurpunkte vom Bild-KOS in das Fahrzeug-KOS umrechnet. Für einen möglichst geringen Rechenaufwand wurde eine zweidimensionale Transformationsmatrix verwendet und die festen Werte der Drehung und Spiegelung der Y-Achse eingetragen. Die Transformationsmatrix sieht wie folgt aus:
cos(90) = 0 | -sin(90) = -1 | AbstandROI+Bildlänge |
sin(90) * -1 = -1 | cos(90) = 0 | Bildbreite/2 |
0 | 0 | 1 |
Zuletzt folgt noch eine Umrechnung von Pixel in mm nach den in Schritt 1 vorgestellten Parametern.
Schritt 4: Kalman-Filter
Autor: Jan Müller
Die Implementierung des Kalman-Filters ist im folgenden Artikel beschrieben Kalman-Filterung der Spurerkennung
Schritt 5: Stopplinienerkennung
Autor: Florian Brinkmann
Die Beschreibung der Stopplinienerkennung wurde aufgrund der Komplexität in einen eigenen Artikel ausgelagert.
Hier geht es zum Artikel OSE Stopplinienerkennung
Schritt 6: Rücktransformation des gefilterten Polynoms in Bildkoordinaten
Autor: Daniel Block Im Rahmen der Spurverfolgung innerhalb der OSE-Softwareumgebung wird das erkannte Polynom zunächst von den Bildkoordinaten in das Fahrzeugkoordinatensystem überführt. In diesem System erfolgt die Verarbeitung, unter anderem durch die Anwendung eines Kalman-Filters zur Glättung und Optimierung der Spurführung. Damit das gefilterte Polynom auch visuell korrekt dargestellt werden kann, muss es anschließend wieder in das Bildkoordinatensystem zurücktransformiert werden.
Die Funktion backTransformPolynomial() übernimmt diese Rücktransformation, indem sie die ursprüngliche Transformation invers durchführt. Dabei werden die Fahrzeugkoordinaten so umgerechnet, dass das gefilterte Polynom im Bildkoordinatensystem dargestellt werden kann. Grundlage für diese Umrechnung sind fahrzeugspezifische Skalierungsfaktoren sowie ein fester Translationsvektor.
Nach der Umrechnung wird das transformierte Polynom erneut angepasst, sodass es in das bestehende Bildkoordinatensystem integriert werden kann. Diese Rücktransformation stellt sicher, dass die erkannte Spur auch nach der Filterung korrekt im Kamerabild visualisiert wird und eine präzise Überlagerung mit der realen Fahrbahnmarkierung möglich ist.
Im folgenden ist der C++ Code für die Rücktransformation gezeigt:
void backTransformPolynomial(
double a_in, double b_in, double c_in, // Fahrzeug-Polynom-Parameter
int fahrzeug_auswahl, // Fahrzeugtyp zur Paraminitialisierung
double& a_out, double& b_out, double& c_out // Output: Bild-Polynom-Parameter
)
{
static bool first = true; // Fahrzeugparameter geladen?
//Umrechnungsfaktoren, siehe Schritt 1 unter https://wiki.hshl.de/wiki/index.php/OSE_Softwareumgebung
static float UmrechnungsfaktorX;
static float UmrechnungsfaktorY;
static float AbstandROI;
// Parameter laden
if (first)
{
switch (fahrzeug_auswahl)
{
case 1:
UmrechnungsfaktorX = 1.44; // in mm/px
UmrechnungsfaktorY = 1.33; // in mm/px
AbstandROI = 430 / UmrechnungsfaktorX; // in mm
break;
case 2:
UmrechnungsfaktorX = 2.11; // in mm/px
UmrechnungsfaktorY = 1.6; // in mm/px
AbstandROI = 580 / UmrechnungsfaktorX; // in mm
break;
default:
cout << endl << "Falsche Fahrzeugauswahl" << endl;
cout << endl << "Press the enter button, to close the program" << endl;
cin.get();
exit(-1);
break;
}
first = false;
}
//Translationsvektor T = [T1, T2]
static float T1 = 1113 + AbstandROI;
static float T2 = 752 / 2;
// Bereich für x im Fahrzeugkoordinatensystem definieren (Meter)
// Dies muss an Ihren Anwendungsfall angepasst werden.
double xStart = -5.0;
double xEnd = 20.0;
int numPoints = 100;
double step = (xEnd - xStart) / (numPoints - 1);
std::vector<double> xBildWerte(numPoints), yBildWerte(numPoints);
for (int i = 0; i < numPoints; i++) {
double xFzg = xStart + i * step;
double yFzg = a_in * xFzg * xFzg + b_in * xFzg + c_in;
// Inverse Transformation:
// yBild = T1 - (xFzg / UmrX)
// xBild = T2 - (yFzg / UmrY)
double yBild = T1 - (xFzg / UmrechnungsfaktorX);
double xBild = T2 - (yFzg / UmrechnungsfaktorY);
xBildWerte[i] = xBild;
yBildWerte[i] = yBild;
}
// Nun haben wir Punkte (xBildWerte, yBildWerte) im Bildkoordinatensystem.
// Passe nun erneut ein Polynom an:
//fitPolynomial(xBildWerte, yBildWerte, a_out, b_out, c_out);
emxArray_real_T* OSE_xWerteMatlabDLL_ast;
emxArray_real_T* OSE_yWerteMatlabDLL_ast;
OSE_xWerteMatlabDLL_ast = emxCreateWrapper_real_T(&xBildWerte[0], 1, numPoints);
OSE_yWerteMatlabDLL_ast = emxCreateWrapper_real_T(&yBildWerte[0], 1, numPoints);
polynom(OSE_yWerteMatlabDLL_ast, OSE_xWerteMatlabDLL_ast, &a_out, &b_out, &c_out); //Berechnen des Spurpolynoms anhand der Matlab Funktion
}
Durch diese Rücktransformation des Polynoms ist es möglich, das Polynom im Ausgabefenster darzustellen. Die folgende Abbildung zeigt das Ausgabefenster mit dem gefilterten Polynom, welches so an die dSPACE-Karte übertragen wird.
![](/wiki/images/3/31/AnzeigeFinaleSpur.png)
Visualisierung der erkannten Spurpunkte
Autor: Daniel Block Für eine verbesserte Darstellung der erkannten Fahrbahnmarkierung werden die berechneten Spurpunkte direkt in das Bild eingezeichnet. Dies ermöglicht eine visuelle Überprüfung der detektierten Spur und erleichtert die Fehleranalyse sowie die Optimierung der Spurverfolgungsalgorithmen.
Die erkannten Punkte werden mit der OpenCV-Funktion circle() als rote Markierungen in das Bild eingezeichnet. Dabei wird für jeden gefundenen Punkt ein Kreis mit einem definierten Radius gezeichnet.
Diese Visualisierung dient nicht nur zur Debugging-Zwecken, sondern auch zur Verbesserung der Nutzerfreundlichkeit der OSE-Software, da sie eine unmittelbare Rückmeldung über die erkannten Fahrbahnmarkierungen liefert.
Die folgende Abbildung zeigt das Ausgabefenster mit eingezeichneten Spurpunkten:
![](/wiki/images/1/1b/EingezeichneteSpurpunkte.png)
Dynamische Anpassung der Region of Interest (ROI) in Kurven
In der OSE-Softwareumgebung wurde die Spurerkennung so erweitert, dass die Region of Interest (ROI) dynamisch an die Fahrsituation angepasst wird. Insbesondere in Kurven wird der ROI verkleinert, um eine präzisere Erkennung der Fahrbahn zu ermöglichen.
Funktionsweise der Anpassung
Die Anzahl der Gates für die Berechnung der Spur-Schnittpunkte wird basierend auf dem Spurparameter OSE_SpurparamterA_f32 reguliert. Dieser Wert beschreibt die Krümmung der Fahrspur.
Kurvige Streckenabschnitte: Wenn OSE_SpurparamterA_f32 größer als 0.2 ist, wird angenommen, dass sich das Fahrzeug in einer Kurve befindet. In diesem Fall wird die maximale Anzahl der Gates (maxArrayGroesse) schrittweise verringert, jedoch nicht unter einen Mindestwert von 8, um eine stabile Erkennung zu gewährleisten.
Gerade Streckenabschnitte: Wenn der Spurparameter unter 0.2 liegt, wird die Anzahl der Gates wieder schrittweise erhöht, bis der ursprüngliche Maximalwert von 13 erreicht ist. Dadurch wird sichergestellt, dass auf geraden Strecken ein weiterer Bereich für die Spurerkennung genutzt wird.
Diese Anpassung der ROI verbessert die Spurverfolgung in Kurven erheblich, da unnötige Bildbereiche ausgeschlossen und die Berechnung effizienter durchgeführt wird. Der Quellcode für diese Anpassung:
static int maxArrayGroesse = 13;
if (OSE_SpurparamterA_f32 > 0.2)
{
if (maxArrayGroesse > 8)
{
maxArrayGroesse = maxArrayGroesse - 1;
}
}
else
{
if (maxArrayGroesse < 13)
{
maxArrayGroesse = maxArrayGroesse + 1;
}
}
Programmablaufdiagramm
Das nachfolgende Programmablaufdiagramm (PAP) veranschaulicht die Funktionsweise der dynamischen Anpassung der ROI anhand der aktuellen Werte von OSE_SpurparamterA_f32 und maxArrayGroesse:
![](/wiki/images/thumb/6/6c/ROIAnpassung_pap.png/600px-ROIAnpassung_pap.png)
Diese Erweiterung sorgt für eine präzisere Spurerkennung, insbesondere in engen Kurven, und trägt zur Verbesserung der Fahrstabilität bei.
Daten senden
Im letzten Teil nach Einlesen und Verarbeiten der Daten werden diese über die RS232 Schnittstelle gesendet. Dies ist aber nicht mehr Teil unserer Arbeit sondern ist im Wiki Artikel Kommunikation zwischen PC und dSpace-Karte via RS232 beschrieben.
Testkonzept
Das SDE-Team 2021/22 hat im Rahmen des Praktikums verschiedene Testfälle entwickelt, die fortlaufend genutzt und angepasst werden. Für die OSE Softwareumgebung sind die Testfälle auf den beiden folgenden Wiki-Seiten zu finden:
- OSE: Test der Spurparameter-Ermittlung in der Simulation
- OSE: Test der Spurparameter-Ermittlung am Fahrzeug
Alle anderen Wiki-Seiten sind auf der Teamseite verlinkt.
Literatur
→ zurück zum Hauptartikel: OSE - Objekt - und Spurerkennung
→ zurück zum Hauptartikel: Praktikum SDE