diff --git a/Bachelorarbeit.pdf b/Bachelorarbeit.pdf index e5d0b05962ae5a999d9dda89b4d0b1952039a7f1..e3f956c25688d3e9281dba65d5e7577b923eba8f 100644 Binary files a/Bachelorarbeit.pdf and b/Bachelorarbeit.pdf differ diff --git a/chap/implementation.tex b/chap/implementation.tex index 5830dab184623b7991fba4fec178cd2908125bda..284cbb1ee1a183edc450b2dd85b49d7f55aed494 100644 --- a/chap/implementation.tex +++ b/chap/implementation.tex @@ -235,7 +235,7 @@ \label{fig: classified edges} \end{figure} - \subsubsection{Genauigkeit der Klassifizierung} + \subsubsection{Genauigkeit der Klassifizierung} \label{sub: genauigkeit klassifizierung} Die Klassifizierung erfolgt leider nicht immer völlig zuverlässig. Gut klassifizierte Kanten haben für die gesamte Länge der Linie dieselbe Klasse erhalten wie es im vergrößerten Bildausschnitt \autoref{fig: gute kante} zu sehen ist. Im Gegensatz dazu haben @@ -263,6 +263,93 @@ \subsection{Linienbildung} \label{sec: linien finden} + Mit den Informationen über die Kantenklasse kann nun der eigentliche Prozess der Linienerkennung erfolgen. Dieser glieder sich in zwei + Schritte, das Zusammenfassen von gleich klassifizierten Kantenpixeln zu durchgängigen Linien und das Zusammenfassen von Linien zu einer + Fahrspurmarkierung. + + Für den ersten Schritt ist es ein weiters mal nötig über das gesamte Bild zu iteriert. Auch diesmal können wieder alle schwarzen Pixel + übersprungen werden. Wird ein klassifiziertes Pixel gefunden, muss überprüft werden, ob es sich um ein Startpixel handelt. Startpixel sind + Pixel, die keine Nachbarn in der ihrer Klasse entsprechenden Ursprungsrichtung haben. Zum Beispiel wäre ein Pixel der \emph{Vertikal} + Klasse ein Startpixel, wenn sich direkt oder diagonal über ihm keine weiteren Pixel derselben Klasse befinden. + + Ist ein Startpixel gefunden, wird es für später abgespeichert. Nun wird der Linie zu ihrem Ende gefolgt. Dazu wird der nächste + Nachbarpixel gesucht. Da die grobe Richtung entsprechend der Klasse bekannt ist, müssen hier nicht alle Nachbarpixel überprüft werden. + Beim Beispiel mit der \emph{Vertikal} Klasse müssten die Pixel direkt und diagonal unterhalb betrachtet werden. Existiert ein Nachbar wird + dieser ausgewählt und der Prozess wiederholt. Dabei werden alle bereits besuchten Pixel aus dem Bild gelöscht, damit sich nicht nocheinaml + untersucht werden. + + \begin{lstlisting}[ + float, + style=example, + caption={Verfolgen einer Linie vom Start- zum Endpunkt}, + label=code: follow line, + language=Python + ] + start = (u, v) + relevant_nh *= -1 + + while True: + pixel_info[u, v] = 0 + for x, y in relevant_nh: + if e == pixel_info[u+x, v+y] & 0x0f: + u, v = u+x, v+y + break + else: # no more neighbours + break + + l = Line(start, (u, v), info) + if l.length > 5: + lines.append(l) + \end{lstlisting} + + Hat ein Pixel keine weiteren Nachbarn, ist er der Endpunkt dieser Linie. Start und Endpunkt werden in ein Linienobjekt zusammengefasst + und abgespeichert. Zusätzliche wird ebenfalls die Orientierungsklasse mit abgespeichert. + + Mittels Start- und Endpunkt kann außerdem die Länge der Linie bestimmt werden. Da durch die in \autoref{sub: genauigkeit klassifizierung} + beschriebenen Störungen viele kurze Linien gefunden werden, deren Berücksichtigung zu viel Rechenzeit in Anspruch nehmen würde, werden + Linien unter einer Minimallänge von 5 Pixeln vernachlässigt. + + Akzeptierte Linien werden ihrer Orientierung entsprechen in einzelnen Listen abgespeichert, sodass am Ende eine Liste für jede + Orientierungsklasse entstanden ist. + + \medskip + Da ein Linienmarker immer aus einer linken und einer rechten Kante besteht, können wir diese durch Bilden von Linienpaaren gleicher + Orientierung, aber unterschiedlichem Vorzeichen, die in geringem Abstand zueinander liegen, identifizieren. + + Dazu werden die Elemente der entsprechenden Listen nacheinander miteinander verglichen, biss ein passendes Paar gefunden wurde. Ein + Beispiel ist in \autoref{code: find pairs} für Linienmarkierungen der Orientierung \emph{Digital 1} gezeigt. Es wird für jeden Kandidaten + aus der ersten Liste ein Partner in der zweiten Liste gesucht. Ein solcher ist gefunden, wenn die Start- und Endpunkte beider Linien + innerhalb bestimmter Bereiche liegen. + + + \begin{lstlisting}[ + float, + style=example, + caption={Finden von Linienpaaren in Python}, + label=code: find pairs, + language=Python + ] + for a in left_D1_edges: + for b in right_D1_edges: + if ( + (a.start[0] - 20) < b.start[0] < (a.start[0] + 20) and + a.start[1] < b.start[1] < (a.start[1] + 30) and + (a.end[0] - 20) < b.end[0] < (a.end[0] + 20) and + a.end[1] < b.end[1] < (a.end[1] + 20) + ): + markings_found.append(LineMarking(a,b, "left")) + right_D1_edges.remove(b) + break + \end{lstlisting} + + Die gefundenen Linienpaare werden zu einem Linienmarker Objekt zusammengefasst. In diesem wird der Umriss bestehend aus den vier + Linienpunkten abgespeichert. Außerdem wird der Mittelwert der beiden Start- und Endpunkte gebildet und somit die Mittellinie des + Linienmarkers angenähert. + + So gefundene Linienmarker lassen sich wieder im Beispielbild markieren, wodurch sich \autoref{fig: found markings} ergibt. Wie man dort + sehen kann, wurden die Linienmarker der eigenen linken und rechten Fahrspurbegrenzung erfolgreich identifiziert. Weitere Markierungen + anderer Spuren konnten aufgrund der unzuverlässigen Klassifizierung nicht erkannt werden. + \begin{figure} \includegraphics[width=.6\textwidth]{img/Marks_found-lines.png} \caption{Umrisse und Mittellinien der gefundenen Fahrspurmarkierungen} @@ -270,9 +357,38 @@ \end{figure} - \subsection{Performance Betrachtung} + \subsubsection{Komplexere Szenen} + + Nicht jede Situation, auf die der Roboter treffen kann, führt zu so guten Ergebnissen wie das gezeigte Beispiel. Daher sind in + \autoref{fig: vergleich szenen} einige weitere Beispiele und die darin detektireten Markierungen im direkten Vergleich gezeigt. - sehr schlecht offensichtlich... + In \ref{subfig: demo C} sind die Linienbegrenzungen nahe am Fahrzeug durchgezogen und werden erst in größerer Entfernung gestrichelt. + Hier war die Erkennung der durchgezogenen Teile sehr gut möglich, jedoch kam es zu einer unpräzisen Identifizierung im oberen Teil der + rechten Linie, da sich zwei Liniensegmente unterschiedlicher Linien zu nahe aneinander befanden. + + Bei der Szene \ref{subfig: demo A} handelt es sich um eine Kurve. Dies erschwert die Erkennung deutlich, da eine durchgängige + Klassifizierung einer Kante nicht garantiert ist. Daher sind auch nicht alle Spurmarkierungen identifiziert. + + Der letzte Vergleich \ref{subfig: demo B} zeigt eine Szene mit vollständig durchgezogener Linie. Dies ist aus dem Grund schwierig, das + die Wahrscheinlichkeit einer Störung durch die hohe Pixelanzahl sehr groß ist. Daher wurde die rechte Kante der Linie auch nicht + durchgängig erkannt und der gefunden Marker wirkt verzehrt. + + \begin{figure} + \subfigure[lange Linien]{ \label{subfig: demo C} + \includegraphics[width=.23\textwidth]{img/demo_org_C.png} + \includegraphics[width=.23\textwidth]{img/demo_found_C.png} + } + \subfigure[leichte Kurve]{ \label{subfig: demo A} + \includegraphics[width=.23\textwidth]{img/demo_org_A.png} + \includegraphics[width=.23\textwidth]{img/demo_found_A.png} + } + \subfigure[durchgezogene Linie]{ \label{subfig: demo B} + \includegraphics[width=.23\textwidth]{img/demo_org_B.png} + \includegraphics[width=.23\textwidth]{img/demo_found_B.png} + } + \caption{Ergebnisse bei komplexeren Szenen im Vergleich} + \label{fig: vergleich szenen} + \end{figure} \section{Implementierung in eine ROS Node} diff --git a/img/Marks_found-lines.png b/img/Marks_found-lines.png new file mode 100644 index 0000000000000000000000000000000000000000..3f9b1b7710cfab27d79029bd224924b59fdbf562 Binary files /dev/null and b/img/Marks_found-lines.png differ diff --git a/img/demo_found_A.png b/img/demo_found_A.png new file mode 100644 index 0000000000000000000000000000000000000000..50fd639083331b817e9fdc3272e3fc9e2b42bb72 Binary files /dev/null and b/img/demo_found_A.png differ diff --git a/img/demo_found_B.png b/img/demo_found_B.png new file mode 100644 index 0000000000000000000000000000000000000000..f5e5722c366800e96d08d3bdc9a598f00ab96f00 Binary files /dev/null and b/img/demo_found_B.png differ diff --git a/img/demo_found_C.png b/img/demo_found_C.png new file mode 100644 index 0000000000000000000000000000000000000000..444822d7f93fc1354d3a90b30eeeb1aae4c68847 Binary files /dev/null and b/img/demo_found_C.png differ diff --git a/img/demo_org_A.png b/img/demo_org_A.png new file mode 100644 index 0000000000000000000000000000000000000000..d002ed2cbced7e4e06b6d2dc7339dbb2a92e983b Binary files /dev/null and b/img/demo_org_A.png differ diff --git a/img/demo_org_B.png b/img/demo_org_B.png new file mode 100644 index 0000000000000000000000000000000000000000..033b901fa001d3dd79270b238a84f26ebab7b718 Binary files /dev/null and b/img/demo_org_B.png differ diff --git a/img/demo_org_C.png b/img/demo_org_C.png new file mode 100644 index 0000000000000000000000000000000000000000..28b331b2ad4bf1f7a907b045c0f2809cb2815c63 Binary files /dev/null and b/img/demo_org_C.png differ