Mit welchem ​​Algorithmus kann ich Bokeh simulieren?

12

Ich versuche, ein Skript zu schreiben, das sich durch jedes Pixel eines Fotos schlängelt und ein Bokeh auf das gesamte Bild anwendet.

Ich habe ein Skript erstellt, das auf diesem Link basiert , aber das scheint ein Hack zu sein.

Ich habe drei Eingabebilder: eine Schwarz-Weiß-Tiefenkarte, ein Foto und ein Bokeh-Pinselbild (das derzeit ein Sechseck ist). Für jedes Pixel des Fotos stempele ich den Bokeh-Pinsel so, dass er auf diesem Pixel und in der Farbe dieses Pixels zentriert ist.

Auf winzigen Bokeh-Pinseln sieht es ... okay aus, aber wenn ich den Bokeh-Pinsel erst einmal vergrößere, sieht er wie eine Gaußsche Unschärfe aus. Hier ist ein mit meinem Algorithmus verschwommenes Bild des Times Square:

Bildbeschreibung hier eingeben

Vergiss die dunklen Ränder, ich kann das reparieren.

Man kann sagen, dass es sich von Gauß unterscheidet, aber es ist immer noch weit weg von dem, was man Bokeh nennen könnte, mit scharfen Kanten:

Bildbeschreibung hier eingeben

Ich verstehe, warum mein Algorithmus das tut, was er tut. Wie kann ich ein Bokeh genauer simulieren?

Entität
quelle
@Imre Ich verstehe die Unterschiede, und dass Bokeh in der Regel durch ein Objektiv und Gauß durch Nachbearbeitung verursacht wird, aber ich möchte Bokeh simulieren.
Entität
@Entity: Wie suche ich nach Beispielbildern mit einer genauen Tiefenkarte? Ist deins genau? Ich würde das gerne selbst ausprobieren (nach dem Finale). Vielleicht werde ich dann in ein paar Wochen eine Antwort finden. Wenn deins öffentlich ist, kann ich einen Link dazu haben?
Martijn Courteaux
@MartijnCourteaux Für meine ersten Tests verwende ich nur eine flache Tiefenkarte, damit alles verschwommen ist. Für eine einfache Geometrie (z. B. eine Tasse auf einem Tisch) halte ich es für ziemlich einfach, eine gut aussehende Tiefenkarte zu erstellen. Für komplexere Bilder benötigen Sie wahrscheinlich eine echte Tiefenkarte. Dies kann aus zwei Bildern oder sogar nur aus Ihrem Einzelbild berechnet werden .
Entity

Antworten:

20

Ich denke, das Hauptproblem ist der dynamische Bereich. Ihr Algorithmus ist wahrscheinlich richtig, aber Sie arbeiten mit dem falschen Datentyp.

Eine Punktlichtquelle, die ansonsten reinweiß ausschneiden würde, wird durch eine defokussierte Linse über einen größeren Bereich verteilt, so dass sie eine Disc bildet, die nicht so hell ist und daher nicht ausschneidet.

Das ist der Grund, warum Sie diese schönen Kreise in Ihrem echten Bokeh-Bild sehen. Wenn Sie das Signal abschneiden (weniger hell machen als sonst, und es dann mit Ihrer Bokeh-Simulation ausbreiten), erhalten Sie einen dunklen Kreis (oder ein Sechseck oder was auch immer), der nicht auffällt und daher nicht realistisch aussieht.

Was Sie in einer realen Bildkette haben, ist:

bokeh (from the lens) -> digitisation (clipping) -> gamma correction & dynamic range compression

Was Sie tun, ist

sharp image -> digitisation (clipping) -> gamma correction & dynamic range compression -> bokeh simulation

Sie erhalten nicht das richtige Ergebnis, da Sie nicht mit linearen Daten arbeiten.

Sie können versuchen, die Daten zu linearisieren, den durch das Abschneiden verlorenen Dynamikbereich zu ersetzen, eine Bokeh-Simulation durchzuführen und dann die nichtlinearen Operationen erneut auszuführen !

