Vergleich der Genauigkeit numerischer Integrationsverfahren.
Der Touristenfilter
Menschenleere Naturfotos dank OpenCV, Python und YOLOv7
Landschaftsaufnahmen ohne Menschen
Als Tourist sucht man die Einsamkeit in der Natur, nur um vor Ort festzustellen, das man die Abgeschiedenheit mit hunderten anderen, gleichgesinnten, Menschen teilten muss. Für stimmungsvolle Naturfotos sind Touristenmassen aber ungeeignet. Ein Urlaub ist teuer, es gibt eine Menge zu sehen und nicht jeder kann oder will frühmorgens der Erste vor Ort sein. Grund genug sich einen Touristenfilter für Fotos zu wünschen.Das Problem ist in der Fotocommunity bekannt und das Mittel der Wahl zu dessen Lösung ist das sogenannte Median-Stacking. Alles was man dazu benötigt, ist eine Serie von Fotos, welche mit einem Stativ aufgenommen wurden. Diese werden dann einfach einer Medianfilterung im Zeitbereich unterzogen. Das heißt man sortiert alle Helligkeitswerte für jedes Pixel in jedem Bild der Serie und wählt dann den Wert, der genau in der Mitte der sortierten Daten liegt.
Leider funktioniert Median-Stacking in den meisten Fällen nicht gut genug und erfordert viel Nacharbeit. Ich möchte hier Algorithmen vorstellen, die mit gleichen Eingangsdaten deutlich besser funktionieren. Die Grundlage der Algorithmen ist die Verwendung eines neuronalen Netzwerkes zur Erkennung von Personen in Kombination mit einem Median-Stack.
Die Basaltsäulen des Reynisfjara-Strandes in Island. Vier Beispielbilder aus einem Fotostapel zeigen Personen an verschiedenen Stellen der Basaltsäulen. Um die Personen zu entfernen, muss man nur die Bereiche zusammenfügen, in denen sich keine Personen befinden.Grundlagen des Median-Stackings
Die folgenden Kommandozeile führt die Medianfilterung eines Fotostacks durch:
python ./filter-all-tourists.py -i ./stack1 -m MEDIAN
Median-Stacking basiert auf der Anwendung eines Mediafilters auf alle Bildpunkte eines Fotos in einer Serie von Bildern. Der Median einer Serie von 2n+1 Werten wird ermittelt, indem die Werte zunächst der Größe nach sortiert werden. Der Wert, dessen Index danach genau in der Mitte der sortierten Daten liegt, ist der Median. Der Median der Serie { 4300, 9, 30, 1, 3, 10, 17 } ist beispielsweise 10, denn nach Sortierung steht die 10 in der Serienmitte:
{ 1, 3, 9, 10, 17, 30, 4300 } = 10
Ein Medianfilter ist besonders geeignet um sporadische Ausreißer aus einer Datenserie herauszufiltern. Denn während bei der Berechnung des Durchschnittswertes alle Werte der Serie mit gleicher Wichtung in die Berechnung eingehen, ignoriert der Median alle anderen Werte außer dem in der Mitte der sortierten Serie. Weil Ausreißer nach Sortierung aber immer entweder am Anfang oder am Ende liegen, werden sie für den Median niemals berücksichtigt. Ein Medianfilter ist allerdings nur geeignet um kurzfristige Störungen der Daten zu eliminieren. Ein Tourist, der in einiger Entfernung vor das Fotomotiv tritt, ist eine solche Störung, solange er nicht stehen bleibt. Wenn er sich zu lange an einem Ort aufhält, kann seine Präsenz nicht mehr herausgefiltert werden und es entstehen Geisterbilder.
Die Entstehung von Geisterbildern lässt sich in Bildern mit Menschen nicht verhindern, denn diese neigen dazu in Gruppen länger stehen zu bleiben. Wenn das passiert, dann wird die Person zum bestimmenden Faktor für die Farbe des Pixels.
Die Medianbildung funktioniert nicht mehr, wenn zu viele Touristen für zu lange Zeit Teile des Bildes verdecken. Im Beispiel verdeckt der Tourist in der blauen Jacke die Felsen an einer Stelle des Bildes in mehr als der Hälfte aller Fotos.Verbessertes Medianstacking mit Objektdetektion und Maskierung
Für verlässliche Ergebnisse benötigt man Verfahren, welche die Bildung von Geisterbildern bei der Median-Filterung verhindern können. Was liegt da näher als deren Ursache, die Touristen, einfach komplett auszublenden? Das ist möglich mittels Objektdetektion und Maskierung. Sehen wir uns drei verschiedene Algorithmen an, die das ermöglichen:
Personen detektieren, ausschneiden und Median-Stacking
Personen werden mit YOLOv7 detektiert und aus den Fotos ausgeschnitten. Danach wird das nächste Bild geladen, Personen werden erneut ausgeschnitten und die Bildteile, welche im ersten Bild fehlen werden vom 2. Foto hineinkopiert. Dieser Vorgang wird solange wiederholt, wie weitere Bilder vorhanden sind.
Personendetektion mit Ausschneiden und Stacking
Die Ursache für das nicht hundertprozentige funktionieren des Median-Stackings ist, dass Personen zu lange an einer Stelle verweilen oder sich mit anderen ständig abwechseln. Wenn das eigentliche Motiv nur einen Minderheit der Zeit frei sichtbar ist, kann der Median nicht funktionieren. Man könnte versuchen sich mit Photoshop das Naturbild aus dem Stack zusammenzusetzen, indem man Ausschnitt für Ausschnitt die Teile des Bildes, in denen der Blick frei ist kombiniert.
python ./filter-all-tourists.py -i ./stack1 -m CUT
Das ist genau das, was der zweite Algorithmus macht, nur eben vollautomatisch. Wir verwenden dafür YOLOv7, einen auf Deep-Learning basierenden Objektdetektor. YOLO ist ein Modell, das mit dem COCO-Datensatz auf über 80 Klassen trainiert wurde. Es erkennt Klassen, wie Personen, Autos, Fahrräder, Motorräder, Katzen, Hunde, Rucksäcke und vieles mehr. Kurzgesagt Dinge die Menschen mit sich führen und die man in einem Naturbild nicht sehen will. Man muss sich nicht einmal die Mühe machen zu prüfen, was YOLO sieht. Wenn YOLO etwas sieht, gehört es nicht in ein Naturbild und wird ausgeschnitten. Das wird in allen Fotos getan und im Idealfall gibt es für jedes Pixel mindestens ein Bild, in dem nichts menschengemachtes die Sicht verdeckt. Wie das aussieht zeigt die folgende Animation:
Touristenentfernung mit YOLOv7. Oben links: Eingangsbild mit YOLOv7 Detektionsboxen. Oben rechts: Heatmap der Touristen. Unten Links: Gefiltertes Foto mit derzeit bestem Ergebnis. Unten Rechts: Weiße Bildteile sind die Teile, die ohne Touristen rekonstruiert werden konnten.Das Verfahren funktioniert, aber nicht gut genug. Denn es gibt einige sichtbare Probleme:
- Der Objektdetektor ist nicht perfekt und erkennt in manchen Fotos nicht alle Personen
- YOLOv7 erkennt keine Schatten. Personen werden ausgeschnitten, deren Schatten aber nicht.
- Auch hier funktioniert die vollständige Entfernung aller Personen nur dann, wenn es mindestens ein Foto gibt in dem jeder Bildbereich frei ist. In dem verwendeten Stack ist das nicht der Fall.
- Wo Personen ausgeschnitten wurden, entstehen harte Übergänge. Das liegt daran, dass sich die Helligkeit der einzelnen Bilder infolge der wechselnden Bewölkung leicht voneinander unterscheidet.
Das Endergebnis ist im folgenden Bild zu sehen (links). Verglichen mit einem einfachen Medianstack (rechtes Bild), ist es nicht viel besser. Allerdings kann man es zusätzlich noch mit einem solchen verbinden und so die Stärken beider Verfahren kombinieren.
Rechts: Median-Stacking hinterlässt Geisterbilder und entfernt keine Touristen, die sich lange an einem Ort aufgehalten haben.
In der Animation oben ist zu erkennen, wie die Touristen buchstäblich Stück für Stück aus dem Bild entfernt werden, bis am Ende des Durchlaufs ein Optimum erreicht wird. Wir modifizieren den Algorithmus nun so, dass er den Fotostack zweimal durchläuft. Damit erreichen wir, dass der zweite Durchlauf mit einem nahezu touristenfreien Bild begonnen wird. Alle Bilder dieses zweiten Durchlaufs werden dann am Ende mit dem Median Verfahren gestapelt. Dadurch erfolgt eine Glättung der Schnittkanten und eine Entfernung der Schatten. Dieser Algorithmus kann tatsächlich Touristen nahezu komplett entfernen und hinterlässt dabei deutlich weniger Artefakte.
Personen mit Rauschen überzeichnen und Median-Stacking
Die Personenentfernung mit YOLOv7-Objektdetektion funktioniert im oben beschriebenen Verfahren gut, erfordert aber zwei Durchläufe. Es ist nicht ohne weiteres möglich die ausgeschnittenen Bilder direkt zu Stacken. Man müsste beim Median-Stacking für jedes Pixel wissen, in welchen Fotos ein Tourist das Pixel bestimmt und diese Bilder für dieses eine Pixel ignorieren. Selbst dann würden am Ende noch "Löcher" an Stellen im Bild zurückbleiben, an denen sich Touristen zu lange aufgehalten haben. Sehen wir uns also ein Verfahren an, das mit nur einem Durchlauf Touristen entfernen kann. Es kann mit folgender Kommandozeile verwendet werden:
python ./filter-all-tourists.py -i ./stack1 -m NOISE_AND_MEDIAN
Auch bei diesem Verfahren werden Personen mit YOLOv7 erkannt. Jetzt wird allerdings jede Person mit einem binären Rauschen aus zufällig verteilten schwarzen und weißen Pixeln überdeckt. Das wird gemacht, weil diese Helligkeitswerte beim Medianstacking an den Anfang oder das Ende sortiert werden und die Möglichkeit besteht, dass dazwischen einige wenige Pixel ohne Touristen gefunden wurden.
Die Helligkeiten in jedem der Fotos werden zunächst so modifiziert, dass weder der Helligkeitswert 0, noch der Helligkeitswert 255 darin vorkommen. Das ist eine nicht sichtbare Reduktion des Dynamikumfangs im Bild. Danach werden alle Touristen mit zufällig verteilten schwarzen und weißen Pixeln überdeckt. Wenn nach der Medianfilterung Pixel mit einer Helligkeit von 0 oder 255 im Ergebnis verbleiben ist klar, dass diese Pixel zu Stellen gehören, an denen Personen gefunden wurden. Denn durch die anfängliche Dynamikreduktion des Bildes kommen diese Helligkeitswerte nicht mehr natürlich vor. Diese Pixel werden abschließend mit der OpenCV-Inpaint Methode überzeichnet. Diese Funktion wurde entwickelt um kleiner Kratzer und Defekte unauffällig durch auffüllen mit Pixeln in ähnlichen Farben zu beseitigen.
Das Überdecken der Touristen mit binärem Rauschen erleichtert dem Medianfilter die Arbeit. Die Farben Schwarz oder Weiß werden bei der Medianfilterung an die Ränder sortiert und spielen so für den Median, der ja in der Mitte der sortierten Pixel liegt keine Rolle.Das Ergebnis kann sich sehen lassen, die Touristen wurden komplett entfernt. Ganz Rückstandsfrei funktioniert das allerdings nicht. Zurück bleibt eine Region mit stärkerem Rauschen und einigen dunklen Pixeln, die vermutlich von dunkler Kleidung der Touristen stammen. Das Verfahren funktioniert nicht besonders gut, wenn sehr viele Touristen im Bild sind oder einige Bildteile permanent verdeckt wurden.
Personen mit OpenCV inpaint überzeichnen und Median-Stacking
Der letzte Algorithmus wird Touristen komplett entfernen, allerdings kann er den Hintergrund nicht vollständig wiederherstellen. Die Artefakte, die er erzeugt werden in vielen Fällen aber akzeptabel sein. Dieser Algorithmus wird mit der Option INPAINT_AND_MEDIAN aktiviert:
python ./filter-all-tourists.py -i ./stack1 -m INPAINT_AND_MEDIAN
Auch dieser Algorithmus beginnt mit einer Personendetektion. Die gefundenen Objekte werden dann in jedem Foto mit der OpenCV inpaint Methode komplett überzeichnet. Danach wird über die so modifizierten Bilder ein Median Stack gebildet. Das sogenannte "inpainting" ist eigentlich nur geeignet um kleinere Kratzer und Bilddefekte zu beseitigen. Es kann den Hintergrund hinter einer Person nicht richtig rekonstruieren und liegt qualitativ weit hinter Methoden wie "Content Aware Fill" von Photoshop. Wenn man allerdings die Ergebnisse vieler solcher inpaintings mit Fotos kombiniert, auf denen die Sicht auf den Hintergrund frei war, dann kann bei der Medianbildung der Hintergrund trotz allem zu einem gewissen Teil rekonstruiert werden.
Durch das OpenCV-inpainting werden die Touristen komplett verdeckt. Rein optisch wirkt das Inpainting fast wie Wassertropfen auf der Linse.Die Personenentfernung funktioniert überraschend gut. Das Inpainting erzeugt Pixel, die farblich gut zum Hintergrund passen. Dabei werden die Ergebnisse kleinerer und größerer Inpaintings später im Medianstack miteinander kombiniert und auch mit Informationen aus Bildern ergänzt, auf denen der Blick frei war. Der Medianfilter mag nicht in der Lage sein den Hintergrund komplett richtig zu rekonstruieren aber er ist sehr nah dran.
Rechst: Selbst in Fotostacks mit vielen Menschen und geparkten Autos funktioniert das entfernen von Personen und sogar den geparkten Fahrzeugen, wenn auch nicht ohne jegliche Spuren.
Bemerkenswert ist, dass dieses Verfahren auch gut funktioniert, wenn viele Menschen Teile des Motivs permanent verdecken. Das Bild oben rechts enthielt neben sehr vielen Menschen auch geparkte Fahrzeuge.
Download und Verwendung des Skriptes
Benutzerschnittstelle des Touristenfilters.Als Eingangsdaten wird eine Fotoserie benötigt, die mit einem Stativ bei unveränderten Lichtverhältnissen aufgenommen wurde. Die Fotoserie sollte ungefähr 30-50 Bilder enthalten, die im Abstand von einigen Sekunden gemacht wurden. Es sollte darauf geachtet werden, dass möglichst jeder Teil des Bildes auf einem der Fotos ohne Menschen zu sehen ist. Die Aufgabe des Touristenfilters ist, in jedem Bild die Bereiche zu isolieren, in denen sich keine Personen befinden und dann aus diesen Bereichen das Originalbild zu rekonstruieren. Das Programm ist in Python geschrieben und kann entweder über die Kommandozeile oder mittels einer grafischen Benutzerschittstelle ausgeführt werden. Es implementiert neben dem Median-Stacking vier weitere, verbesserte, Algorithmen.
Programmbedienung
Den Ordner mit den Eingabebildern wählt man mit dem "Select Image Folder" Buttons aus. Danach wählt man das Verfahren, welches verwendet werden soll und drückt den "Start" Button.
Kommandozeilenoptionen
Das Programm kann vollständig über die Kommandozeile gesteuert werden.
Parameter | Beschreibung |
---|---|
-i | Ordner mit den Eingangsbildern. Die Bilder müssen aus einer mit einem Stativ aufgenommenen Serie stammen oder mit anderer Software ausgerichtet worden sein. |
-m METHODE | Die anzuwendende Methode der Entfernung. Mögliche Optionen sind: CUT, CUT_AND_MEDIAN, MEDIAN, NOISE_AND_MEDIAN, INPAINT_AND_MEDIAN |
-v VIDEO_NAME (optional) | Erzeugt ein Video des Stackingvorgangs. |
Beispiel:
python ./filter-all-tourists.py -i ./stack1 -m MEDIAN
Das Ausgabebild wird im Skriptverzeichnis abgelegt. Der Name das Bildes setzt sich aus dem Namen des Eingabeordners, der ausgewählten Methode sowie einigen Suchparametern zusammen. (z.B: stack4_yolo_NOISE_AND_MEDIAN_1280x736_conf=0.01_nms=0.9_sc=0.1_boxus=1.05x1.1.jpg)