SoSe24 - Praktikum Systementwurf - Segmentierung der Fahrbahnmarkierungen: Unterschied zwischen den Versionen
Zeile 215: | Zeile 215: | ||
== Ergebnisse == | == Ergebnisse == | ||
* '''Darstellung der Ergebnisse''' | * '''Darstellung der Ergebnisse''' | ||
[[Datei:Unbearbeitete Fahrbahn.jpg]] | |||
Das ist ein biniarisiertes Bild von einer Aufnahme der Kamera. Man sieht die Fahrbahnmarkierungen und eine weitere. | |||
[[Datei:Erkannte fahrbahn.jpg]] | [[Datei:Erkannte fahrbahn.jpg]] | ||
Das ist das bearbeitete Bild welches aus der Aufnahme durch den Algorithmus entstanden ist. | |||
* '''Links zu den Arbeitsergebnissen''' | * '''Links zu den Arbeitsergebnissen''' | ||
[https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/_Semesterordner/SS2024/Team_2_Sander_Fleer/Termin_9/9_5/ Link zu dem SVN-Ordner der Arbeitsergebnisse] | [https://svn.hshl.de/svn/MTR_SDE_Praktikum/trunk/_Semesterordner/SS2024/Team_2_Sander_Fleer/Termin_9/9_5/ Link zu dem SVN-Ordner der Arbeitsergebnisse] |
Version vom 3. Juli 2024, 16:18 Uhr
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 |
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
%grayFrame = rgb2gray(frame);
processedFrame = markRoadway(frame, centerX, centerY, areaDistance);
% Bearbeitete Frames in das neue Video schreiben
writeVideo(outputVideo, im2uint8(processedFrame));
end
% Video Writer schließen
close(outputVideo);
function markedIm = markRoadway(image, centerX, centerY, areaDistance)
binIm = imbinarize(image);
CC = bwconncomp(binIm);
imSize = CC.ImageSize;
n = CC.NumObjects;
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
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
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
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
Das ist ein biniarisiertes Bild von einer Aufnahme der Kamera. Man sieht die Fahrbahnmarkierungen und eine weitere. 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 | |
Wo tritt das Problem auf? | Beispiel | Beispiel |
Wie zeigt sich das Problem? | Beispiel | Beispiel |
Wann tritt das Problem auf? | Beispiel | Beispiel |
Warum ist es ein Problem? | Beispiel | Beispiel |
Nr. | Beschreibung |
---|---|
1 | Warum? |
Nr. | Maßnahme | Verantwortung | Termin | Status |
---|---|---|---|---|
1 | Max Mustermann |
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.
- 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.
→ zurück zum Hauptartikel: Praktikum SDE | SDE-Team 2024/25 | Lernzielkontrolle 3