Welchen Algorithmus kann ich verwenden, um Bokeh zu simulieren?

Ich versuche, ein Skript zu schreiben, das jedes Pixel in einem Foto durchläuft und ein Bokeh auf das Bild als Ganzes anwendet.

Ich habe ein Skript basierend auf diesem Link erstellt , 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 zentriert ist und in der Farbe dieses Pixels.

Auf winzigen Bokeh-Pinseln sieht es … okay aus, aber sobald ich die Bokeh-Pinselgröße überhaupt erhöhe, sieht es aus wie eine Gaußsche Unschärfe. Hier ist ein Bild von Times Square, das mit meinem Algorithmus verschwommen ist:

Geben Sie hier die Bildbeschreibung ein

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

Sie können irgendwie sagen, dass es sich von Gauß unterscheidet, aber es ist immer noch weit entfernt von dem, was respektabel als Bokeh mit scharfen Kanten bezeichnet werden könnte:

Geben Sie hier die Bildbeschreibung ein

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

@Imre Ich verstehe die Unterschiede und dass Bokeh normalerweise durch ein Objektiv und Gaussian durch Nachbearbeitung verursacht wird, aber ich möchte Bokeh simulieren.
@Entity: Wie suche ich nach Beispielbildern mit einer genauen Tiefenkarte? Ist deiner genau? Ich würde das gerne selbst ausprobieren (nach dem Finale). Vielleicht bekomme ich dann in ein paar Wochen eine Antwort. Wenn deines öffentlich ist, kann ich einen Link dazu haben?
@MartijnCourteaux Für meine ersten Tests verwende ich nur eine flache Tiefenkarte, damit alles verschwommen ist. Für einfache Geometrie (z. B. eine Tasse auf einem Tisch) wäre es meiner Meinung nach 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 .

Antworten (2)

Ich denke, das Hauptproblem ist eines des Dynamikbereichs. Ihr Algorithmus ist wahrscheinlich richtig, aber Sie arbeiten an der falschen Art von Daten.

Eine Punktlichtquelle, die sonst abgeschnitten und reinweiß werden würde, wird durch eine defokussierte Linse über eine größere Fläche verteilt, sodass sie eine Scheibe bildet, die nicht so hell ist und daher nicht abgeschnitten wird.

Deshalb erhalten Sie diese schönen Kreise in Ihrem echten Bokeh-Bild. Wenn Sie das Signal beschneiden (es weniger hell machen, als es sonst wäre, und es dann mit Ihrer Bokeh-Simulation ausbreiten, erhalten Sie einen schwachen Kreis (oder Sechseck oder was auch immer), der nicht auffällt und daher nicht realistisch aussieht.

Was Sie in einer echten 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.

Was Sie tun können, ist zu versuchen, die Daten zu linearisieren, jeden Dynamikbereich zu ersetzen, der durch Clipping verloren gegangen ist, Ihre Bokeh-Simulation durchzuführen und dann die nichtlinearen Operationen zu wiederholen!

Hier ist ein Beispiel. Ich habe mit einem HDR-Bild begonnen, das Tonemapping unterzogen wurde und ein stark nichtlineares Ergebnis liefert. Dies ist der schlechteste Bildtyp, mit dem man eine Bokeh-Simulation versuchen kann!

Wenn Sie eine Standardfaltungsoperation durchführen, um Bokeh zu simulieren (mit dem Linsenunschärfe-Werkzeug von Photoshop), erhalten Sie dieses Ergebnis, das dem, was Sie erhalten, sehr ähnlich ist:

Um ein besseres Ergebnis zu erzielen, habe ich eine extreme Kurve angewendet, um zu versuchen, das Bild wieder ungefähr so ​​zu machen, wie es vor dem Tonemapping gewesen wäre, wo die Glanzlichter viel, viel heller sind als der Rest des Bildes. Ich tat dies, indem ich mit dem Ebenenwerkzeug den mittleren Eingang weit nach rechts schob, von 1,0 auf etwa 0,2). Ich habe dann wie zuvor das Linsenunschärfe-Werkzeug angewendet. Schließlich habe ich eine extreme Kurve in der entgegengesetzten Richtung zur ersten Kurve angewendet. Das Ergebnis ist zwar weit davon entfernt, perfekt zu sein, sieht aber eher wie ein echtes Objektiv-Bokeh aus:

 

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

tl;dr Selbst wenn Sie ein perfektes mathematisches Bokeh-Modell implementiert haben, muss es auf nicht geclippte lineare Daten angewendet werden. Wenn Sie die gleichen Berechnungen auf stark modifizierte Daten anwenden (selbst ein Standard in Kamera-JPEG ist aus mathematischer Sicht stark modifiziert), erhalten Sie ein ganz anderes Ergebnis.

Zunächst einmal zählt in der Optik nur Licht und Dunkelheit nicht. Stellen Sie sicher, dass Ihr Algorithmus dunkle Pixel nicht an ihrer ursprünglichen Position ausbluten lässt. Die resultierenden Pixel sollten eher dem Maximum nahegelegener Quellpixel ähneln als dem Durchschnitt. Oder, um noch genauer zu sein, Sie würden Logarithmen der Auswirkungen auf die Quellpixel aufsummieren.

Eine andere mögliche Ursache, warum Ihre Kanten möglicherweise nicht scharf sind, wäre, wenn die Kanten Ihrer Maske nicht scharf sind. Die Animation auf der Seite, die Sie als Referenz angegeben haben, könnte missverstanden werden, sodass in einer Maske das ursprüngliche Pixel hell und andere allmählich dunkler werden. Dies würde auch im berechneten Bokeh zu schlammigen Rändern führen. In der Fotografie haben Öffnungen bestimmte Kanten, keine allmählichen. Eigentlich sollten also die meisten Pixel in einer Maske gleich hell sein und nur Kanten (wo weniger als ein Pixel für eine glatte Linie gefärbt sein sollte) können einen gewissen Grauton haben.

Sie erwähnen auch eine Tiefenkarte, aber kein Wort über deren Verwendung . Die Größe Ihrer Bokeh-Maske sollte mit der Pixeltiefe und der Tiefendifferenz der Brennebene korrelieren - je weiter ein Pixel von der Brennebene entfernt ist (in beiden Richtungen), desto größer sollte seine Maske sein. In der Brennebene sollte die Maskengröße 1 × 1 Pixel betragen.

Vorausgesetzt, die Operationen sind alle additiv, werden Sie nicht das Problem haben, dass sich dunkle Bereiche ausbreiten. Es ist wahr, dass Sie eine scharfe Maske benötigen, um scharfe Kreise zu erhalten, aber das Hauptproblem besteht darin, dass seine Bokeh-Operation auf nichtlineare Daten angewendet wird.