Hier ist ein Beispiel. Ich habe mit einem HDR-Bild begonnen, das tonemappt wurde und ein sehr nichtlineares Ergebnis liefert. Dies ist die schlechteste Art von Bild, mit der Sie eine Bokeh-Simulation versuchen können!

Wenn Sie eine Standard-Faltungsoperation durchführen, um Bokeh zu simulieren (mit dem Objektivunschärfewerkzeug von Photoshop), erhalten Sie dieses Ergebnis, das dem sehr ähnlich ist, was Sie erhalten:

Um ein besseres Ergebnis zu erzielen, habe ich eine extreme Kurve angewendet, um zu versuchen, das Bild wieder in etwa so zu machen, wie es vor dem Tonemapping gewesen wäre, bei dem die Glanzlichter viel, viel heller als der Rest des Bildes sind. Ich habe das mit dem Ebenen-Werkzeug gemacht, indem ich den mittleren Eingang weit nach rechts geschoben habe (von 1,0 auf ungefähr 0,2). Ich habe dann wie zuvor das Werkzeug für die Linsenunschärfe angewendet. Schließlich habe ich der ersten Kurve eine extreme Kurve entgegengesetzt angewendet. Das Ergebnis ist noch lange nicht perfekt, ähnelt jedoch eher einem echten Linsenbokeh:

 

Wenn Sie dies im Code tun, versuchen Sie, jeden Wert zu würfeln, dann wenden Sie Ihre Bokeh-Simulationsroutine an und nehmen Sie dann die Kubikwurzel jedes Werts. Sie sollten eine Verbesserung sehen. Es könnte einige Anpassungen erfordern.

tl; dr , auch wenn Sie ein perfektes mathematisches Modell Bokeh implementiert haben, müssen sie auf unclipped lineare Daten angewendet werden. Wenn Sie dieselben Berechnungen auf stark veränderte Daten anwenden (selbst ein Standard in Kamera-JPEG wird mathematisch stark verändert), erhalten Sie ein ganz anderes Ergebnis.

Matt Grum
quelle
12

Erstens summiert sich in der Optik nur das Licht und die Dunkelheit nicht. Stellen Sie sicher, dass Ihr Algorithmus dunkle Pixel nicht nach außen ausblutet. Die resultierenden Pixel sollten eher dem Maximum der Quellpixel in der Nähe als dem Durchschnitt entsprechen. Um noch genauer zu sein, würden Sie die Logarithmen der Auswirkungen auf die Quellpixel zusammenfassen.

Eine andere mögliche Ursache, warum Ihre Ränder möglicherweise nicht scharf sind, ist, dass die Ränder Ihrer Maske nicht scharf sind. Die Animation auf der Seite, die Sie als Referenz angegeben haben, kann missverstanden werden, sodass in einer Maske das ursprüngliche Pixel hell und andere nach und nach dunkler sind. Dies würde sich auch in schlammigen Rändern im berechneten Bokeh niederschlagen. In der Fotografie haben Aperturen bestimmte Kanten, keine graduellen. Tatsächlich sollten die meisten Pixel in einer Maske die gleiche Helligkeit haben und nur Kanten (bei denen weniger als ein Pixel für eine glatte Linie farbig sein sollte) können einen Grauton aufweisen.

Sie erwähnen auch mit einer Tiefenkarte, aber kein Wort zu verwenden es. Die Größe Ihrer Bokeh-Maske sollte mit der Pixeltiefe und dem Tiefenunterschied der Brennebene korrelieren. Je weiter ein Pixel von der Brennebene entfernt ist (in beide Richtungen), desto größer sollte die Maske sein. In der Brennebene sollte die Maskengröße 1 × 1 Pixel betragen.

Imre
quelle
Vorausgesetzt, die Operationen sind alle additiv, tritt das Problem der Ausbreitung dunkler Bereiche nicht auf. Es ist wahr, dass Sie eine scharfe Maske benötigen, um scharfe Kreise zu erhalten, aber das Hauptproblem ist, dass seine Bokeh-Operation auf nichtlineare Daten angewendet wird.
Matt Grum,