Informationen zum Erstellen von Budget-Stereobildern auf Fingern (Stereogramm, Anaglyphe, Stereoskop)

Am nächsten Wochenende müssen Sie ein paar Dutzend Codezeilen schreiben und ein Bild zeichnen, aber keines ist besser. Also habe ich letztes vorletztes Wochenende gezeigt, wie man Raytracing macht und sogar alles in die Luft jagt. Dies ist für viele überraschend, aber Computergrafik ist eine sehr einfache Sache. Ein paar hundert Zeilen nacktes C ++ reichen aus, um interessante Bilder zu erstellen.

Das Thema des heutigen Gesprächs ist das binokulare Sehen, und heute können wir nicht einmal hundert Codezeilen erreichen. In der Lage zu sein, dreidimensionale Szenen zu rendern, wäre es dumm, Stereopaare zu passieren. Heute werden wir so etwas zeichnen:



Die Torheit der Magic Carpet- Entwickler verfolgt mich. Für diejenigen, die es nicht gefunden haben, ermöglichte dieses Spiel das 3D-Rendering sowohl in Anaglyphen als auch in Stereogrammen in den Haupteinstellungen, die nur im Menü verfügbar sind! Dieses Gehirn explodierte nur speziell.

Parallaxe


Also fangen wir an. Warum erlaubt uns unser visueller Apparat für den Anfang, Tiefe wahrzunehmen? Es gibt so ein kluges Wort "Parallaxe". Wenn an den Fingern, dann konzentrieren wir uns auf den Bildschirm. Alles, was sich in der Ebene des Bildschirms für unser Gehirn befindet, ist in einer einzigen Kopie vorhanden. Aber wenn plötzlich eine Fliege vor dem Bildschirm fliegt, dann (wenn wir unsere Augen nicht ändern!) Wird unser Gehirn sie doppelt registrieren. Gleichzeitig teilt sich auch die Spinne an der Wand hinter dem Bildschirm, und die Richtung der Gabelung hängt davon ab, ob sich das Objekt vor oder hinter dem Brennpunkt befindet:



Unser Gehirn ist eine sehr effiziente Maschine zur Analyse leicht unterschiedlicher Bilder. Es verwendet Disparität , um Tiefeninformationen aus zweidimensionalen Netzhautbildern für Stereopsis zu erhalten . Nun, Gott segne sie mit den Worten, lasst uns besser Bilder zeichnen!

Nehmen wir an, unser Bildschirm ist ein Fenster in die virtuelle Welt :)



Unsere Aufgabe ist es, zwei Bilder mit dem zu zeichnen, was durch dieses „Fenster“ sichtbar wird. Es gibt zwei Bilder, eines für jedes Auge. In der Abbildung oben habe ich sie mit einem rot-blauen „Sandwich“ gezeigt. Lassen Sie uns noch nicht stören, wie genau wir diese Bilder dem visuellen Apparat zuführen, wir müssen nur zwei Dateien speichern. Ich bin speziell daran interessiert, wie diese Bilder mit unserem Raytracer erhalten werden können .

Angenommen, die Blickrichtung ändert sich nicht, es handelt sich um einen Vektor (0,0, -1). Angenommen, wir können die Position der Kamera um den Augenabstand verschieben. Was noch? Es gibt eine kleine Subtilität: Der Sichtkegel durch unser „Fenster“ ist asymmetrisch. Und unser Raytracer kann nur einen symmetrischen Blickkegel rendern:



Was tun? Lesen :)
Tatsächlich können wir die Bilder breiter als nötig rendern und nur den Überschuss zuschneiden:



Anaglyphe


Mit dem allgemeinen Rendering-Mechanismus sollte klar sein, dass es jetzt an der Zeit ist, uns die Frage der Bildlieferung an unser Gehirn zu stellen. Eine der einfachsten Optionen ist die rot-blaue Brille:



Wir machen nur die beiden Pre-Renderings nicht schwarz, sondern weiß, schreiben das linke Bild in den roten Kanal und das rechte Bild in blau. Sie erhalten folgendes Bild:



Rotes Glas schneidet einen Kanal ab und blaues Glas schneidet einen anderen ab, so dass jedes Auge sein eigenes Bild erhält und wir die Welt in 3D betrachten können. Hier sind die Änderungen am Haupt-Commit des ersten Artikels , in denen sowohl die Kameraeinstellungen für beide Augen als auch die Kanalbaugruppe angezeigt werden.

