SigSys15 Ampelphasenerkennung
Autor: Andre Merkel
Betreuer: Prof. Schneider
Motivation
Ein Bild einer Ampel soll mittels eines Matlab-Programms auf die entsprechende Ampelphase ermittelt werden und die erkannte Phase soll im Bild eingezeichnet werden.
Ziel
Eine Ampel soll anhand ihrer Ampelphase analysiert und diese ausgegeben werden.
Aufgabe
- Einarbeitung in die Farberkennung
- Bild einlesen und Farbe filtern
- Erkennung von Farben bei unterschiedlichen Tageszeiten
- Berechnen, welche Phase die Ampel aktuell hat
- Markierung der Ampelphase im Bild
Einleitung
Im Rahmen der Lehrveranstaltung „Signalverarbeitende Systeme“ des Studiengangs „Business and Systems Engineering“ im Sommersemester 2015 gab es die Aufgabe, ein Projekt im Bereich der Bildverarbeitung durchzuführen. Die vorliegende Dokumentation befasst sich mit dem auswerten von Ampelphasen.
Detailliert bestand die Aufgabe darin, ein Bild mit einer Ampel einzulesen und diese anschließend zu analysieren. Da es sich um Ampelphasen handelt, ist die Erkennung von Farben besonders relevant für dieses Projekt. Zusätzlich sollten die Ampelphasen ungeachtet der Tageszeit (Tag oder Nacht) stabil erkannt werden. Sobald die Ampelphase erkannt wurde, sollte ebenfalls diese auf dem Bild gekennzeichnet werden.
Das hier vorgestellte Projekt wurde mit MatLab 2014a entwickelt und getestet. Die Nutzung anderer Versionen, insbesonderer älterer MatLab Versionen, kann zu Fehler oder zu unerwarteten Ereignissen führen. Daher wird empfohlen MatLab 2014a zu nutzen.
Konzept und Projektplanung
Im folgenden wird das Konzept und die Projektplanung vorgestellt:
0 Festlegung des Projektthemas innerhalb der Lehrveranstaltung „Signalverarbeitende Systeme“
1 Projektvorbereitung
1.1 Recherche über Farbräume und digitale Bilder
1.2 Planung der anstehenden Aufgaben
1.3 Einarbeitung in die Farbfilterung und Farbreduzierung
2 Projektdurchführung
2.1 Entwurf eines Black-Box-Modell
2.2 Entwicklung mehrere Farbfilter Algorithmen
2.3 Farbfilter testen
2.4 Farbfilter bewerten und auswählen
2.5 Implementierung eines Farbfilters
2.6 Implementierung Nebenfunktionen (z.B. Funktion zum einfügen von Bildern)
2.7 Umfangreiche Tests der Software und Anpassung von Parameter
3 Projektabschluss
3.1. Auswertung des Projekts
3.2. Abschließen der Dokumentation
Im fogenden ist ein Gantt-Diagramm sowie ein dazugehörige Zeitachse, welche mit dem Programm MS Project 2013 erstellt wurden. Dabei wurde das Diagramm erstellt und nach diesem gearbeitet.
Projektablaufplan
In diesem Kapitel wird die Funktionsweise der Ampelphasenerkennung näher erläutert. In der linken Abbildung (Abbildung 3) ist die Struktur des Programms hinterlegt. Zu Beginn muss das Hauptprogramm aufgerufen werden, welches ein Bild einliest. Nachdem dies geschehen ist leitet das Hauptprogramm das eingelesene Bild weiter an die Farbfilterung und Farbreduzierung weiter. Hierbei wird das eingelesene Bild nur auf die gesuchte Farbe gefiltert und alle anderen Farben werden aus dem Bild entfernt, sodass innerhalb diesen Schritts alle nicht gesuchten Farben auf ihre Grauwerte reduziert werden. Dieser Vorgang ist sehr entscheidend für das weitere Vorgehen, denn es soll dadurch der Einfluss anderer Farben nicht die Ampelphasen mit beeinflussen. Im selben Schritt erfolgt ebenfalls die Betrachtung des Bildes, ob die entsprechenden Farben "grün", "gelb" und "rot" vorliegen. An dieser Stelle sei angemerkt, dass die Farben der Ampel sich nur bedinkt von denen der in der Natur vorkommen Farben unterscheiden. Da nun das Bild auf die gesuchten Farben reduziert wurde, wird nach diesen explizit gesucht. Wird eine entsprechende Farbe gefunden, so wird das Bild weitergeleitet, um festzustellen welche Farbe tatsächlich gefunden wurde. Nach der Ermittlung der Farbe, wird die Position der gefundenen Ampelphase mit einem roten Viereck im Ursprungsbild eingezeichnet. Dadurch hat der Anwender die Bestätigung, dass die Ampelphase gefunden wurde.
Zusätzlich sei an dieser angemerkt, dass der Projektablaufplan eine vereinfachte Darstellung des entwickelten Programms darstellt, um einen guten Überblick zu schaffen und eine einfache Einarbeitung in die Thematik zu ermöglichen. Im weiteren Verlauf werden konkrete Bezüge zur Farberkennung, Farbfilterung sowie Postionserkennung und der Funktionsweise erläutert. Insgesamt jedoch liegt das Augenmerkmal bei der robusten Farberkennung sowie einer robusten Unterscheidung der Farbe.
Farbraum in MatLab
In diesem Kapitel wird der eingesetzte Farbraum, in welchem gearbeitet wird, näher erläutert. Durch dieses Kapitel wird eine Grundlage und das Verständnis für späteres Vorgehen geschaffen.
Das Einlesen von Bildern in MatLab geschieht mit dem Befehl "imread()", welches eine Bilddatei als Variable in den Workspace speichert. Das Bild selbst liegt nun in MatLab im RGB-Farbraum. Charakteristisch für diesen Farbraum ist zunächst, dass diese Variable in MatLab als eine Matrix vorliegt. Allerdings besitzt diese Matrix neben Zeilen und Spalten auch eine Angabe für den jeweiligen Farbton. Dabei wird diese Farbangabe mit RGB abgekürtzt. Die Abkürzung RGB steht für R = rot, G = grün und B = blau. Das beudetet das jedes Pixel im Bild durch seine Position gekennzeichnet ist und durch die Mischung aus den Werten R, G und B. Dabei liegen die RGB-Werte im Intervall von 0 bis 255. Das bedeutet, das ein Farbton aus der Mischung von drei Zahlen repräsentiert wird. Hierdurch ergibt sich, dass Farben, wie blau, einen gewissen Anteil an rot und grün besitzen. Allerdings gibt es auch die Möglichkeit, einen oder zwei Farbangaben auf null zu setzen, um einen entsprechenden Farbton zu erhalten. Der beschriebene Sachverhalt zu dem RGB-Farbraum kann ebenfalls aus der Abbildung 4 entnommen werden.
Liegt ein Bild im RGB-Farbraum vor, so kann dieses mit dem Befehl "imshow()" angezeigt werden. Das menschliche Auge empfindet die Darstellung von RGB-Bildern als natürlich und anschaulich. Allerdings ist dieser Farbraum weniger geeignet, um in diesen zu arbeiten. Die Problematik dabei ergibt sich, dass jeder Farbton durch drei Zahlen repräsentiert wird. Eine Filterung bzw. die Suche nach einer bestimmten Farbe geht immer mit der Prüfung aller drei Werte einher. Zusätzlich kann durch unterschiedliche Belichtung eines Objektes der Farbton sich ändern. Das bedeutet, dass auch die drei Werte (RGB) sich ändern. Daher ist eine Farbfilterung in einem RGB-Raum ungegeignet.[1]
Um effektiv eine Farbe im Bild zu filtern, wurde das RGB-Bild in den HSV-Farbraum übertragen. Dabei liefert dieser Farbraum den Farbwinkel, die Sättigung und die Helligkeit. Für das vorliegende Projekt ist der Farbwinkel von besonderer Bedeutung, da dieser alle Farbtöne in einer Variable erfasst. Um den Farbton mittels des Farbwinkels zu bestimmen wird eine Angabe von 0° bis 360° genutzt. Diese Angabe reicht aus, um alle benötigten Farben zu beschreiben. Durch den Farbton ist es nun möglich robust nach bestimmten Farben zu suchen bzw. nach diesen zu filtern. Des Weiteren gibt die Sättigung die Vermengenung der Farbe mit weiß und die Helligkeit gibt die Amplitude des Lichts an. Der beschriebene Sachverhalt zu dem HSV-Farbraum kann ebenfalls aus der Abbildung 5 entnommen werden.[2]
Startdatei
In diesem Kapitel findet die Vorstellung und Erläuterung der Startdatei statt, sowie eine Einleitung in die Funktionsweise sowie den konkreten Aufbau der entwickelten Software.
Insgesamt betrachtet ist die entwickelte Software modular aufgebaut, da dies viele Vorteile mit sich bringt und heut zu Tage ein Standard in der Entwicklung von Softwareprojekten darstellt. Die modulare Programmierung hat den besonderen Vorteil, dass jedes Modul für sich alleine entwickelt und getestet werden kann, ohne dass das gesamte Projekt fertig sein muss. Außerdem können Verbesserung an den einzelnen Modulen unabhängig von einander geschehen, auch dann wenn das Projekt fertig ist. Das liegt darin, das an sich nur die Schnittstellen eingehalten werden müssen, da die Logik in den Modulen vom Rest der Software gekapselt ist. Dies ermöglicht auch das Austauschen von Modulen bei einem fertigen Projekt, ohne dass an anderen Stellen der Software der Quellcode angepasst werden muss. Ein weiterer Vorteil der modularen Programmierung ist die Wiederverwendbarkeit von den Modulen. Wie bereits erwähnt, ist die Logik der Module vom restlichen Quellcode gekappelt und kann daher selbst in anderen Projekten einbezogen werden, sofern die Schnittstellen eingehalten werden.
Im nächsten Schritt wird die Startdatei betrachtet. Diese heißt "HauptSkript.m" und dient dem koordiniertem Aufruf von Funktionen, um die Ampelphasen zu erkennen. Um den Aufbau des Projekts besser zu erläutern wird zunächst der Quellcode betrachtet:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Mit diesem Skript wird die %
% Ampelphasenerkennung ge- %
% startet. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
clc
%% Bild einlesen
Bild = Modul_Bild_einlesen;
%% Bild nach farb-Pixel absuchen
BinaerBild_gruen = 0;
BinaerBild_gelb = 0;
BinaerBild_rot = 0;
% Feststellung der grünen Ampelphase
BinaerBild_gruen = Modul_gruen_erkennen(Bild);
% Feststellung der roten bzw. rot-gelben Ampelphase
if (length(find(BinaerBild_gruen==1))) == 0
% Erfassung der roten Ampelphase
BinaerBild_rot = Modul_rot_erkennen(Bild);
% Erfassung der gelben Ampelphase
BinaerBild_gelb = Modul_gelb_erkennen(Bild);
% Auswertung der rot-gelben Ampelphase (falls vorhanden)
if (length(find(BinaerBild_rot(:,:)==1))) > 0 && (length(find(BinaerBild_gelb(:,:)==1))) > 0
% Auswertung, ob es sich tatsächlich um eine rot-gelbe Ampelphase handelt
[BinaerBild_rot, BinaerBild_gelb] = Modul_rot_gelb_Auswertung(BinaerBild_rot, BinaerBild_gelb);
end
end
%% Ausgabe
Modul_Ausgabe(BinaerBild_gruen, BinaerBild_gelb, BinaerBild_rot, Bild);
Zu Beginn des Skripts erfolgt der Aufruf von "clear all", "close all" und "clc" Befehlen. Dies sorgt dafür, dass alle Variablen aus dem Workspace gelöscht, alle geöffneten Figuren geschlossen und das Command-Window bereinigt werden. Diese Vorgehenweise sorgt dafür, dass keine Variablen einen Einfluss auf die Ausführung des Projekts ausüben können.
Im nächsten Schritt erfolgt das Einlesen eines ausgewählten Bildes, welches in die Variable "Bild" gespeichert wird. Für eine detailierte Beschreibung dieser Funktion siehe das Kapitel "Bilder einlesen".
Nachdem Einlesen des Bildes, findet eine Initialsierung der Variablen "BinaerBild_gruen", "BinaerBild_gelb" und "BinaerBild_rot" statt. Diese Variablen dienen dem speichern von Bildinformation im binären Bereich. Das bedeutet, dass sobald eine entsprechende Farbe im Bild gefunden wurde, diese Information in ein Binärbild übertragen wird.
Der nächste Schritt beinhaltet den Aufruf der Funktion "Modul_gruen_erkennen()". Diese Funktion dient der Farbfilterung und der Suche nach der grünen Ampelphase. Die Funktion arbeitet robust und ist in Lage zwischen dem grün einer Ampel und bspw. dem grün von Bäumen und Büschen zu unterscheiden. Für eine detailierte Beschreibung dieser Funktion siehe das Kapitel "Filterung der grünen Farbe".
Sofern keine grüne Ampelphase gefunden wurde, findet eine weitere analyse des Bildes statt. Hierfür wird nach roter und gelber Ampelphase gesucht. Im Gegensatz zu der grünen Ampelphase muss nach der roten und gelben Ampelphase im Verbund gesucht werden. Der Grund hierfür liegt darin, dass im roten Licht der Ampel ein gewisser gelber Anteil vorkommen kann und umgekehrt. Daher findet zuerst der Aufruf der Funktion "Modul_rot_erkennen()", welche nach der rote Ampelphase sucht und anschließend erfolgt eine Suche nach der gelben Phase mit der Funktion "Modul_gelb_erkennen()". Für eine detailierte Beschreibung dieser Funktionen siehe das Kapitel "Filterung der roten Farbe" und "Filterung der gelben Farbe".
Anschließend erfolgt eine Prüfung, ob ein roter und gelber Anteil gefunden wurde (bezogen auf die Ampelphase). Trifft dieser Fall ein, so findet eine weitere Analyse statt. Mithilfe der Funktion "Modul_rot_gelb_Auswertung()" wird überprüft, ob es sich um eine rote Phase mit gelben Anteil, einer gelben Phase mit roten Anteil oder ob es sich tatsächlich um eine rot-gelben Phase handelt. Für eine detailierte Beschreibung dieser Funktion siehe das Kapitel "Analyse der rot-gelben Ampelphase".
Abschließend ruft die Startdatei die Funktion "Modul_Ausgabe()" auf, welche dann anhand der Binärbilder die Ampelphase ausgibt und im originalen Bild die Position der Ampelphase einzeichnet. Für eine detailierte Beschreibung dieser Funktion siehe das Kapitel "Ausgabe der Ampelphase".
Bilder einlesen
Im vorliegenden Kapitel erfolgt die Erläuterung der Funktionweise des Einlesens eines Bildes.
Wie bereits oben beschrieben, wird die Funktion "Modul_Bild_einlesen" zu Beginn des Programms aufgerufen. Für eine bessere Auseinandersetzung mit dieser Funktion, wird im folgenden der Quellcode betrachtet:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Dient dem Einlesen eines Bildes. %
% Das Bild muss im jpg-Format vorliegen. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Bild = Modul_Bild_einlesen
% Information zum Dialog
disp('Bitte wählen Sie ein Bild aus, in welchem die Ampel erkannt werden soll')
% Dialog zum Einlesen des Bildes
[BildName, BildPfad] = uigetfile('*.jpg','Bitte wählen Sie ein Bild aus');
% Pfad des Bildes hinzufügen
addpath(BildPfad);
Bild = imread(BildName);
disp('Die Ampelphase wird gesucht...')
end
Die obere Funktion gibt eine Information im Command-Window mit dem Befehl "disp()" aus, um den Anwender zu informieren, dass dieser ein Bild auswählen soll. Damit jedoch der Anwender ein Bild bequem aussuchen kann, wird mit dem Befehl "uigetfile()" ein Dialog aufgerufen, in welchem der Anwender sein Bilder auswählen kann. Der Dialog ist im Bild links dargestellt (Abbildung 6). Neben der Information im Command-Window, steht eine Information auf dem oberen Rahmen des Dialogs, welche noch einmal den Hinweis darauf gibt, dass ein Bild ausgesucht werden soll. Sobald der Anwender sein Bild ausgesucht hat, wird der Bildpfad und der Bildname gespeichert. Damit MatLab jedoch das Bild einlesen kann, muss der Pfad mittels "addpath()" für die MatLab Umgebung bekannt gemacht werden. Anschließend wird mithilfe des Bildnamens und dem Befehls "imread()" das ausgesuchte Bild in der Variable "Bild" hinterlegt. Bevor die Funktion die Variable zurückliefert, erfolgt eine weitere Ausgabe im Command-Window. Diese informiert den Anwender darüber, dass jetzt tatsächlich nach der Ampelphase gesucht wird. Dieser Hinweis soll dem Anwender die Sicherheit geben, dass seine Bildauswahl erfolgreich war und das die Software jetzt weiter arbeitet und nicht abgestürtzt ist.
Filterung der grünen Farbe
Das vorliegende Kapitel behandelt die Funkionsweise und Aufbau der Erkennung der grünen Ampelphase.
Bevor jedoch eine Auseinandersetzung mit dem Quellcode stattfindet, folgt zunächst eine Betrachtung der grünen Ampelphase als solche. Hierfür wird das selbstgeschossene Bild herangezogen (Abbildung 7). Der Mensch benötigt nur einen kurzen Blick, um zu erkennen, dass es hierbei um eine grüne Ampelphase handelt. Ganz im Gegenteil ist es, sobald eine automatische Suche nach dieser grünen Ampelphase stattfinden soll. Zu einem liegt die Problematik darin, dass das Bild viele Informationen hat. Das bedeutet, dass eine einfache Suche nach der grünen Farbe nict ausreicht. Der Grund hierfür liegt darin, dass die Bäume bzw. Büsche ebenfalls grün sind. Zum anderen liegt das Bild in einem RGB-Farbraum vor, dass, wie bereits erwähnt, ungeeignet ist um eine Farbfilterung durchzuführen. Außerdem besitzt die grüne Ampelphase keine gleich bleibende grüne Farbe über die gesamte Fläche der Scheibe. Dies ist deutlich an der Abbildung 8 zu erkennen. Diese Abbildung zeigt die gleiche Ampel wie Abbilundg 7 aus der Nähe (hier wurde in das linke Bild gezoomt). An dem rechten Bild ist deutlich zu erkennen, dass alleine sich in der Ampelscheibe untershiedliche grüne Farbtöne ergeben und auch nicht die gesamte Fläche ausgeleuchtet ist.
All diese Bedingungen stellen eine große Herausforderung, um das Bild auszuwerten, dar.
Da jetzt die Problematik soweit erläutert wurde, folgt im nächsten Schritt die Vorstellung des Quellcodes:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Dient der Filterung von %
% grünen Pixeln. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [BinaerBild] = Modul_gruen_erkennen(RGB_Img)
%% Farbe hervorheben
% Zunächst muss die grüne Farbe hervorgehoben werden, indem
% die restlichen Farben grau gesetzt werden
% Bild in den HSV-Farbraum konvertieren
HSV_Img = rgb2hsv(RGB_Img);
% Farbwert bzw Farbwinkel erfassen
Farbwert = 360.*HSV_Img(:,:,1);
% Sättigung der Farbe erfassen
Saettigung = HSV_Img(:,:,2);
% Erfassen der rot und gelb Anteile im Bild
Restfarbe = (Farbwert > 190) ;
% Die erfasste Restfarbe in der Sättigung auf "0" setzen
Saettigung(Restfarbe) = 0;
% Die neuen Werte speichern
HSV_Img(:,:,2) = Saettigung;
% Das obere Verfahren sorgte dafür, das alle nicht grün-Anteile
% nun grau Vorliegen. Als nächstes werden die grünen-Pixel erfasst
% und einheitlich grün gefärbt, sodass alle grünen Pixel genau den
% gleichen Wert aufweisen. Dadurch ist es später einfacher zu prüfen,
% welche Pixel grün sind und welche nicht. Die restlichen Pixel werden
% schwarz gefärbt (Ausblendung der nicht benötigten Farbe).
%% Erfassung der Pixelfarbe
for i=1:length(HSV_Img(:,1,1))
for j=1:length(HSV_Img(1,:,1))
R = HSV_Img(i, j, 1);
G = HSV_Img(i, j, 2);
B = HSV_Img(i, j, 3);
hP = 360*R;
if (G < 0.75 || B < 0.75) || (hP < 120)
% nicht-grüne Pixel schwarz färben
HSV_Img(i, j, 1) = 0;
HSV_Img(i, j, 2) = 0;
HSV_Img(i, j, 3) = 0;
else
% grüne Pixel einheitlich färben
HSV_Img(i, j, 1) = 0.4;
HSV_Img(i, j, 2) = 1;
HSV_Img(i, j, 3) = 1;
end
end
end
%% Pixel abspeichern, zählen und in den RGB-Raum konvertieren
% Das Bild zurück in den RGB-Farbraum konvertieren
gruen_Bild = hsv2rgb(HSV_Img);
% binäres Bild erzeugen
BinaerBild = im2bw(gruen_Bild);
end
Aus dem Quellcode geht hervor, dass die obige Funktion ein Bild als Eingabeparamter übergeben bekommt. Anschließend erfolgt eine Konvertierung des RGB-Bildes in den HSV-Farbraum. Darauffolgend werden die Farbwerte des Bildes in die Variable "Farbwert", sowie die der Sättigung in die Variable "Sättigung" gespeichert. Im nächsten Schritt erfolgt die Erfassung aller Pixel, die einen geringen Grünanteil besitzen und werden auf ihre Grauwerte reduziert. Das Ergebnis ist in der linken Abbildung zu sehen. Werden jetzt Abbildung 7 und Abbildung 9 verglichen, so ist deutlich zu erkennnen, dass die Abbildung 9 weniger Farben besitzt. Dieser Schritt ist insofern nützlich, da dieser nicht relevante Informationen aus dem Bild entfernt bzw. reduziert. Allerdings sind die grünen Pixel der Büsche und Bäume noch da. Damit diese nicht zufällig als die grüne Ampelphase erkannt werden, erfolgt im weiteren Verlauf mithilfe der for-Schleifen eine weitere Filterung. Hierbei findet eine Zielgereichtete Suche nach den benötigten Pixel statt. Die in der for-Schleifen eingestellten Werte wurden dabei auf empirischer Analyse verschiedener Bilder mit grünen Ampelphasen ermittelt. Das besondere hierbei ist, dass alle Pixel, die nicht in das Schema passen "entfernt" werden. Das bedeutet, dass jedes Pixel, welches nicht den gesuchten Wert aufweist, wird auf "0" gesetzt, d.h. das dieses Pixel schwarz gefärbt wird. Das Ergebnis dieser Filterung kann in der rechten Abbildung (Abbildung 10) betrachtet werden. Aus dieser ist deutlich zu entnehmen, dass nur die grüne Farbe der Ampelphase noch zu sehen ist. Allerdings ist an dieser Stelle die Funktion noch nicht beendet. Das HSV-Bild wird zurück in den RGB-Farbraum konvertiert und anschließend als Binärbild gespeichert. Das Binärbild enthält an der Stelle der grünen Pixel nun weiße Pixel. Die Farbe selbst wird im weiteren Verlauf nicht mehr benötigt, sondern nur die Pixel. Des Weiteren wird dieses Binärbild in die Variable "BinaerBild_gruen" in der Startdatei hinterlegt, damit eine nachträgliche Verwechslung, um welche gefundene Ampelphase es sich handeln könnte, ausgeschlossen. Dadurch wird das originale Bild ausschließlich auf die grüne Ampelphase reduziert. Der Vorteil dieser starken Reduzierung liegt in der Einfachheit der Variable. Wenn diese in MatLab geöffnet, wird eine große Matrix mit vielen Nullen angezeigt. An den Stellen, an denen die grünen Pixel der Ampelphase gefunden wurden, steht eine "1". Dies ermöglicht ein einfaches und schnelles arbeiten mit diesem Bild, da keine weiteren Informationen stören bzw. Einfluss nehmen.
Filterung der roten Farbe
Das vorliegende Kapitel behandelt die Funkionsweise und Aufbau der Erkennung der roten Ampelphase.
Da die Vorgehensweise und der Aufbau der roten Ampelphasenerkennung, die der grünen Ampelphasenerkennung ähnelt, wird der Fokus bei der Beschreibung des Quellcodes auf einige Besonderheiten gelegt. Dies soll eine unnötige Wiederholung vermeiden. Daher wird an dieser Stelle auf das Kapitel "Filterung der grünen Farbe" verwiesen.
Der Quellcode, um eine rote Ampelphase zu erkennen, ist wie folgt aufgebaut:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Dient der Filterung von roten Pixeln. %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [BinaerBild] = Modul_rot_erkennen(RGB_Img)
%% Farbe hervorheben
% Zunächst muss die rote Farbe hervorgehoben werden, indem
% die restlichen Farben grau gesetzt werden
% Bild in den HSV-Farbraum konvertieren
HSV_Img = rgb2hsv(RGB_Img);
% Farbwert bzw Farbwinkel erfassen
Farbwert = 360.*HSV_Img(:,:,1);
% Sättigung der Farbe erfassen
Saettigung = HSV_Img(:,:,2);
% Erfassen der grün und gelb Anteile im Bild
Restfarbe = (Farbwert > 10) & (Farbwert < 340);
% Die erfasste Restfarbe in der Sättigung auf "0" setzen
Saettigung(Restfarbe) = 0;
% Die neuen Werte speichern
HSV_Img(:,:,2) = Saettigung;
%% Erfassung der Pixelfarbe
% Das obere Verfahren sorgte dafür, das alle nicht rot-Anteile
% nun grau Vorliegen. Als nächstes werden die roten Pixel erfasst
% und einheitlich rot gefärbt, sodass alle roten Pixel genau den
% gleichen Wert aufweisen. Dadurch ist es später einfacher zu prüfen,
% welche Pixel rot sind und welche nicht. Die restlichen Pixel werden
% schwarz gefärbt (Ausblendung der nicht benötigten Farbe).
for i=1:length(HSV_Img(:,1,1))
for j=1:length(HSV_Img(1,:,1))
R = HSV_Img(i, j, 1);
G = HSV_Img(i, j, 2);
B = HSV_Img(i, j, 3);
if (G < 0.75 || B < 0.75)
% nicht-rote Pixel schwarz färben
HSV_Img(i, j, 1) = 0;
HSV_Img(i, j, 2) = 0;
HSV_Img(i, j, 3) = 0;
else
% rote Pixel einheitlich färben
HSV_Img(i, j, 1) = 1;
HSV_Img(i, j, 2) = 1;
HSV_Img(i, j, 3) = 1;
end
end
end
%% Pixel abspeichern, zählen und in den RGB-Raum konvertieren
% Das Bild zurück in den RGB-Farbraum konvertieren
rot_Bild = hsv2rgb(HSV_Img);
% binäres Bild erzeugen
BinaerBild = im2bw(rot_Bild);
% rote Pixel eintragen
for i=1:length(BinaerBild(:,1))
for j=1:length(BinaerBild(1,:))
if rot_Bild(i,j,1) == 1
BinaerBild(i,j) = 1;
end
end
end
end
Wie bereits oben erwähnt, ähnelt dieser Quellcode dem aus Kapitel "Filterung der grünen Farbe". Der einzige wichtige Unterschied liegt hier in der Vorfilterung, in welcher alle Pixel mit geringem Rotanteil auf ihre Grauwerte reduziert werden. Dies wurde ebenfalls empirisch erfasst. Zum Vergleich dienen die Abbildungen 11 und 12. Anhand der rechten Abbildung ist die Vorfilterung noch deutlicher zu erkennen als im Kapitel zuvor. Ebenfalls liefert diese Funktion ein Binärbild mit den nötigen Information an die Startdatei zurück.
Filterung der gelben Farbe
Das vorliegende Kapitel behandelt die Funkionsweise und Aufbau der Erkennung der gelben Ampelphase.
Da die Vorgehensweise und der Aufbau der roten Ampelphasenerkennung, die der grünen sowie roten Ampelphasenerkennung ähnelt, wird der Fokus bei der Beschreibung des Quellcodes auf einige Besonderheiten gelegt. Dies soll eine Redundanz vermeiden. Daher wird an dieser Stelle auf das Kapitel "Filterung der grünen Farbe" verwiesen.
Der Quellcode, um eine rote Ampelphase zu erkennen, ist wie folgt aufgebaut:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Dient der Filterung von gelben Pixeln. %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [BinaerBild] = Modul_gelb_erkennen(RGB_Img)
%% Farbe hervorheben
% Zunächst muss die gelbe Farbe hervorgehoben werden, indem
% die restlichen Farben grau gesetzt werden
% Bild in den HSV-Farbraum konvertieren
HSV_Img = rgb2hsv(RGB_Img); %# Convert the image to HSV space
% Farbwert bzw Farbwinkel erfassen
Farbwert = 360.*HSV_Img(:,:,1);
% Sättigung der Farbe erfassen
Saettigung = HSV_Img(:,:,2);
% Erfassen der grün und gelb Anteile im Bild
Restfarbe = (Farbwert < 10) | (Farbwert > 30); % [< 38, > 60]
% Die erfasste Restfarbe in der Sättigung auf "0" setzen
Saettigung(Restfarbe) = 0;
% Die neuen Werte speichern
HSV_Img(:,:,2) = Saettigung;
%% Erfassung der Pixelfarbe
% Das obere Verfahren sorgte dafür, das alle nicht gelb-Anteile
% nun grau Vorliegen. Als nächstes werden die gelben Pixel erfasst
% und einheitlich gelb gefärbt, sodass alle roten Pixel genau den
% gleichen Wert aufweisen. Dadurch ist es später einfacher zu prüfen,
% welche Pixel rot sind und welche nicht. Die restlichen Pixel werden
% schwarz gefärbt (Ausblendung der nicht benötigten Farbe).
for i=1:length(HSV_Img(:,1,1))
for j=1:length(HSV_Img(1,:,1))
R = HSV_Img(i, j, 1);
G = HSV_Img(i, j, 2);
B = HSV_Img(i, j, 3);
hP = 360*R;
if (G < 0.5 || B < 0.5) %|| (hP < 30)
HSV_Img(i, j, 1) = 0;
HSV_Img(i, j, 2) = 0;
HSV_Img(i, j, 3) = 0;
else
HSV_Img(i, j, 1) = 0.13;
HSV_Img(i, j, 2) = 1;
HSV_Img(i, j, 3) = 1;
end
end
end
%% Pixel abspeichern, zählen und in den RGB-Raum konvertieren
% Das Bild zurück in den RGB-Farbraum konvertieren
gelb_Bild = hsv2rgb(HSV_Img);
% binäres Bild erzeugen
BinaerBild = im2bw(gelb_Bild);
end
Die oben dargelegte Funktion geht bei der Filterung genauso vor, wie bei den beiden anderen Ampelphasenerkennungen auch. Allerdings sind hier die Werte für die Filterung angepasst. Die linke Abbildung (Abbildung 13) zeigt eine gelbe Ampelphase, welche stark mit Sonnenstrahlen "belichtet" ist, sodass das obere Verkehrszeichen "gelber" ist als die Ampelphase selbst. Allerdings kann der Filter hier Zielgerichtet die gelbe Ampelphase erkennen (siehe Abbidlung 14).
Analyse der rot-gelben Ampelphase
In dem vorliegenden Kapitel wird die Analyse der rot-gelben Ampelphase behandelt.
Die Analyse der rot-gelben Ampelphase stellt an sich keine Filterung wie in den Kapiteln zuvor dar. Das liegt darin, dass in roten Ampeln auch ein Anteil an gelben Pixeln existieren können, die der gelben Ampelphase gleich sind und umgekehrt. Daher würde an dieser Stelle eine Filterung wie in den oberen Kapiteln beschrieben wird nicht zielführend sein.
Um die Vorgehensweise der rot-gelben Ampelphase besser zu erläutern wird zunächst der Quellcode betrachtet:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Mit diesem Skript wird die Ampelphase %
% berechnet, ob es sich um eine "rote", %
% "gelbe2 oder eine "rot-gelbe" Phase %
% handelt. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [Binaer_rot, Binaer_gelb] = Modul_rot_gelb_Auswertung(BinaerBild_rot, BinaerBild_gelb)
%% Schwellwerte für rot und gelb setzen
Schwell_rot = 23; % in Prozent
Schwell_gelb = 23; % in Prozent
%% gelbe Pixel, die zu weit entfernt liegen löschen
[Zeile, Spalte] = find(BinaerBild_rot==1);
rot_Vertikal = round((min(Zeile) + max(Zeile)) / 2);
BinaerBild_gelb(1:rot_Vertikal,:) = 0; % gelbe Pixel oberhalb der roten Pixel entfernen
%% rot- und gelb-Anteile in Prozent berechnen
sumPixel = length(find(BinaerBild_rot(:,:)==1)) + length(find(BinaerBild_gelb(:,:)==1));
rotPix_Anteil = length(find(BinaerBild_rot(:,:)==1)) / sumPixel * 100;
gelbPix_Anteil = length(find(BinaerBild_gelb(:,:)==1)) / sumPixel * 100;
%% Schwellwert prüfen
% Liegt der rot-Anteil zu niedrig, gilt dies als Rauschen und wird entfernt
if rotPix_Anteil < Schwell_rot
Binaer_rot = zeros(length(BinaerBild_rot(:,1)), length(BinaerBild_rot(1,:)));
else
Binaer_rot = BinaerBild_rot;
end
% Liegt der gelb-Anteil zu niedrig, gilt dies als Rauschen und wird entfernt
if gelbPix_Anteil < Schwell_gelb
Binaer_gelb = zeros(length(BinaerBild_rot(:,1)), length(BinaerBild_rot(1,:)));
else
Binaer_gelb = BinaerBild_gelb;
end
end
Die obere Funktion wird immer dann aufgerufen, sobald die gelbe und rote Ampelphasenerkennung die Farben gefunden haben. An dieser Stelle wird dann überprüft, ob tatsächlich eine rot-gelbe Ampelphase vorliegt. Als erstes wird ein Schwellwert festgelegt, welcher aussagt, dass unterhalb diesen Wertes es keine rot-gelbe Ampelphase vorliegt, sondern eine rote bzw. gelbe Ampelphase. In der oberen Funktion wird ein Schwellwert von 23% festgelegt. Dieser Wert wurde empirisch ermittelt. Für einen Beispiel wird an dieser Stelle die Abbildung 15 herangezogen. An diesem Bild ist schon in dem Ausgangszustand zu erkennen, dass innerhalb der gelben Ampelphase auch ein roter Anteil existiert. Das Ergebnis nach der roten Ampelphasenerkennung ist in der Abbildung 16 zu sehen. In diesem ist ein gewisser Teil rot. Daher errechnet die obige Funktion das Verhältnis zwischen den roten und gelben Pixel. Abschließend erfolgt eine Überprüfung, ob der Schwellwert überschritten wird. In diesem Fall wird der Schwerllwert der roten Pixel nicht überschritten, daher gelten diese als Rauschen und werden entfernt. Dadurch entsteht also eine korrekte Erkennung der gelben Ampelphase.
Ausgabe der gefundenen Ampelphase
In diesem Kapitel wird aufgezeigt wie die erkannte Ampelphase dem Anwender angezeigt wird.
Zunächst wird der Quellcode betrachtet, mit welchen die Ausgabe stattfindet
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signalverarbeitende Systeme %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Projekt: Ampelphasenerkennung %
% %
% Autor: Andre Merkel %
% %
% Studiengang: Business and Systems Engineering %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Beschreibung: Mit diesem Skript wird die Ampelphase %
% dem Benutzer angezeigt. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% Implementierung: MatLab 2014a %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% letzte Änderung: 28.05.2015 %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Modul_Ausgabe(BinaerBild_gruen, BinaerBild_gelb, BinaerBild_rot, Bild)
if (length(find(BinaerBild_gruen==1))) == 0 && (length(find(BinaerBild_gelb==1))) ==0 && (length(find(BinaerBild_rot==1))) == 0
msgbox('Es wurde keine Ampelphase erkannt.','Ampelphasenerkennung');
return;
end
figure; imshow(Bild)
hold on
if (length(find(BinaerBild_gruen==1))) > 0
[Xmin_gruen, Xmax_gruen, Ymin_gruen, Ymax_gruen] = Submodul_Kasten_berechnen(BinaerBild_gruen);
Submodul_Plot_Rahmen(Xmin_gruen, Xmax_gruen, Ymin_gruen, Ymax_gruen);
myicon = imread('Ampel_gruen.png');
msgbox('Es wurde eine grüne Ampelphase erkannt','Ampelphasenerkennung','custom',myicon)
elseif (length(find(BinaerBild_gelb==1))) > 0 && (length(find(BinaerBild_rot==1))) > 0
[Xmin_rot, Xmax_rot, Ymin_rot, Ymax_rot] = Submodul_Kasten_berechnen(BinaerBild_rot);
Submodul_Plot_Rahmen(Xmin_rot, Xmax_rot, Ymin_rot, Ymax_rot);
[Xmin_gelb, Xmax_gelb, Ymin_gelb, Ymax_gelb] = Submodul_Kasten_berechnen(BinaerBild_gelb);
Submodul_Plot_Rahmen(Xmin_gelb, Xmax_gelb, Ymin_gelb, Ymax_gelb);
myicon = imread('Ampel_rot_gelb.png');
msgbox('Es wurde eine rot-gelbe Ampelphase erkannt','Ampelphasenerkennung','custom',myicon)
elseif (length(find(BinaerBild_rot==1))) > 0
[Xmin_rot, Xmax_rot, Ymin_rot, Ymax_rot] = Submodul_Kasten_berechnen(BinaerBild_rot);
Submodul_Plot_Rahmen(Xmin_rot, Xmax_rot, Ymin_rot, Ymax_rot);
myicon = imread('Ampel_rot.png');
msgbox('Es wurde eine rote Ampelphase erkannt','Ampelphasenerkennung','custom',myicon)
elseif (length(find(BinaerBild_gelb==1))) > 0
[Xmin_gelb, Xmax_gelb, Ymin_gelb, Ymax_gelb] = Submodul_Kasten_berechnen(BinaerBild_gelb);
Submodul_Plot_Rahmen(Xmin_gelb, Xmax_gelb, Ymin_gelb, Ymax_gelb);
myicon = imread('Ampel_gelb.png');
msgbox('Es wurde eine gelbe Ampelphase erkannt','Ampelphasenerkennung','custom',myicon)
end
end
Die obige Funktion bekommt als Argumente die jeweiligen Binärbilder übergeben. Diese prüft diese jetzt auf Inhalt und imformiert den Anwender um die gefundene Ampelphase. Das Ergebnis ist in der linken Abbildung (Abbildung 17) zu sehen. Hierzu wird das originale Bild geplotet mit dem Dialog, welche Ampelphase gefunden wurde. In dieser Abbildung ist deutlich zu entnehmen, dass eine gelbe Ampelphase erkannt wurde und keine rote bzw. rot-gelbe Ampelphase. Ebenfalls wurde die gelbe Ampelphase mit einem roten Viereck umrandet.
Fazit
Das Projekt der Ampelphasenerkennung war eine spannende und herausfordernde Aufgabe. Dadurch konnten viele wichtige Erkenntnisse über die Farbräume sowie der Aufbau von digitalen Bildern gesammelt werden. Die Komplexitität bzw. größte Schwierigkeit des Projektes war die Ermittlung korrekter Werte für die Filterung, da diese in keiner Literatur bzw. Webseiten behandelt wurden. Auch die Verifizierung der Ergebnisse, dass die Ampelphase tageszeitunabhängig gefunden werden muss, war eine anspruchsvolle Aufgabe. Insgesamt betrachtet kann über das vorliegende Projekt gesagt werden, dass es in der Lage ist robust bei einer Ampel alle Ampelphasen zu erkennen, unabhänigig von der Tageszeit. Außerdem bietet das Projekt aufgrund des modularen Aufbaus einen Mehrwert für andere Projekte, da die Module bzw. die Funktionen einfach kopiert und ggf. die Parameter angepasst werden können.
Ausblick
Das Projekt Ampelphasenerkennung kann in der aktuellen Form immernoch erweitert werden. Beispielsweise könnte das Projekt so erweitert werden, dass es defekte Ampeln (keine Ampelphase vorhanden) erkennen kann und somit rät die Verkehrszeichen zu nutzen.
Youtube-Video
Zum Projektabschluss fand eine Videoaufnahme, um die Ergebnisse des Projekts "Ampelphasenerkennung" aufzuzeigen, statt. Das Youtube-Video befindet sich unter dem folgendem Link [8].
Ampelbilder zum Testen des Programms
-
grüne Ampelphase (kleine Ampel)<ref>[1]kleine grüne Ampel. RWTH Aachen University
-
rot-gelbe Ampelphase bei Nacht <ref>[2]rot-gelbe Ampelphase. Autobild.de
-
rot-gelbe Ampelphase bei starker Sonneneinstrahlung (selbst geschossenes Bild)
-
grüne Ampelphase bei starker Sonneneinstrahlung (selbst geschossenes Bild)
Quellen
- ↑ [3]Information zum RGB-Farbraum. Wikipedia. Abgerufen am 17. Mai 2015.
- ↑ [4]Information zum HSV-Farbraum. Wikipedia. Abgerufen am 17. Mai 2015.
- ↑ [5]gelbe Ampel. Ruhrnachrichten. Abgerufen am 10. Mai 2015.
- ↑ [6]gelbe Ampel. Ruhrnachrichten. Abgerufen am 10. Mai 2015.
- ↑ [7]gelbe Ampel. Ruhrnachrichten. Abgerufen am 10. Mai 2015.
→ zurück zum Hauptartikel: Signalverarbeitende Systeme SoSe2015