SoSe24 - Praktikum Systementwurf - Segmentierung der Fahrbahnmarkierungen
Autoren: | Dennis Fleer, Philipp Sander |
Thema: | Segmentierung der Fahrbahnmarkierungen |
Workshoptermin 9: | 20.06.2024 |
Lernzielkontrolle 3: | 04.07.2024 |
Einleitung
Aufgabe war es einen Algorithmus zu entwickeln, welcher die Fahrbahnmarkierungen erkennt. Dieses wurde mit Hilfe von Matlab und der bwconncomp Methode umgesetzt.
PAP
Das PAP des Hauptprogramms liefert einen Überblick über das generelle Programm, während das PAP des Algorithmus sich mehr auf die Details bezieht wie die Fahrbahn erkannt wird.
Programmablaufplan des Hauptprogramms |
Programmablaufplan des Algorithmus |
Quelltext
- MATLAB Quelltext Ihrer Lösung mit Header und Kommentaren.
- Beachten Sie die Programmierrichtlinien für MATLAB®.
segmentiereFahrbahnmarkierungen.m |
%****************************************************************
% Hochschule Hamm-Lippstadt *
%****************************************************************
% Modul : segementiereFahrbahnmarkierungen.m *
% *
% Datum : 20.06.2024 *
% *
% Funktion : Fahrbahnmarkierungserkennung für *
% das CaroloCup Fahrzeug *
% *
% Implementation : MATLAB 2019b *
% *
% Req. Toolbox : *
% *
% Author : 2024 Philipp Sander, Dennis Fleer *
% *
% Bemerkung : Lernzielkontrolle 3 vom 04.07.24 *
% *
% Verwendete Datei: GeradeInKurve_IPT.mp4 *
% *
% Letzte Änderung : 03.07.2024 *
% *
%***************************************************************/
clear all,
close all
clc
%% Video laden
video = VideoReader('GeradeInKurve_IPT.mp4');
n = video.NumFrames;
% Video Writer initialisieren
outputVideoFile = 'GeradeInKurve_Segmente.mp4';
outputVideo = VideoWriter(outputVideoFile, 'MPEG-4');
outputVideo.FrameRate = video.FrameRate; % gleiche Bildrate wie das Originalvideo
open(outputVideo);
centerX = 450;
centerY = 325;
areaDistance = 150;
% Frames extrahieren, bearbeiten und in das neue Video schreiben
while hasFrame(video)
frame = readFrame(video);
% Frame bearbeiten
processedFrame = markRoadway(frame, centerX, centerY, areaDistance);
% Bearbeitete Frames in das neue Video schreiben
writeVideo(outputVideo, im2uint8(processedFrame));
end
% Video Writer schließen
close(outputVideo);
%****************************************************************
% Modul : segementiereFahrbahnmarkierungen.m *
% *
% Datum : 20.06.2024 *
% *
% Funktion : Algorithmus zur Erkennung und Einfärbung *
% der Fahrbahnmarkierung in einem Bild *
% *
% Implementation : MATLAB 2019b *
% *
% Req. Toolbox : *
% *
% Author : 2024 Philipp Sander, Dennis Fleer *
% *
% Bemerkung : Lernzielkontrolle 3 vom 04.07.24 *
% *
% Verwendete Datei: GeradeInKurve_IPT.mp4 *
% *
% Letzte Änderung : 03.07.2024 *
% *
%***************************************************************/
function markedIm = markRoadway(image, centerX, centerY, areaDistance)
%Bild biniarisieren
binIm = imbinarize(image);
%Objekte detektieren
CC = bwconncomp(binIm);
imSize = CC.ImageSize;
n = CC.NumObjects;
%Detektionsebene (Region of Interest) definieren
centerArea = [centerX-areaDistance, centerX; centerY-areaDistance, centerY+areaDistance];
nearestLeft = Inf;
leftObject = [];
nearestRight = Inf;
rightObject = [];
middleObjects = {};
arrayLength = 0;
for i = 1:n
object = CC.PixelIdxList{i};
[x, y] = ind2sub(imSize, object);
[~, maxIndex] = max(x);
maxY = y(maxIndex);
distanceY = centerY - maxY;
if inBetweenArea(centerArea, x, y)
arrayLength = arrayLength + 1;
middleObjects{arrayLength} = object;
disp("BETWEEN");
elseif distanceY > 0 && distanceY < nearestLeft && touchingArea(centerArea, x, y)
nearestLeft = distanceY;
leftObject = object;
%disp("FOUND LEFT " + num2str(distanceY));
elseif distanceY < 0 && abs(distanceY) < nearestRight && touchingArea(centerArea, x, y)
nearestRight = abs(distanceY);
rightObject = object;
%disp("FOUND RIGHT " + num2str(distanceY));
end
end
leftY = 0;
rightY = 100;
if ~isempty(rightObject)
[x, y] = ind2sub(imSize, rightObject);
[~, maxIndex] = max(x);
rightY = y(maxIndex);
end
if ~isempty(leftObject)
[x, y] = ind2sub(imSize, leftObject);
[~, maxIndex] = max(x);
leftY = y(maxIndex);
end
%% Darstellung
markedIm = drawRectangle(image, centerArea(1,1), centerArea(1,2), centerArea(2,1), centerArea(2,2), 0, 0, 255);
for i = 1:arrayLength
object = middleObjects{i};
[x, y] = ind2sub(imSize, object);
[~, maxIndex] = max(x);
maxY = y(maxIndex);
if maxY >= leftY && maxY <= rightY
markedIm = paintArea(markedIm, x, y, 255, 0, 0);
disp("FOUND MIDDLE");
else
disp(["[FAILED] maxY:", num2str(maxY), " leftY:", num2str(leftY), " rightY:", num2str(rightY)]);
end
end
if ~isempty(rightObject)
[x, y] = ind2sub(imSize, rightObject);
markedIm = paintArea(markedIm, x, y, 255, 255, 0);
end
if ~isempty(leftObject)
[x, y] = ind2sub(imSize, leftObject);
markedIm = paintArea(markedIm, x, y, 0, 255, 0);
end
end
%****************************************************************
% Modul : segementiereFahrbahnmarkierungen.m *
% *
% Datum : 20.06.2024 *
% *
% Funktion : Überprüfung ob alle Pixel eines Objekts in *
% der angegebenen Ebene liegt *
% *
% Implementation : MATLAB 2019b *
% *
% Req. Toolbox : *
% *
% Author : 2024 Philipp Sander, Dennis Fleer *
% *
% Bemerkung : Lernzielkontrolle 3 vom 04.07.24 *
% *
% Verwendete Datei: GeradeInKurve_IPT.mp4 *
% *
% Letzte Änderung : 03.07.2024 *
% *
%***************************************************************/
function result = inBetweenArea(area, objectX, objectY)
resX = all(objectX >= area(1, 1) & objectX <= area(1, 2));
resY = all(objectY >= area(2, 1) & objectY <= area(2, 2));
result = resX & resY;
end
%****************************************************************
% Modul : segementiereFahrbahnmarkierungen.m *
% *
% Datum : 20.06.2024 *
% *
% Funktion : Überprüfung ob ein Objekt in min. 1 Pixel *
% in einer Ebene liegt *
% *
% Implementation : MATLAB 2019b *
% *
% Req. Toolbox : *
% *
% Author : 2024 Philipp Sander, Dennis Fleer *
% *
% Bemerkung : Lernzielkontrolle 3 vom 04.07.24 *
% *
% Verwendete Datei: GeradeInKurve_IPT.mp4 *
% *
% Letzte Änderung : 03.07.2024 *
% *
%***************************************************************/
function result = touchingArea(area, objectX, objectY)
resX = any(objectX >= area(1, 1) & objectX <= area(1, 2));
resY = any(objectY >= area(2, 1) & objectY <= area(2, 2));
result = resX & resY;
end
%****************************************************************
% Modul : segementiereFahrbahnmarkierungen.m *
% *
% Datum : 20.06.2024 *
% *
% Funktion : Einzeichnen eines RGB Rechtecks in ein Bild *
% *
% Implementation : MATLAB 2019b *
% *
% Req. Toolbox : *
% *
% Author : 2024 Philipp Sander, Dennis Fleer *
% *
% Bemerkung : Lernzielkontrolle 3 vom 04.07.24 *
% *
% *
% Letzte Änderung : 03.07.2024 *
% *
%***************************************************************/
function outImage = drawRectangle(image, x1, x2, y1, y2, r, g, b)
imSize = size(image);
sizeX = imSize(1);
sizeY = imSize(2);
if x1 < 0
x1 = 0;
end
if y1 < 0
y1 = 0;
end
if x2 > sizeX
x2 = sizeX;
end
if y2 > sizeY
y2 = sizeY;
end
outImage = image;
for x = x1:x2
for y = y1:y2
%disp([num2str(x), num2str(y)]);
outImage = paintPixel(outImage, x, y, r, g, b);
end
end
end
function outImage = paintArea(image, xArr, yArr, r, g, b)
for i = 1:length(xArr)
image = paintPixel(image, xArr(i), yArr(i), r, g, b);
end
outImage = image;
end
function image = paintPixel(image, x, y , r, g, b)
if x >= 1 && x <= size(image, 1) && y >= 1 && y <= size(image, 2)
image(x, y, 1) = r;
image(x, y, 2) = g;
image(x, y, 3) = b;
else
%disp(['Ungültiger Index: x=', num2str(x), ', y=', num2str(y)]);
end
end
|
Ergebnisse
- Darstellung der Ergebnisse
- Abb. 4: Das ist ein biniarisiertes Bild von einer Aufnahme der Kamera. Man sieht die Fahrbahnmarkierungen und eine weitere.
- Abb. 5: Das ist das bearbeitete Bild welches aus der Aufnahme durch den Algorithmus entstanden ist.
- Links zu den Arbeitsergebnissen :
Link zu dem SVN-Ordner der Arbeitsergebnisse
Analyse
Beschreibung | Das Problem ist.. | Das Problem ist nicht... |
---|---|---|
Was genau ist das Problem? | Äußere Einflüsse wie Licht oder Objekte werfen Flecken | Objekte innerhalb der Ebene erkennen |
Wo tritt das Problem auf? | Am Rand der Detektionsebene | Außerhalb der Detektionsebene liegende Objekte |
Wie zeigt sich das Problem? | Er springt zwischen Objekten | Er bleibt konstant auf dem falschen Objekt |
Wann tritt das Problem auf? | Bei der dynamischen Erkennung im Video | Bei der statischen Erkennung in einem Bild |
Warum ist es ein Problem? | Weil dadurch die erkannte Fahrbahn sich verändert | Außerhalb der Detektionsebene liegende Objekte werden als Fahrbahn identifiziert |
Nr. | Beschreibung |
---|---|
1 | Die Objekte die nicht zu 100% in der Ebene liegen |
2 | Kleine Objekte am unteren Rand werden zu einem Rauschen |
Nr. | Maßnahme | Verantwortung | Status |
---|---|---|---|
1 | Teilüberschneidung der Objekte mit der Ebene zu lassen | Fleer, Sander | |
2 | Objekte müssen eine Mindestgröße aufweisen | Fleer, Sander |
Hinweis: Die Maßnahmen müssen nicht umgesetzt werden.
Zusammenfassung
- Zusammenfassung
Der Algorithmus funktioniert auf Bilderebene einwandfrei, allerdings tut er sich aus unerklärlichen Gründen bei einem Video deutlich schwerer, wobei eigentlich ein Video auch nur aus hintereinander gereihten Bildern besteht.
- Diskussion der Ergebnisse
Die Ergebnisse sind nicht wirklich zufriedenstellend. Der Algorithmus hat noch viele Fehler weswegen eine Spurführung quasi unmöglich wäre.
- Ausblick
Eine deutliche Verbesserung des Algorithmus wäre eine Weiterführung der Mittleren Linien durch die Gradientenvektoren.
- Lessons Learned
So einen Algorithmus zu entwerfen macht Spaß ist aber extrem zeit intensiv. Die Entwicklung für den Algorithmus hat ca. 20 Stunden gebraucht und er funktioniert immernoch nicht richtig, was sehr frustrierend ist.
Beantwortung der Lernzielkontrollfragen
- Mit welchen Ansätzen lassen sich die Mittle- und rechte Fahrspur segmentieren? Wir haben den Einsatz einer Ebene gewählt, damit schließt man im ersten Schritt viele der äußeren Einflüsse wie Lichtreflektionen und ähnliches aus. Im nächsten Schritt haben wir versucht Objekte zu finden, die größer sind als die Ebene, aber dennoch diese in ihren untersten Punkten berühren. Im Anschluss sortieren wir die gefundenen Objekte nach der Nähe zum Mittelpunkt. Und so finden wir die Linke und Rechte Fahrbahnmarkierungen. Die mittlere finden wir durch die Linke und Rechte Begrenzung, jedes weitere gefundene Objekt muss sich dazwischen befinden um als eine Mittellinie erkannt zu werden. Die außerhalb liegenden Mittellinien können dann über die Gradienten der gefundenen Mittellinien berechnet werden.
- Wieso sollten alle Fahrbahnränder segmentiert werden? Bei Kurvenfahrten kann es passieren, dass eine der Fahrbahnränder nicht mehr von der Kamera gesehen wird und dementsprechend muss darauf reagiert werden können. Wenn ich mindestens Links und Rechts nehme habe ich das Problem der Kurvenfahrt nicht mehr, da immer ein Fahrbahnrand übrig ist. Die Mittellinien braucht man, damit das Auto nicht auf der falschen Seite fährt und es so zu Unfällen kommen kann.
- Welche Vor- und Nachteile hat die Segmentierung? Die Segmentierung ist ein schnelles Verfahren welches in Echtzeit angewendet werden kann. Ein großer Nachteil sind Lichteinflüsse da diese mehrere Segmente miteinander verbinden, so kann nicht mehr alles richtig segmentiert werden kann. Ein weitere Nachteil ist, da wir uns auf Basis eines biniarisierten Bildes befinden, dass Farben nicht erkannt werden können.
- Wie könnten die Nachteile behandelt werden? Man könnte das ganze mit der Hough Transformation machen, da diese Präzise auf Linien reagieren kann. Hough Transformationen haben eine höhere Resistenz gegenüber äußeren Einflüssen, dafür ist diese allerdings langsamer. Das Farbproblem lässt sich durch die Verwendung von Modellbasierten Algorithmen lösen.
→ zurück zum Hauptartikel: Praktikum SDE | SDE-Team 2024/25 | Lernzielkontrolle 3