diff --git a/Bachelorarbeit.pdf b/Bachelorarbeit.pdf index 08298ac95505839acf1a9e5b9770dadd6dba0de1..d0cc3b20272279f48d078e588db33bf94c1369ee 100644 Binary files a/Bachelorarbeit.pdf and b/Bachelorarbeit.pdf differ diff --git "a/bib/Glossareintr\303\244ge.tex" "b/bib/Glossareintr\303\244ge.tex" index f908152eda79af2f181f799e528a5e65f31fc95d..68b430cde6b8fbcb7faa1bb515aef752a634ae8d 100644 --- "a/bib/Glossareintr\303\244ge.tex" +++ "b/bib/Glossareintr\303\244ge.tex" @@ -178,3 +178,20 @@ Ein Bereich festgelegter Größe um einen relevanten Hauptpixel. } } + +\newglossaryentry{CPU}{ + name={CPU (\emph{Central Processing Unit})}, + text={CPU}, + sort={CPU}, + description={Die zentrale Recheneinheit eines Computers. Hier werden alle Programme abgearbeitet und alle Berechnungen durchgeführt.} +} + +\newglossaryentry{GPU}{ + name={GPU (\emph{Graphics Processing Unit})}, + text={GPU}, + sort={GPU}, + description={ + Eine spezialisierte Recheneinheit eines Computers zur Grafikverarbeitung. Sie ist speziallisiert darauf viel kleine Berechnungen + parallel auszuführen. + } +} diff --git a/chap/ausblick.tex b/chap/ausblick.tex index dbf254653f8df8455f8b3da33f46bfdd638c874d..4c2593df5e202134c44fb3f6125463daa64135b8 100644 --- a/chap/ausblick.tex +++ b/chap/ausblick.tex @@ -17,7 +17,7 @@ Derzeit werden vor allem bei weiter von der Kamera entfernten Linien, also vor allem den Spurmarkierungen benachbarter Spuren, viele \gls{Pixel} fehlklassifiziert. Wie in \autoref{fig: schlechte kante} gezeigt, wird eine Kante durch solche \gls{Pixel} unterbrochen und eine - durchgängige Linienverfolgung nicht möglich ist. + durchgängige Linienverfolgung ist nicht möglich. Hier könnten zuerst einmal Ansätze zum Verbinden von sehr eng zusammenliegenden Linien Abhilfe schaffen. Aber eine Verbesserung der Genauigkeit bei der Klassifizierung wäre ebenfalls denkbar, vor allem da dies bereits teilweise durch den vorherigen Punkt mit abgedeckt ist. diff --git a/chap/einleitung.tex b/chap/einleitung.tex index 6d31a6a547a5792e2aa350edeca654b9bd5fde25..da9036565c699a6cf9a9cd5c091ecdd1bdde14e7 100644 --- a/chap/einleitung.tex +++ b/chap/einleitung.tex @@ -21,7 +21,7 @@ unterscheiden. Gegebenenfalls kann auch das zeitliche Tracking eines Spurmodells umgesetzt werden. - Die Bildverarbeitung sollte auf der Jetson-nano Hardware unter \gls{ROS} in Echtzeit lauffähig sein. Eine erste + Die Bildverarbeitung sollte auf der Jetson Nano Hardware unter \gls{ROS} in Echtzeit lauffähig sein. Eine erste Implementierung kann mit Python erfolgen. Für den längerfristigen Einsatz wäre eine Umsetzung in \gls{C++} mit \glspl{ROS Nodelet} wünschenswert. diff --git a/chap/implementation.tex b/chap/implementation.tex index 2cbb38264ecd50107084ec19aefdaf27d440aac5..b59e49fb2ae148064665adf448d8b9c3f3af1cf0 100644 --- a/chap/implementation.tex +++ b/chap/implementation.tex @@ -19,7 +19,7 @@ Die Entwicklung und Konzeptionierung des Algorithmus erfolgt in \gls{python}. Diese Sprache muss nicht kompiliert werden und hat eine einfache Syntax, wodurch das Testen beschleunigt wird und sie generell einfacher zu verwenden ist. - Der Algorithmus lässt sich in mehrere Einzelschritte aufteilen, welche in den folgenden Unterkapiteln beschreiben im Einzelnen beschrieben + Der Algorithmus lässt sich in mehrere Einzelschritte aufteilen, welche in den folgenden Unterkapiteln im Einzelnen beschrieben sind. Zur Übersicht ist aber der gesamte Ablauf in \autoref{fig: PAP} skizziert. Angefangen wird dort mit dem Erhalten des Bildes, womit sowohl manuelles Laden eines Beispiel-Bildes, als auch das Erhalten des Bildes über ein \gls{Topic} gemeint ist. @@ -49,12 +49,12 @@ $\sigma=1,5$ verwendet. \gls{OpenCV} stellt hierzu die Funktion \lstinline{GaussianBlur()} zur Verfügung, der das geladene Bild, die Kernelgröße und der Wert für $\sigma$ übergeben wird. - Die eigentliche Kantenerkennung wird mittels eines \glspl{canny} durchgeführt. Dabei handelt es sich um einen von John Canny 19983 - entwickelten und in \cite{Canny:computationAlapproachEdgeDetection} veröffentlichten Algorithmus. Dieser bestimmt für jeden \gls{Pixel} den - Gradientenbetrag in $x$ und $y$-Richtung. Dann werden diejenigen \gls{Pixel} unterdrückt, welche entlang der Gradientenrichtung kein - Maximum darstellen. Zum Abschluss wird das Bild mit einem Hysterese-Schwellwert binarisiert. Das bedeutet, dass alle \gls{Pixel} über einem - initialen, oberen Schwellwert als Kanten gesetzt werden und mittels eines zweiten, niedrigeren Schwellwerts, Lücken zwischen diesen Pixeln - geschlossen werden. \cite{Nischwitz:Computergrafik2} + Die eigentliche Kantenerkennung wird mittels eines \glspl{canny} durchgeführt. Dabei handelt es sich um einen von John Canny 1983 + entwickelten und in \cite{Canny:computationAlapproachEdgeDetection} veröffentlichten Algorithmus. Dieser bestimmt für jeden \gls{Pixel} + den Gradientenbetrag in $x$ und $y$-Richtung. Dann werden diejenigen \gls{Pixel} unterdrückt, welche entlang der Gradientenrichtung kein + Maximum darstellen. Zum Abschluss wird das Bild mit einem Hysterese-Schwellwert binarisiert. Das bedeutet, dass alle \gls{Pixel} über + einem initialen, oberen Schwellwert als Kanten gesetzt werden und mittels eines zweiten, niedrigeren Schwellwerts, Lücken zwischen diesen + Pixeln geschlossen werden. \cite{Nischwitz:Computergrafik2} Auch dieser Algorithmus ist in \gls{OpenCV} bereits implementiert und wird für den ersten Entwurf verwendet. Die Funktion bekommt das geladene und geglättete Bild sowie die beiden Hysterese-Schwellwerte übergeben. Diese ist auch in \autoref{code: canny} gezeigt. @@ -173,7 +173,7 @@ \end{equation} Dazu werden zuerst die Gradienten $d_x$ und $d_y$ ermittelt. Die $3\!\times\!3$ \gls{Pixelnachbarschaft} des aktuellen Pixels wird dabei - elementweise mit dem jeweiligen Sobel-\gls{Kernel} multipliziert und die Summe der Ergebnismatrix gebildet (siehe \autoref{eq: dx dy}). + elementweise mit dem Sobel-\gls{Kernel} multipliziert und die Summe der Ergebnismatrix gebildet (siehe \autoref{eq: dx dy}). Das Pythonpaket \lstinline{numpy} stellt hierfür sehr hilfreiche Funktion zum Arbeiten mit Matrizen zur Verfügung. Dadurch lässt sich diese Operation in wenigen Zeilen durchführen, wie \autoref{code: dx dy} zeigt. @@ -237,7 +237,7 @@ \subsubsection{Genauigkeit der Klassifizierung} \label{sub: genauigkeit klassifizierung} Die Klassifizierung erfolgt 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 + dieselbe Klasse erhalten, wie es im vergrößerten Bildausschnitt in \autoref{fig: gute kante} zu sehen ist. Im Gegensatz dazu haben unzuverlässig klassifizierte Kanten mehrere Klassen in einem engen Bereich und wechseln häufig sogar mehrfach zwischen mehreren Klassen, wie das Beispiel in \autoref{fig: schlechte kante} zeigt. @@ -310,8 +310,8 @@ 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 entsprechend in einzelnen Listen abgespeichert, sodass am Ende eine Liste für jede - Orientierungsklasse entstanden ist. + Akzeptierte Linien werden ihrer Orientierung entsprechend in einzelnen Listen abgespeichert, sodass für jede + Orientierungsklasse eine Liste entsteht. \medskip Da ein Linienmarker immer aus einer linken und einer rechten Kante besteht, kann dieser durch Bilden von Linienpaaren gleicher @@ -342,7 +342,7 @@ break \end{lstlisting} - Die gefundenen Linienpaare werden zu einem Linienmarker Objekt zusammengefasst. In diesem wird der Umriss bestehend aus den vier + 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. @@ -368,10 +368,10 @@ 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. + Klassifizierung einer Kante nicht garantiert ist. Daher sind 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, - dass die Wahrscheinlichkeit einer Störung durch die hohe Pixelanzahl sehr groß ist. Daher wurde die rechte Kante der Linie auch nicht + dass die Wahrscheinlichkeit einer Störung durch die hohe Pixelanzahl sehr groß ist. Daher wurde die rechte Kante der Linie nicht durchgängig erkannt und der gefundenen Marker wirkt verzehrt. \begin{figure} @@ -407,7 +407,7 @@ Beim Abonnieren des \lstinline{/img/gray} Topics wird die \gls{Callback} \lstinline{callback_image()} angehängt, sodass diese von \gls{ROS} für jedes Bild aufgerufen und das Bild an sie übergeben wird. Da dieses in einem \gls{ROS} eigenen Bild-Datentyp übergeben wird, \gls{OpenCV} - diesen aber nicht verwenden kann, ist es nötig das Bild zuerst einmal in einen anderen Datentyp umzuwandeln. Hierzu wird wieder das ROS-Paket + diesen aber nicht verwenden kann, ist es nötig das Bild zuerst in einen anderen Datentyp umzuwandeln. Hierzu wird wieder das ROS-Paket \lstinline{cv_bridge} und dessen Funktion \lstinline{toCvCopy()} verwendet. @@ -452,7 +452,7 @@ \pagebreak Mittels Sobel die Gradienten zu bestimmen, wirkt in \gls{C++} deutlich komplizierter, da hier vieles manuell gemacht werden muss, was in - \gls{python} von \lstinline{numpy} erledigt wurde. Mit zwei For-Schleifen wird über die $3\!\times\!2$ \gls{Pixelnachbarschaft} iteriert, die + \gls{python} von \lstinline{numpy} erledigt wurde. Mit zwei For-Schleifen wird über die $3\!\times\!3$ \gls{Pixelnachbarschaft} iteriert, die Elemente mit dem \gls{Kernel} multipliziert und aufsummiert, wie in \autoref{code: sobel c++} zu sehen. \begin{lstlisting}[ @@ -474,8 +474,8 @@ \end{lstlisting} Die eigentliche Klassifizierung ist praktisch identisch zur \gls{python}-Version. Lediglich die Überprüfung der Winkelbereiche ist etwas - langwieriger, da nicht wie in \gls{python} auf einen Wertebereich überprüft werden kann. Die Codierung der Klassen Erfolg wieder über die - einzelnen Bit des Bytes der einzelnen Pixel. Die Umsetzung ist in \autoref{code: klassen c++} dargestellt. + langwieriger, da nicht wie in \gls{python} auf einen Wertebereich überprüft werden kann. Die Codierung der Klassen erfolg wieder über die + einzelnen Bits des Bytes der einzelnen Pixel. Die Umsetzung ist in \autoref{code: klassen c++} dargestellt. \begin{lstlisting}[ float, @@ -609,7 +609,7 @@ \subsubsection{Paarbildung} - Auch die Bildung von Linienpaaren aus einer rechten und linken Linie erfolgt analog zu \gls{python}. Hier gibt es auch keine signifikanten + Die Bildung von Linienpaaren aus einer rechten und linken Linie erfolgt analog zu \gls{python}. Hier gibt es ebenfalls keine signifikanten Unterschiede in der Umsetzung, wie in \autoref{code: pairing c++} zu sehen ist. Auch hier wird mit den gefundenen Paaren wieder ein Linienmarker-Objekt erzeugt und zur oberen Nutzung abgespeichert. @@ -617,7 +617,7 @@ \begin{lstlisting}[ float, style=example, - caption={Linie verfolgen, bis keine Nachbarn mehr existieren}, + caption={Paaren von Linien gleicher Orientierungsklasse und geringem Abstand}, label=code: pairing c++, language=C++ ] @@ -652,15 +652,15 @@ \begin{figure} \includegraphics[width=.75\textwidth, trim={0 0 12px 31px}, clip]{img/jtop_cameraUndistortDetection.png} - \caption{CPU Auslastung des JetBots mit laufender Kamera, Entzerrung und Markierungserkennung} + \caption{\gls{CPU}-Auslastung des JetBots mit laufender Kamera, Entzerrung und Markierungserkennung} \label{fig: jtop markings} \end{figure} - Ein Screenshot von \lstinline{jtop} ist in \autoref{fig: jtop markings} abgebildet. Mit der zusätzlichen neuen \gls{ROS Node} ist die CPU - Auslastung nur geringfügig auf ca. $37,5\,\percent$ gestiegen, auch dies ist dank starker Fluktuation in der CPU Nutzung praktisch - vernachlässigbar. + Ein Screenshot von \lstinline{jtop} ist in \autoref{fig: jtop markings} abgebildet. Mit der zusätzlichen neuen \gls{ROS Node} ist die + \gls{CPU} Auslastung nur geringfügig auf ca. $37,5\,\percent$ gestiegen, auch dies ist aufgrund starker Fluktuation in der + \gls{CPU}-Nutzung praktisch vernachlässigbar. - Die Laufzeit-Performance der \gls{C++} implementiert ist wie erwartet deutlich besser als bei der \gls{python}-Version. Vom Erhalt des + Die Laufzeit-Performance der \gls{C++} Implementierung ist wie erwartet deutlich besser als bei der \gls{python}-Version. Vom Erhalt des Bildes bis zur Veröffentlichung des Ergebnisses mit den gefundenen Linienmarkierungen dauert es $\approx 3,46\,\ms$. \begin{table} @@ -815,16 +815,16 @@ \subsection{Performance Betrachtung} Die wichtigste Frage ist nun, wie sich diese Implementierung im Gegensatz zum Ansatz mit \gls{OpenCV} verhält. Dazu wurden wieder die - CPU-Auslastung mittels \lstinline{jtop} erfasst und die Durchlaufzeit des Algorithmus für jedes Bild gemessen. + \gls{CPU}-Auslastung mittels \lstinline{jtop} erfasst und die Durchlaufzeit des Algorithmus für jedes Bild gemessen. \begin{figure} \includegraphics[width=.75\textwidth, trim={0 0 12px 31px}, clip]{img/jtop_cameraUndistortDetection_own.png} - \caption{CPU Auslastung des JetBots mit laufender Kamera, Entzerrung und Markierungserkennung mit eigener Implementierung} + \caption{\gls{CPU}-Auslastung des JetBots mit laufender Kamera, Entzerrung und Markierungserkennung mit eigener Implementierung} \label{fig: jtop markings own} \end{figure} - Wie aus \autoref{fig: jtop markings own} abzulesen ist, ist die CPU-Auslastung mit durchschnittlichen $37.75\,\percent$ exakt identisch - zur Implementierung mit \gls{OpenCV}. Das ist wenig überraschend, da der Algorithmus Grunde immer noch dieselbe Arbeit verrichtet. + Wie aus \autoref{fig: jtop markings own} abzulesen ist, ist die \gls{CPU}-Auslastung mit durchschnittlichen $37.75\,\percent$ exakt identisch + zur Implementierung mit \gls{OpenCV}. Das ist wenig überraschend, da der Algorithmus im Grunde immer noch dieselbe Arbeit verrichtet. \pagebreak[3] Die Messung der Laufzeit zeigt allerdings, dass die eigene Implementierung deutlich weniger performant ist. Mit einer Durchlaufzeit von diff --git a/chap/kalibrierung.tex b/chap/kalibrierung.tex index 304fc9eeb622043d7244cbb07d4d68ca6ac3996c..325a314c0efdf24a4f6359210feef83c9c49fb20 100644 --- a/chap/kalibrierung.tex +++ b/chap/kalibrierung.tex @@ -35,7 +35,7 @@ \end{figure} Mathematisch lässt dich die Veränderung eines Punktes durch die Verzerrung wie in \autoref{eq: radiale verzerrung} beschrieben berechnen. - Dabei beschreiben $x$ und $y$ die unverzerrten Pixelkoordinaten, $k_1$, $k_3$ und $k_3$ die Verzerrungs-Koeffizienten. + Dabei beschreiben $x$ und $y$ die unverzerrten Pixelkoordinaten, $k_1$, $k_2$ und $k_3$ die Verzerrungs-Koeffizienten. Theoretisch existieren noch weitere Koeffizienten, aber in der Praxis haben sich die ersten drei als ausreichend herausgestellt. \cite{Hanning:highPrecisionCamCalibration} @@ -409,20 +409,20 @@ Da diese \gls{ROS Node} eine Grundlagenfunktion darstellt und parallel zu jeder anderen Anwendung laufen muss, ist es wichtig, dass sie möglichst performant ist und wenig Ressourcen des JetBots verbraucht. - Daher wurde die mittlere CPU Auslastung und die durchschnittliche Laufzeit der \glslink{Callback}{Call\-back-Funk\-tion}, welche für + Daher wurde die mittlere \gls{CPU}-Auslastung und die durchschnittliche Laufzeit der \glslink{Callback}{Call\-back-Funk\-tion}, welche für jedes Bild durchlaufen wird, gemessen. \begin{figure} \includegraphics[width=.75\textwidth, trim={0 0 12px 31px}, clip]{img/jtop_cameraUndistort.png} - \caption{CPU Auslastung des JetBots mit laufender Kamera und Entzerrer-\gls{ROS Node}} + \caption{\gls{CPU}-Auslastung des JetBots mit laufender Kamera und Entzerrer-\gls{ROS Node}} \label{fig: jtop cam+undist} \end{figure} - Der \lstinline{jtop} Screenshot in \autoref{fig: jtop cam+undist} zeigt die CPU Nutzung bei aktivem ROS-Core, Kamera-Treiber und der - neu erstellten Entzerrer-\gls{ROS Node}. Die durchschnittliche CPU-Auslastung liegt bei ungefähr $35,25\,\percent$, ist also sogar + Der \lstinline{jtop} Screenshot in \autoref{fig: jtop cam+undist} zeigt die \gls{CPU}-Nutzung bei aktivem ROS-Core, Kamera-Treiber und der + neu erstellten Entzerrer-\gls{ROS Node}. Die durchschnittliche \gls{CPU}-Auslastung liegt bei ungefähr $35,25\,\percent$, ist also sogar sehr geringfügig niedriger als die in \autoref{sub: performance baseline} gemessene Grundauslastung ohne die neue \gls{ROS Node}. Das - ist aber auf die starke Fluktuation in der CPU-Auslastung und die daher ungenauen Messung zurückzuführen. Die Auslastung wird daher - als identisch betrachtete. + ist aber auf die starke Fluktuation in der \gls{CPU}-Auslastung und die daher ungenaue Messung zurückzuführen. Die Auslastung wird daher + als identisch betrachtet. Um die Laufzeit der \gls{ROS Node} zu bestimmen, wird die aktuelle Zeit, wie sie von der Funktion \lstinline{ros::Time::now()} zurückgegeben wird, verwendet. Die Zeit beim Start der \gls{Callback} wird abgespeichert. Nach Durchlauf der Funktion wird erneut die diff --git a/chap/standdertechnik.tex b/chap/standdertechnik.tex index c68ece4235f9fe411767986e0759645d60b4aca2..c3a4fd754ec225b7286cd7ab158806f9797b3caf 100644 --- a/chap/standdertechnik.tex +++ b/chap/standdertechnik.tex @@ -70,7 +70,7 @@ Diese Netzwerke können mittels eines großen Datensatzes an Bildern trainiert werden, um unter unterschiedlichsten, unvorhersehbaren Bedingungen noch Ergebnisse zu erhalten. Dabei gilt, je größer und vielfältiger der Trainingsdatensatz, umso wahrscheinlicher erzielt das trainierte Netzwerk gute Ergebnisse. \cite{survey:deepLeraningInLanemarkerdetection} vergleicht frei verfügbare Datensätze und liefert - eine Übersicht für welche Anwendungen diese sich eigen. + eine Übersicht für welche Anwendungen diese sich eignen. Der generelle Detektierungsablauf ist auch bei Deep-Learning-Methoden der in \autoref{fig: genersich} dargestellte. Je nach Methode und Netzwerk können aber mehrere Schritte vom selben Netzwerk erledigt oder mehrere Netzwerke für die einzelnen Schritte verwendet werden. @@ -87,12 +87,12 @@ \medskip Ein großer Nachteil aller Deep-Learning-Methoden ist die benötigen hohe Rechenleistung. Bereist das Training der Netzwerke erfordert einen existierenden, ausreichen großen Datensatz und viel Zeit und Rechenleitung. Aber auch zur Nutzung der fertig trainierten Netzwerkes ist - wieder einiges an Rechenleitung notwendig. Hier kann zwar die GPU zu Hilfe genommen werden, es ist aber ein Nachteil gegenüber den + wieder einiges an Rechenleitung notwendig. Hier kann zwar die \gls{GPU} zu Hilfe genommen werden, es ist aber ein Nachteil gegenüber den traditionellen Ansätzen. Dies ist insbesondere für den Anwendungsfall dieser Arbeit ein Problem. Die Ressourcen des JetBots sollen so wenig wie möglich belastet werden, damit dieses mit weiten Anwendungen geteilt werden können. Da einige potenzielle Anwendungen auf die Verwendung von Neuralen - Netzen angewehten sind, ist insbesondere die GPU sehr sparsam zu benutzen. + Netzen angewiesen sind, ist insbesondere die \gls{GPU} sehr sparsam zu benutzen. Daher ist für diese Arbeit die Verwendung von Deep-Learning nicht sinnvoll und findet keine Anwendung. @@ -104,11 +104,11 @@ Objekterkennung, Bewegungserkennung und 3D-Modell Extraktion erstellt werden können. Daher ist sie eine der Standardbibliotheken, wenn es um digitale Bildverarbeitung geht und wird fast immer zur Demonstration neuer Konzepte benutzt. Da sie sowohl in C/\gls{C++}, Java und Python genutzt werden kann, ist sie außerdem sehr vielseitig und hat den Vorteil, dass Konzepte in einer abstrakten Sprache wie \gls{python} getestet - werden und später relativ simpel in eine hardwarenahe Programmiersprache übersetzt werden können. Weitere Informationen sind in der + werden und später ohne große Probleme in eine hardwarenahe Programmiersprache übersetzt werden können. Weitere Informationen sind in der Dokumentation des Projektes \cite{OpenCV:homepage} zu finden. - In dieser Arbeit wird diese Bibliothek daher insbesondere für die Entwicklungsphase verwendet. Da der Bibliothekscode jedoch auch viele - potenziell nicht benötigte Zusatzfunktionen mit bring, wird auch ein Wechsel auf eine eigene Implementierung mit besserer Performance in + In dieser Arbeit wird diese Bibliothek daher insbesondere für die Entwicklungsphase verwendet. Da der Bibliothekscode jedoch auch viele, + potenziell nicht benötigte, Zusatzfunktionen mit bringt, wird auch ein Wechsel auf eine eigene Implementierung mit besserer Performance in Betracht gezogen. @@ -116,7 +116,7 @@ Das \glslink{ROS}{Robot Operating System} (kurz: ROS) ist eine Sammlung von Software Bibliotheken und Werkzeugen, die zum Erstellen von Roboter Applikationen dienen. Es bietet eine eigene Paketverwaltung über die bestehende Bibliotheksfunktionen für die Verwendung - heruntergeladen werden können. Dabei handelte es sich um verschiedenste Anwendungen, angefangen Treibern, über fertige, direkt anwendbare + heruntergeladen werden können. Dabei handelte es sich um verschiedenste Anwendungen, angefangen bei Treibern, über fertige, direkt anwendbare Algorithmen, bis zu nutzernahen Steueroberflächen und sogar (Lern-)Spiele. Die Webseite des Projektes \cite{ROS:homepage} bietet hierzu weitere Informationen. Außerdem bietet \gls{ROS} Integrationen mit anderen bestehenden Projekten, wie zum Beispiel \gls{OpenCV}. @@ -127,7 +127,7 @@ \medskip Für diese Arbeit ist \gls{ROS} deshalb interessant, da sich die Ergebnisse so modular an potenzielle weitere Prozesse weitergeben lassen. Dies - wird durch \gls{ROS}\todo{ROS's ??} Fähigkeit möglich, Einzelprozesse als sogenannte \glslink{ROS Node}{ROS Nodes} zu erstellen. Jede + wird durch \gls{ROS} Fähigkeit möglich, Einzelprozesse als sogenannte \glslink{ROS Node}{ROS Nodes} zu erstellen. Jede \gls{ROS Node} kann eigene Informationen als sogenannte \glspl{Topic} veröffentlichen und andere, parallel laufende \glspl{ROS Node} können diese abonnieren. @@ -141,16 +141,16 @@ \section{Der JetBot Roboter} \label{sec: JetBot} - Beim in für diese Arbeit verwendeten Roboter handelt es sich um einen JetBot v2.1 von der Firma Sparkfun. Im Folgenden werden seine + Bei dem in dieser Arbeit verendeten Roboter handelt es sich um einen JetBot v2.1 von der Firma Sparkfun. Im Folgenden werden seine Komponenten und Einsatzmöglichkeiten für diese Arbeit näher beschrieben. - Der Roboter verwendet das von Nvidia produzierte Jetson Nano Entwicklerboard \cite{jetson-nano:homepage}. Hierbei handlet es sich um einen + Der Roboter verwendet das von Nvidia produzierte Jetson Nano Entwicklerboard \cite{jetson-nano:homepage}. Hierbei handelt es sich um einen Mini-Computer der speziell für Bildverarbeitung und Selbstlehrende Algorithmen entwickelt wurde. Es verfügt über einen 4-Kern ARM Prozessor - als CPU sowie, neben herkömmlichen Anschlüssen für PC-Peripherie, über Anschlüsse für 2 Kameras und mehre GPIO Pins. Dadurch eignet es sich - bereits sehr gut für eingebettet Anwendungen. + als \gls{CPU} sowie, neben herkömmlichen Anschlüssen für PC-Peripherie, über Anschlüsse für 2 Kameras und mehre GPIO Pins. Dadurch eignet es + sich bereits sehr gut für eingebettete Anwendungen. Was dieses Board für die Anwendung in der Bildverarbeitung aber besonders interessant mach, ist die integrierte, für die Größe leistungsstarke - GPU. Diese kann für grafikintensive Anwendungen, aber vor allem für das Arbeiten mit Neuralen Netzen genutzt werden. Da für diese Arbeit + \gls{GPU}. Diese kann für grafikintensive Anwendungen, aber vor allem für das Arbeiten mit Neuralen Netzen genutzt werden. Da für diese Arbeit explizit nicht mit Deep Learning gearbeitet wird, um diese Ressourcen für spätere Weiterentwicklung freizuhalten, ist dieses Feature aber hier uninteressant. @@ -184,26 +184,26 @@ \begin{figure} \includegraphics[width=.75\textwidth, trim={0 0 12px 31px}, clip]{img/jtop_baseline.png} - \caption{CPU Auslastung des JetBots ohne \gls{ROS}} + \caption{\gls{CPU}-Auslastung des JetBots ohne \gls{ROS}} \label{fig: jtop baseline} \end{figure} - Da alle in dieser Arbeit entwickelten Programme lediglich die CPU benutzen, ist dies der einzige relevante Messwerte. Trotze sind die - anderen Werte interessant und werden mit dokumentiert. Wie man im Screenshot sieht, ist das System in diesem Fall kaum belastet. Die - Auslastung ohne irgendwelche laufenden Prozesse liegt bei $\approx8.25\,\percent$. + Da alle in dieser Arbeit entwickelten Programme lediglich die \gls{CPU} benutzen, ist dies der einzige relevante Messwerte. Trotzdem sind + die anderen Werte interessant und werden mit dokumentiert. Wie man im Screenshot sieht, ist das System in diesem Fall kaum belastet. Die + Auslastung ohne irgendwelche laufenden Prozesse liegt bei $\approx8,25\,\percent$. Relevanter ist aber der Fall mit laufender Kamera, da dies die Voraussetzung für diese Arbeit ist. Wird die Kamera-\gls{ROS Node} gestartet und erneut \lstinline{jtop} überprüft, ergibt sich die in \autoref{fig: jtop cam baseline} gezeigte Screenshot. \begin{figure} \includegraphics[width=.75\textwidth, trim={0 0 12px 31px}, clip]{img/jtop_camera.png} - \caption{CPU Auslastung mit laufender Kamera und ROS-Core} + \caption{\gls{CPU}-Auslastung mit laufender Kamera und ROS-Core} \label{fig: jtop cam baseline} \end{figure} - Dort ist die CPU-Auslastung deutlich höher und liegt bei $\approx38\,\percent$. Es ist allerdings zu beachten, dass dies nicht + Dort ist die \gls{CPU}-Auslastung deutlich höher und liegt bei $\approx38\,\percent$. Es ist allerdings zu beachten, dass dies nicht ausschließlich auf die Kamera-\gls{ROS Node} zurückzuführen ist. Um überhaupt \glslink{ROS Node}{ROS Nodes} benutzen zu können, muss das - sogenannte ROS Core gestartet sein. Diese geschieht automatisch beim Starten der ersten Node. Es ist für den Großteil der zusätzlichen + sogenannte ROS Core gestartet sein. Dies geschieht automatisch beim Starten der ersten Node. Es ist für den Großteil der zusätzlichen Auslastung verantwortlich, sodass zusätzliche \glspl{ROS Node} die Auslastung nur geringfügig erhöhen werden. \pagebreak diff --git a/svg/Lens_alignment.svg b/svg/Lens_alignment.svg index f215229483b236c5d5d9ffebd913a60faf4b32d1..e4a57f31821a43367c13d89ab5059839e795f589 100644 --- a/svg/Lens_alignment.svg +++ b/svg/Lens_alignment.svg @@ -25,13 +25,13 @@ inkscape:document-units="mm" showgrid="false" showguides="false" - inkscape:zoom="3.3638608" - inkscape:cx="195.01401" - inkscape:cy="99.587949" - inkscape:window-width="1920" - inkscape:window-height="1017" - inkscape:window-x="1912" - inkscape:window-y="-8" + inkscape:zoom="2.5060319" + inkscape:cx="112.5285" + inkscape:cy="116.71839" + inkscape:window-width="1368" + inkscape:window-height="850" + inkscape:window-x="-6" + inkscape:window-y="-6" inkscape:window-maximized="1" inkscape:current-layer="layer1"> <sodipodi:guide @@ -48,7 +48,7 @@ x="0" y="0" width="24.241247" - height="29.358212" + height="29.358213" id="page29995" /> <inkscape:page x="34.241247" @@ -94,13 +94,13 @@ <text xml:space="preserve" style="font-size:3.175px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#0c46a1;fill-opacity:1;stroke-width:0.264583" - x="30.666185" + x="29.821556" y="25.028616" id="text28738"><tspan sodipodi:role="line" id="tspan28736" style="font-size:3.175px;fill:#0c46a1;fill-opacity:1;stroke-width:0.264583" - x="30.666185" + x="29.821556" y="25.028616">Linse</tspan></text> <rect style="fill:#1b5e20;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264999" @@ -156,13 +156,13 @@ <text xml:space="preserve" style="font-size:3.175px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#0c46a1;fill-opacity:1;stroke-width:0.264583" - x="64.907433" + x="64.062805" y="25.028616" id="text29792"><tspan sodipodi:role="line" id="tspan29790" style="font-size:3.175px;fill:#0c46a1;fill-opacity:1;stroke-width:0.264583" - x="64.907433" + x="64.062805" y="25.028616">Linse</tspan></text> <rect style="fill:#1b5e20;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264999" diff --git a/svg/PAP_generisch_markerdetektion.svg b/svg/PAP_generisch_markerdetektion.svg index 062406dd1de4d9ed7f817fadc8aa137ba0ffe0f1..e7ccd58911ec210c7e025c0c0e1d110fa39c899c 100644 --- a/svg/PAP_generisch_markerdetektion.svg +++ b/svg/PAP_generisch_markerdetektion.svg @@ -1,286 +1,299 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - <svg - width="65.477997mm" - height="85.584579mm" - viewBox="0 0 65.477997 85.584579" - version="1.1" - id="svg5" - inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" - sodipodi:docname="PAP_generisch_markerdetektion.svg" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="PAP_generisch_markerdetektion.svg" + inkscape:version="1.0 (4035a4fb49, 2020-05-01)" + id="svg5" + version="1.1" + viewBox="0 0 65.477997 85.584579" + height="85.584579mm" + width="65.477997mm"> + <metadata + id="metadata50"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> <sodipodi:namedview - id="namedview7" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:showpageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:deskcolor="#d1d1d1" - inkscape:document-units="mm" - showgrid="false" - inkscape:zoom="2.3786088" - inkscape:cx="56.755865" - inkscape:cy="211.46815" - inkscape:window-width="1920" - inkscape:window-height="1017" - inkscape:window-x="1912" - inkscape:window-y="-8" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" inkscape:window-maximized="1" - inkscape:current-layer="layer1" /> + inkscape:window-y="-6" + inkscape:window-x="-6" + inkscape:window-height="850" + inkscape:window-width="1368" + inkscape:cy="211.46815" + inkscape:cx="56.755865" + inkscape:zoom="2.3786088" + showgrid="false" + inkscape:document-units="mm" + inkscape:deskcolor="#d1d1d1" + inkscape:pagecheckerboard="0" + inkscape:pageopacity="0.0" + inkscape:showpageshadow="2" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="namedview7" /> <defs id="defs2" /> <g - inkscape:label="Ebene 1" - inkscape:groupmode="layer" + transform="translate(-113.24405,-28.687072)" id="layer1" - transform="translate(-113.24405,-28.687072)"> + inkscape:groupmode="layer" + inkscape:label="Ebene 1"> <g - id="g10493-8" + style="display:inline" transform="translate(21.670614,-2.750652)" - style="display:inline"> + id="g10493-8"> <path - style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + sodipodi:nodetypes="ccccc" id="path4703-3" - sodipodi:nodetypes="ccccc" /> + d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" - d="m 124.31244,40.511082 v 2.00542" + sodipodi:nodetypes="cc" id="path20429" - sodipodi:nodetypes="cc" /> + d="m 124.31244,40.511082 v 2.00542" + style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> </g> <g - id="g20461" + style="display:inline" transform="translate(21.670614,13.106106)" - style="display:inline"> + id="g20461"> <path - style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + sodipodi:nodetypes="ccccc" id="path20457" - sodipodi:nodetypes="ccccc" /> + d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" - d="m 124.31244,40.511082 v 2.00542" + sodipodi:nodetypes="cc" id="path20459" - sodipodi:nodetypes="cc" /> + d="m 124.31244,40.511082 v 2.00542" + style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> </g> <g - id="g10487" - transform="translate(21.670614,24.914687)"> + transform="translate(21.670614,24.914687)" + id="g10487"> <rect - style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#1b5e20;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" - id="rect8556" - width="17.146717" - height="8.5733585" - x="115.73907" - y="4.0223846" + rx="4.2866793" ry="4.2866793" - rx="4.2866793" /> + y="4.0223846" + x="115.73907" + height="8.5733585" + width="17.146717" + id="rect8556" + style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#1b5e20;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" /> <text - xml:space="preserve" - style="font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;stroke-width:0.264583" - x="124.23948" + id="text8560" y="9.6970081" - id="text8560"><tspan - sodipodi:role="line" - id="tspan8558" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583" + x="124.23948" + style="font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;stroke-width:0.264583" + xml:space="preserve"><tspan + y="9.6970081" x="124.23948" - y="9.6970081">Bild</tspan></text> + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583" + id="tspan8558" + sodipodi:role="line">Bild</tspan></text> </g> <g - id="g20450" - transform="translate(21.670614,15.906322)"> + transform="translate(21.670614,15.906322)" + id="g20450"> <rect - style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" - id="rect8562" - width="64.977997" - height="11.345918" - x="91.823441" - y="26.114948" + ry="0" rx="0" - ry="0" /> + y="26.114948" + x="91.823441" + height="11.345918" + width="64.977997" + id="rect8562" + style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" /> <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" - x="124.35886" + id="text9354" y="30.75145" - id="text9354"><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" - x="124.35886" + x="124.35886" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" + xml:space="preserve"><tspan + id="tspan20431" y="30.75145" - id="tspan20431">Aufbereitung:</tspan><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" x="124.35886" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">Aufbereitung:</tspan><tspan + id="tspan5074" y="35.60215" - id="tspan5074">In Grauwerte umwandeln / Filtern</tspan></text> + x="124.35886" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">In Grauwerte umwandeln / Filtern</tspan></text> </g> <g - id="g5080" + style="display:inline" transform="translate(21.670614,28.96286)" - style="display:inline"> + id="g5080"> <path - style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + sodipodi:nodetypes="ccccc" id="path5076" - sodipodi:nodetypes="ccccc" /> + d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" - d="m 124.31244,40.511082 v 2.00542" + sodipodi:nodetypes="cc" id="path5078" - sodipodi:nodetypes="cc" /> + d="m 124.31244,40.511082 v 2.00542" + style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> </g> <g - id="g5090" - transform="translate(21.670614,47.619834)"> + transform="translate(21.670614,47.619834)" + id="g5090"> <rect - style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" - id="rect5082" - width="36.262444" - height="11.345918" - x="106.18121" - y="26.114948" + ry="0" rx="0" - ry="0" /> + y="26.114948" + x="106.18121" + height="11.345918" + width="36.262444" + id="rect5082" + style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" /> <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" - x="124.42139" + id="text5088" y="30.365856" - id="text5088"><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" - x="124.42139" + x="124.42139" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" + xml:space="preserve"><tspan + id="tspan5086" y="30.365856" - id="tspan5086">Features</tspan><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" x="124.42139" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">Features</tspan><tspan + id="tspan5143" y="35.216557" - id="tspan5143">verknüpfen</tspan></text> + x="124.42139" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">verknüpfen</tspan></text> </g> <g id="g5139"> <g - id="g20455" - transform="translate(21.670614,20.802758)"> + transform="translate(21.670614,20.802758)" + id="g20455"> <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" - x="124.40149" + id="text20445" y="41.689034" - id="text20445"><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" - x="124.40149" + x="124.40149" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" + xml:space="preserve"><tspan + id="tspan21193" y="41.689034" - id="tspan21193">Features </tspan><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" x="124.40149" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">Features </tspan><tspan + id="tspan5094" y="46.539734" - id="tspan5094">Identifizieren</tspan></text> + x="124.40149" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">identifizieren</tspan></text> </g> <rect - style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" - id="rect5082-1" - width="36.262444" - height="11.345918" - x="127.98825" - y="57.878029" + ry="0" rx="0" - ry="0" /> + y="57.878029" + x="127.98825" + height="11.345918" + width="36.262444" + id="rect5082-1" + style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" /> </g> <g - id="g5149" + style="display:inline" transform="translate(21.670614,44.819618)" - style="display:inline"> + id="g5149"> <path - style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + sodipodi:nodetypes="ccccc" id="path5145" - sodipodi:nodetypes="ccccc" /> + d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" - d="m 124.31244,40.511082 v 2.00542" + sodipodi:nodetypes="cc" id="path5147" - sodipodi:nodetypes="cc" /> + d="m 124.31244,40.511082 v 2.00542" + style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> </g> <g - id="g5159" - transform="translate(21.670614,63.476592)"> + transform="translate(21.670614,63.476592)" + id="g5159"> <rect - style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" - id="rect5151" - width="45.571644" - height="11.345918" - x="101.52661" - y="26.114948" + ry="0" rx="0" - ry="0" /> + y="26.114948" + x="101.52661" + height="11.345918" + width="45.571644" + id="rect5151" + style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#0d47a1;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" /> <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" - x="124.44033" + id="text5157" y="30.728712" - id="text5157"><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" - x="124.44033" + x="124.44033" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583" + xml:space="preserve"><tspan + id="tspan5155" y="30.728712" - id="tspan5155">Verbesserung mit</tspan><tspan - sodipodi:role="line" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" x="124.44033" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">Verbesserung mit</tspan><tspan + id="tspan5163" y="35.579411" - id="tspan5163">weiteren Informationen</tspan></text> + x="124.44033" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;stroke-width:0.264583" + sodipodi:role="line">weiteren Informationen</tspan></text> </g> <g - id="g5221" + style="display:inline" transform="translate(21.670614,60.676376)" - style="display:inline"> + id="g5221"> <path - style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + sodipodi:nodetypes="ccccc" id="path5217" - sodipodi:nodetypes="ccccc" /> + d="m 125.03972,42.516502 -0.72728,2.00542 -0.72727,-2.00542 h 0.72727 z" + style="fill:#000000;stroke:none;stroke-width:0.205976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" - d="m 124.31244,40.511082 v 2.00542" + sodipodi:nodetypes="cc" id="path5219" - sodipodi:nodetypes="cc" /> + d="m 124.31244,40.511082 v 2.00542" + style="fill:none;stroke:#000000;stroke-width:0.256;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> </g> <g - id="g5229" - transform="translate(21.670614,101.42591)"> + transform="translate(21.670614,101.42591)" + id="g5229"> <rect - style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#b71c1c;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" - id="rect5223" - width="23.739723" - height="8.5733585" - x="112.44257" - y="4.0223846" + rx="4.2866793" ry="4.2866793" - rx="4.2866793" /> + y="4.0223846" + x="112.44257" + height="8.5733585" + width="23.739723" + id="rect5223" + style="fill:none;fill-opacity:0.74902;fill-rule:evenodd;stroke:#b71c1c;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1" /> <text - xml:space="preserve" - style="font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;stroke-width:0.264583" - x="124.23948" + id="text5227" y="9.6970081" - id="text5227"><tspan - sodipodi:role="line" - id="tspan5225" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583" + x="124.23948" + style="font-size:3.88056px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;stroke-width:0.264583" + xml:space="preserve"><tspan + y="9.6970081" x="124.23948" - y="9.6970081">Ergebnis</tspan></text> + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583" + id="tspan5225" + sodipodi:role="line">Ergebnis</tspan></text> </g> </g> </svg>