Anaglyphen-Renderings sind eine der ältesten Möglichkeiten, (Computer!) Stereobilder anzuzeigen. Sie haben viele Mängel, zum Beispiel eine schlechte Farbwiedergabe (versuchen Sie übrigens, den grünen Kanal des rechten Auges im grünen Kanal des endgültigen Bildes aufzuzeichnen). Ein Vorteil: Solche Gläser lassen sich leicht aus improvisierten Materialien herstellen.

Stereoskop


Mit der Verbreitung von Smartphones erinnerten wir uns daran, was Stereoskope sind (die für eine Sekunde im 19. Jahrhundert erfunden wurden)! Vor einigen Jahren schlug Google vor , zwei Penny-Objektive (leider nicht am Knie), Pappe (überall herumliegend) und ein Smartphone (in der Tasche liegend) zu verwenden, um eine ziemlich erträgliche Virtual-Reality-Brille zu erhalten:



Auf aliexpress waren es Haufen, hundert Rubel pro Stück. Im Vergleich zur Anaglyphe müssen Sie überhaupt nichts tun. Nehmen Sie einfach zwei Bilder auf und komponieren Sie sie nebeneinander. Hier ist das Commit .



Genau genommen kann je nach Objektiv eine Korrektur der Objektivverzerrung erforderlich sein, aber ich habe mich überhaupt nicht darum gekümmert und sie sieht auf meiner Brille großartig aus. Wenn Sie jedoch wirklich eine tonnenförmige Vorverzerrung anwenden müssen, die die Verzerrung des Objektivs ausgleicht, sieht dies für mein Smartphone und meine Brille folgendermaßen aus:



Stereogramme


Was aber, wenn Sie keine zusätzlichen Geräte verwenden möchten? Dann gibt es nur eine Option - zu betäuben. Im Allgemeinen reicht das vorherige Bild aus, um Stereo anzusehen. Verwenden Sie einfach den Trick, um Stereo anzusehen. Es gibt zwei Prinzipien zum Anzeigen von Stereogrammen: Bewegen Sie entweder Ihre Augen oder bewegen Sie Ihre Augen auseinander. Also habe ich ein Diagramm gezeichnet, in dem ich zeige, wie Sie das vorherige Bild betrachten können. Das vorherige Bild ist doppelt, zwei rote Balken im Diagramm zeigen zwei Bilder auf der linken Netzhaut, zwei blaue auf der rechten.



Wenn wir unsere Augen auf den Bildschirm richten, erhalten wir von vier Bildern zwei. Wenn wir unsere Augen zur Nase blinzeln, ist es durchaus möglich, dem Gehirn „drei“ Bilder zu zeigen. Und umgekehrt, wenn Sie Ihre Augen öffnen, können Sie auch "drei" Bilder erhalten. Durch Überlagerung zentraler Bilder erhält das Gehirn einen Stereoeffekt.

Diese Methoden werden verschiedenen Menschen auf unterschiedliche Weise gegeben, zum Beispiel weiß ich überhaupt nicht, wie ich meine Augen bewegen soll, aber ich züchte leicht. Es ist wichtig, dass das für eine Methode erstellte Stereogramm auf die gleiche Weise betrachtet wird, da sonst eine invertierte Tiefenkarte erhalten wird (siehe negative und positive Parallaxe). Das Problem bei dieser Methode zum Betrachten von Stereo ist, dass es sehr schwierig ist , Ihre Augen relativ zum Normalzustand stark zu bewegen, sodass Sie sich mit kleinen Bildern zufrieden geben müssen. Und was ist, wenn Sie große wollen? Lassen Sie uns die Farbe vollständig opfern und nur eine Wahrnehmung der Tiefe wollen. Mit Blick auf die Zukunft sehen Sie hier das Bild am Ende dieses Teils:



