www.wikidata.de-de.nina.az
Floodfill bzw Flutfullung ist ein Begriff aus der Computergrafik Es ist ein einfacher Algorithmus um Flachen zusammenhangender Pixel einer Farbe in einem digitalen Bild zu erfassen und mit einer neuen Farbe zu fullen Ausgehend von einem Pixel innerhalb der Flache werden jeweils dessen Nachbarpixel darauf getestet ob diese Nachbarpixel auch die alte Farbe enthalten Jedes gefundene Pixel mit der alten Farbe wird dabei sofort durch die neue Farbe ersetzt Inhaltsverzeichnis 1 Rekursive Implementierung 1 1 4 connected oder 4 Neighbour 1 2 8 connected oder 8 Neighbour 2 Iterative Implementierung 2 1 Programmierung 2 1 1 C 2 1 2 Python 3 Teiliterative Implementierung 4 EinzelnachweiseRekursive Implementierung BearbeitenEs gibt zwei Varianten der rekursiven Implementierung 4 connected oder 4 Neighbour Bearbeiten nbsp SchemaEs werden jeweils die 4 benachbarten Pixel unten links oben und rechts vom Ausgangspunkt untersucht Der Koordinatenursprung ist die Ecke links oben def fill4 x y alteFarbe neueFarbe if getPixel x y alteFarbe setPixel x y neueFarbe fill4 x y 1 alteFarbe neueFarbe unten fill4 x y 1 alteFarbe neueFarbe oben fill4 x 1 y alteFarbe neueFarbe rechts fill4 x 1 y alteFarbe neueFarbe links 8 connected oder 8 Neighbour Bearbeiten nbsp SchemaEs werden jeweils die 8 benachbarten Pixel oben unten links rechts oben links oben rechts unten links und unten rechts vom Ausgangspunkt untersucht Der Koordinatenursprung ist die Ecke links oben def fill8 x y alteFarbe neueFarbe if getPixel x y alteFarbe setPixel x y neueFarbe fill8 x y 1 alteFarbe neueFarbe unten fill8 x y 1 alteFarbe neueFarbe oben fill8 x 1 y alteFarbe neueFarbe rechts fill8 x 1 y alteFarbe neueFarbe links fill8 x 1 y 1 alteFarbe neueFarbe rechts unten fill8 x 1 y 1 alteFarbe neueFarbe rechts oben fill8 x 1 y 1 alteFarbe neueFarbe links unten fill8 x 1 y 1 alteFarbe neueFarbe links oben Bei gleichen Ausgangsbedingungen fullt die 8 connected Variante ublicherweise einen grosseren Bereich als die 4 connected Variante da sie durch feine Ritzen kriecht Je nach Anwendungsfall kann dies gewunscht sein oder auch nicht Der Algorithmus in der rekursiven Form ist zwar einfach zu formulieren und zu verstehen eignet sich jedoch nur bedingt fur nicht triviale Anwendungen Der Algorithmus ist uberaus rekursiv Daher besteht ein hohes Risiko dass der Algorithmus zu einem Stack Overflow fuhrt Ebenso benotigen die moglichen vielen Stack Operationen durch die Rekursionen im Vergleich zu den eigentlichen Operationen des Algorithmus relativ viel Zeit Nicht zuletzt sind viele Rekursionsaufrufe des Algorithmus unnotig da dabei unnotigerweise Pixel getestet werden die kurz zuvor bereits auf die neue Farbe gesetzt wurden Jede Rekursion trifft mindestens auf ein solches Pixel jenes Pixel welches gerade im daruberliegenden Rekursionslevel markiert wurde Iterative Implementierung BearbeitenProgrammierung Bearbeiten Mit Hilfe einer Warteschlange eines Stapelspeichers oder einer ahnlichen Datenstruktur ist auch eine iterative Implementierung moglich Dabei werden die Nachbarpixel Koordinaten gespeichert und dann nacheinander abgearbeitet Die Reihenfolge in der die Koordinaten aus der Datenstruktur ausgelesen werden spielt dabei keine Rolle Durch das hohe Risiko eines Stack Overflow bei der rekursiven Implementierung ist die iterative Version in der Regel die bessere Wahl zur Implementierung des Verfahrens C BearbeitenDas folgende Programm in der Programmiersprache C verwendet zwei verschachtelte while Schleifen fur eine Breitensuche der Pixel mit derselben Farbe 1 2 using System using System Collections Generic using System Drawing namespace FloodFill class Program Diese Methode gibt true zuruck wenn die beiden Farben gleich sind sonst false private static bool ColorMatch Color replacementColor Color targetColor return replacementColor ToArgb targetColor ToArgb Diese Methode fullt alle zusammenhangenden Pixel die dieselbe Farbe wie das Startpixel haben mit der neuen Farbe private static void FloodFill Bitmap bitmap Point point Color replacementColor Color targetColor bitmap GetPixel point X point Y Speichert die Farbe des Startpixels Queue lt Point gt queue new Queue lt Point gt Warteschlange der Pixel fur die Breitensuche queue Enqueue point Fugt das Startpixel der Warteschlange hinzu while queue Count 0 So lange die Warteschlange nicht leer ist Point point1 queue Dequeue Entfernt das erste Pixel aus der Warteschlange if ColorMatch bitmap GetPixel point1 X point1 Y targetColor Wenn die Farbe des aktuellen Pixels gleich dem Startpixel ist wird die nachste Iteration der ausseren while Schleife ausgefuhrt continue Point point2 new Point point1 X 1 point1 Y Speichert das Pixel rechts vom aktuellen Pixel while point1 X gt 0 amp amp ColorMatch bitmap GetPixel point1 X point1 Y targetColor So lange das aktuelle Pixel nicht links vom Rand ist und die Farbe des Startpixels hat bitmap SetPixel point1 X point1 Y replacementColor Setzt das aktuelle Pixel auf die neue Farbe if point1 Y gt 0 amp amp ColorMatch bitmap GetPixel point1 X point1 Y 1 targetColor Wenn das aktuelle Pixel nicht am linken Rand ist und die Farbe des Startpixels hat queue Enqueue new Point point1 X point1 Y 1 Fugt das Pixel uber dem aktuellen Pixel der Warteschlange hinzu if point1 Y lt bitmap Height 1 amp amp ColorMatch bitmap GetPixel point1 X point1 Y 1 targetColor Wenn das aktuelle Pixel nicht am rechten Rand ist und die Farbe des Startpixels hat queue Enqueue new Point point1 X point1 Y 1 Fugt das Pixel unter dem aktuellen Pixel der Warteschlange hinzu point1 X Verschiebt das aktuelle Pixel um 1 nach links Die folgende while Schleife wiederholt den Ablauf mit dem Pixel rechts vom aktuellen Pixel while point2 X lt bitmap Width 1 amp amp ColorMatch bitmap GetPixel point2 X point2 Y targetColor bitmap SetPixel point2 X point2 Y replacementColor if point2 Y gt 0 amp amp ColorMatch bitmap GetPixel point2 X point2 Y 1 targetColor queue Enqueue new Point point2 X point2 Y 1 if point2 Y lt bitmap Height 1 amp amp ColorMatch bitmap GetPixel point2 X point2 Y 1 targetColor queue Enqueue new Point point2 X point2 Y 1 point2 X Verschiebt das aktuelle Pixel um 1 nach rechts Hauptmethode die das Programm ausfuhrt public static void Main string args Bitmap bitmap new Bitmap UnfilledCircle png Weist den Inhalt der Bilddatei mit dem angegebenen Dateinamen der Variablen der Klasse Bitmap hinzu FloodFill bitmap new Point 200 200 Color Red Aufruf der Methode mit den Parametern fur Startpixel und Farbe bitmap Save FilledCircle png Speichert das geanderte Bitmap als Bilddatei mit dem angegebenen Dateinamen Python Bearbeiten def fill4 x y alteFarbe neueFarbe stack push x y while stack isNotEmpty x y stack pop if getPixel x y alteFarbe setPixel x y neueFarbe stack push x y 1 stack push x y 1 stack push x 1 y stack push x 1 y Dieses iterative Beispiel entspricht dem rekursiven Algorithmus mit vier Nachbarn Derjenige mit acht Nachbarn wird entsprechend analog implementiert Anstatt auf dem Stack die als nachstes zu testenden Positionen zu speichern ist es moglich die vorherigen Positionen und Richtungen zu speichern Der Stack enthalt dadurch nur den Pfad zur derzeitigen Position was den Algorithmus speichereffizienter macht 3 Teiliterative Implementierung BearbeitenBei teiliterativer Implementierung besteht der Algorithmus aus einem iterativen Teil der immer weiterlauft und sich immer in eine bestimmte Richtung wendet zum Beispiel immer linksherum Wenn der iterative Teil keine Pixel mehr zum Einfarben findet wird der rekursive Teil gestartet der nun deutlich weniger tief in die Rekursion geht Somit ist ein Stack Overflow weniger wahrscheinlich Einzelnachweise Bearbeiten Rosetta Code Bitmap Flood fill GeeksforGeeks Flood fill Algorithm Tiefensuche von zusammenhangenden Nodes in Minetest Abgerufen von https de wikipedia org w index php title Floodfill amp oldid 217249155