Dieses Stereogramm dient zum „Verdünnen“ der Augen (Stereogramm mit Wandaugen). Für diejenigen, die die umgekehrte Sichtweise bevorzugen, machen Sie hier ein Bild . Wenn Sie nicht an Stereogramme gewöhnt sind, probieren Sie verschiedene Bedingungen aus: ein Vollbild, ein kleines Bild, helles Licht, Dunkelheit. Die Aufgabe besteht darin, die Augen so zu öffnen, dass die beiden benachbarten Wirbelstreifen zusammenfallen. Der einfachste Weg, sich oben links zu konzentrieren, ist Sie ist flach. Zum Beispiel bin ich von der Umgebung des Habr umgeben, ich öffne das Bild im Vollbildmodus. Vergessen Sie nicht, die Maus davon zu entfernen!

Geben Sie sich nicht mit dem fehlerhaften 3D-Effekt zufrieden. Wenn Sie sich der abgerundeten Formen in der Mitte zufälliger Punkte und einiger schwacher 3D-Effekte nur vage bewusst sind, ist dies sicherlich eine unvollständige Illusion! Wenn Sie richtig aussehen, sollten die Kugeln für den Betrachter deutlich aus der Bildschirmebene herausgehen. Der Effekt sollte stabil sein und erhalten bleiben, da jeder Teil des Bildes, sowohl der Vordergrund als auch der Hintergrund, ständig und detailliert untersucht wird. Stereopsis hat Hysterese: Sobald Sie ein stabiles Bild erhalten, wird es klarer, je länger Sie schauen. Je weiter der Bildschirm von den Augen entfernt ist, desto größer ist der Tiefeneffekt.

Dieses Stereogramm wurde nach der vor einem Vierteljahrhundert von Thimbleby et al. Vorgeschlagenen Methode gezeichnet. In ihrem Artikel „ Anzeigen von 3D-Bildern: Algorithmen für Einzelbild-Zufallspunktstereogramme “.

Ausgangspunkt


Der Ausgangspunkt für das Rendern von Stereogrammen ist eine Tiefenkarte (wir haben die Farbe vergessen). Hier ist ein Commit , das ein solches Bild ergibt :



Die Tiefen in unserem Render werden durch die nahen und fernen Ebenen abgeschnitten, dh der am weitesten entfernte Punkt in meiner Karte hat eine Tiefe von 0, der nächste.

Grundprinzip


Lassen Sie unsere Augen in einem Abstand d vom Bildschirm sein. Platzieren Sie die (imaginäre) Fernebene (z = 0) im gleichen Abstand hinter dem Bildschirm. Wir wählen eine Konstante μ, die die Position der nahen Ebene bestimmt (z = 0): Sie befindet sich in einem Abstand μd von der fernen. Ich habe in meinem Code μ = 1/3 gewählt. Insgesamt lebt unsere ganze Welt in einer Entfernung von d-μd bis d hinter dem Bildschirm. Lassen Sie uns einen Abstand e zwischen den Augen definieren (in Pixel, in meinem Code habe ich 400 Pixel gewählt).



Wenn wir den Punkt unseres Objekts betrachten, der im Diagramm rot markiert ist, sollten zwei grün markierte Pixel im Stereogramm dieselbe Farbe haben. Wie finde ich den Abstand zwischen diesen Pixeln? Sehr einfach. Wenn der aktuell projizierte Punkt eine Tiefe von z hat, ist das Verhältnis der Parallaxe zum Abstand zwischen den Augen gleich dem Verhältnis der entsprechenden Tiefen: p / e = (d-dμz) / (2d-dμz). Beachten Sie übrigens, dass d schrumpft und nirgendwo anders involviert ist! Das heißt, p / e = (1 μz) / (2 μz), was bedeutet, dass die Parallaxe gleich p = e * (1 μz) / (2 μz) Pixel ist.

Das heißt, das Grundprinzip der Erstellung eines Stereogramms: Wir gehen die gesamte Tiefenkarte durch, bestimmen für jeden Tiefenwert, welche Pixel dieselbe Farbe haben sollen, und schreiben dies in unser Beschränkungssystem. Dann gehen wir von einem beliebigen Bild aus und versuchen, alle zuvor auferlegten Einschränkungen zu erfüllen.

Bereiten Sie das Originalbild vor


In diesem Stadium werden wir ein Bild vorbereiten, auf das wir später Parallaxenbeschränkungen auferlegen werden.
Hier, nimm ein Commit , er zeichnet dieses Bild:



Beachten Sie, dass die Farben im Allgemeinen nur zufällig sind, außer dass ich rand () * sin in den roten Kanal setze, um periodische Wellen bereitzustellen. Diese Wellen werden mit einem Abstand von 200 Pixeln erzeugt. Dies (mit ausgewählten μ = 1/3 und e = 400) ist der maximale Parallaxenwert in unserer Welt, es ist auch eine entfernte Ebene. Diese Wellen sind optional, erleichtern jedoch den notwendigen Fokus des Sehens.

Stereogramm rendern


Tatsächlich sieht der vollständige Code für das Stereogramm folgendermaßen aus:

int parallax(const float z) { const float eye_separation = 400.; // interpupillary distance in pixels const float mu = .33; // if the far plane is a distance D behind the screen, then the near plane is a distance mu*D in front of the far plane return static_cast<int>(eye_separation*((1.-z*mu)/(2.-z*mu))+.5); } size_t uf_find(std::vector<size_t> &same, size_t x) { return same[x]==x ? x : uf_find(same, same[x]); } void uf_union(std::vector<size_t> &same, size_t x, size_t y) { if ((x=uf_find(same, x)) != (y=uf_find(same, y))) same[x] = y; } int main() { [...] for (size_t j=0; j<height; j++) { // autostereogram rendering loop std::vector<size_t> same(width); std::iota(same.begin(), same.end(), 0); // initialize the union-find data structure (same[i]=i) for (size_t i=0; i<width; i++) { // put the constraints int par = parallax(zbuffer[i+j*width]); int left = i - par/2; int right = left + par; // works better than i+par/2 for odd values of par if (left>=0 && right<(int)width) uf_union(same, left, right); // left and right pixels will have the same color } for (size_t i=0; i<width; i++) { // resolve the constraints size_t root = uf_find(same, i); for (size_t c=0; c<3; c++) framebuffer[(i+j*width)*3+c] = framebuffer[(root+j*width)*3+c]; } } [...] 

Wenn überhaupt, dann verpflichten Sie sich hier . Die Funktion int parallax (const float z) gibt den Abstand zwischen Pixeln derselben Farbe für den aktuellen Tiefenwert an. Wir rendern das Stereogramm zeilenweise, da die Linien unabhängig voneinander sind (wir haben keine vertikale Parallaxe). Daher verläuft die Hauptschleife einfach durch alle Zeilen. Für jeden von ihnen beginnen wir mit einem vollständigen, unbegrenzten Satz von Pixeln, denen wir dann paarweise Gleichheitsbeschränkungen auferlegen, und am Ende werden wir eine bestimmte Anzahl von Clustern von (nicht verbundenen) Pixeln derselben Farbe haben. Beispielsweise sollten ein Pixel mit dem Index links und ein Pixel mit dem Index rechts am Ende identisch sein.

Wie speichere ich diese Einschränkungen? Die einfachste Antwort ist Union - Datenstruktur finden . Ich werde es nicht beschreiben, dies sind nur drei Codezeilen, Sie können es auf Wikipedia lesen. Die Hauptidee ist, dass wir für jeden Cluster einen bestimmten „Verantwortlichen“ dafür haben, es ist auch ein Wurzelpixel, wir werden es in der gleichen Farbe wie im Originalbild belassen und alle anderen Pixel im Cluster neu streichen:

  for (size_t i=0; i<width; i++) { // resolve the constraints size_t root = uf_find(same, i); for (size_t c=0; c<3; c++) framebuffer[(i+j*width)*3+c] = framebuffer[(root+j*width)*3+c]; } 

Fazit


Nun, eigentlich ist das alles. Zwanzig Codezeilen - und unser Stereogramm ist fertig, brechen Sie Augen und Köpfe, zeichnen Sie Bilder! Übrigens sind nur zufällige Farben in einem Stereogramm im Allgemeinen ein Luxus. Wenn Sie es versuchen, können Sie im Prinzip auch die Farbe unseres Bildes teilweise übertragen.

Andere Stereo-Betrachtungssysteme, zum Beispiel im Zusammenhang mit der Polarisation , habe ich aus der Diskussion herausgenommen, da sie über das Budget von einhundert Rubel hinausgehen. Wenn Sie etwas verpassen, fügen Sie hinzu und korrigieren Sie!

Source: https://habr.com/ru/post/de438646/


All Articles