3D-(Voxel-/)Schnittbilder(MRT) Visualisieren (OpenGL 4.3)



  • Heyho dot,

    Danke für die Antwort 😉

    Hilft mir auf jeden Fall schon mal weiter,
    allerdings nur für den weitere Tests mit anderen Verfahren.

    Ich möchte eigentlich erstmal nur einen "naiven"- (und offensichtlich schlechten) Ansatz implementieren um ihn als Vergleichsverfahren in die Arbeit mit ein zu beziehen.
    Ich habe meine z-Schichten mit der größe x*y..

    Ist der Farbwert meiner Schicht größer 0 möchte ich diesen als Voxel der Größe 1*1*Abtastbreite an der stelle (x,y,z) in meine Scene malen.

    Die Ursprungs frage ist jetzt eigentlich: Wie male ich den Voxel in OpenGL.

    mit Direct-Volume-Rendering verlasse ich schon wieder den "naiven"-Ansatz einfach Voxel zu male und gehe schon wieder einen (durchaus sinnvollen und Intelligenten) Schritt weiter.
    Ähnlich wie bei Marching-Cubes.

    Lieben Gruß



  • Marching Cubes kann lediglich Isoflächen extrahieren, das ist etwas völlig anderes als DVR, aber ok 😉

    Ein ganz einfacher Ansatz wäre wohl etwas basierend auf Slicing, so wie z.B. hier beschrieben: http://http.developer.nvidia.com/GPUGems/gpugems_ch39.html


  • Mod

    JangoK schrieb:

    Die Ursprungs frage ist jetzt eigentlich: Wie male ich den Voxel in OpenGL.
    ..
    Ähnlich wie bei Marching-Cubes.

    wenn dass das ziel ist, generieren ein mesch. lege einfach eine box pro 'vollen' voxel ab, wobei du keine seite der box ablegst wenn sie zu einem anderen vollen voxel gehoert. das duerfte einfach zu implementieren sein und auf heutigen GPUs vermutlich schneller laufen als man denkt 😉



  • Ok,

    danke euch beiden.

    Damit kann ich arbeiten 😉

    Lieben Gruß

    Jango



  • Sry für Doppelposting ^^

    Also nochmal für mich zum Verständnis und für alle anderen die es Interessiert und über Google hier drauf Stoßen.

    Ausgangspunkt sind 3D-Schicht-Daten wie sie z.B. ein MRT liefert.
    Sprich 2D-Schichten und davon "z-viele".

    Um diese zu Visualisieren gibt es 2 Wege.

    Der eine ist das Indirect Volume Rendering.

    Worunter der von mir angedachte "Naive"-Ansatz fällt.
    Dieser heißt dann meinen Recherchen zur Folge. "Cuberille-Approach"
    Unter diesen Punkt würde auch das Marching-Cube Fallen.

    Dieser Ansatz beschäftigt sich damit, aus den 2D-Schicht Daten wieder ein 3D-Gittermodell zu erstellen welches dann einfach Visualisiert werden kann.

    Vorteil - Kann schneller mit Gerechnet werden und leichter manipuliert werden.

    Der zweite ist der von dot angesprochene... das Direct Volume Rendering

    Dieser beschäftigt sich damit, wie man die 2D-Schichten Visualisieren kann ohne sie vorher in ein 3D-Modell zurück zu rechnen.

    Das wird z.B. gemacht indem man die 2D-Schichten als Textur Implementiert unter Hintereinander ablegt und dann per Verfahren wie Ray-Casting auf eine 2D-Schicht abbildet. (Wie Osbios es ansprach)

    Problem, dass ich hierbei sehe ist die Rotation um genau 90°, da kommt es bei der Visualisierung zu einer Lücke, weil die 2D-Schichten keine Tiefe haben.

    In der Literatur, die ich Online gefunden und einsehen konnte habe ich dafür die Lösung noch nicht gefunden, oder einfach nicht wirklich verstanden 😉

    Hab mir jetzt allerdings ein Buch bestellt, was hoffentlich nochmal ein bisschen Klarheit in die ganze Sache bringt.

    Buch: http://www.amazon.de/Real-Time-Volume-Graphics-Christof-Rezk-Salama/dp/1568812663/ref=sr_1_1?ie=UTF8&qid=1405080834&sr=8-1&keywords=Real-Time+Volume+Graphics

    Falls ich hier irgendwas falsches Schreibe, bitte korregiert mich 🙂

    Lieben Gruß

    Jango



  • eigentlich renderst du nicht die schichten der textur, sondern schichten in die tiefe vom view-cone. du passt dabei die indizierung der textur so an, dass die UVs inverse rotiert sind zur camera rotation. natuerlich benutzt du dafuer dann eine 3d textur, keine z * 2d texturen.



  • JangoK schrieb:

    Der zweite ist der von dot angesprochene... das Direct Volume Rendering

    Dieser beschäftigt sich damit, wie man die 2D-Schichten Visualisieren kann ohne sie vorher in ein 3D-Modell zurück zu rechnen.

    Das wird z.B. gemacht indem man die 2D-Schichten als Textur Implementiert unter Hintereinander ablegt und dann per Verfahren wie Ray-Casting auf eine 2D-Schicht abbildet. (Wie Osbios es ansprach)

    Problem, dass ich hierbei sehe ist die Rotation um genau 90°, da kommt es bei der Visualisierung zu einer Lücke, weil die 2D-Schichten keine Tiefe haben.

    3d Texturen sampelt man mit 3d-coordinaten.
    Man kann dabei einen normalen linear filter anwenden.
    Anstelle von 4 Texeln wie bei einer 2d Textur werden bei 3d Texturen 8 Texel gelesen.



  • JangoK schrieb:

    Das wird z.B. gemacht indem man die 2D-Schichten als Textur Implementiert unter Hintereinander ablegt und dann per Verfahren wie Ray-Casting auf eine 2D-Schicht abbildet. (Wie Osbios es ansprach)

    Problem, dass ich hierbei sehe ist die Rotation um genau 90°, da kommt es bei der Visualisierung zu einer Lücke, weil die 2D-Schichten keine Tiefe haben.

    In der Literatur, die ich Online gefunden und einsehen konnte habe ich dafür die Lösung noch nicht gefunden, oder einfach nicht wirklich verstanden 😉

    Was haelt Dich davon ab, entsprechende Texturen in x, y und z Richtung zu erzeugen? Du koenntest die dann gleichzeitig darstellen oder einfach immer die nehmen, die fuer den Blickwinkel am Besten passen. Zumindest wuerdest Du so diese "Luecke" ganz einfach umgehen.



  • Gregor schrieb:

    Was haelt Dich davon ab, entsprechende Texturen in x, y und z Richtung zu erzeugen? Du koenntest die dann gleichzeitig darstellen oder einfach immer die nehmen, die fuer den Blickwinkel am Besten passen. Zumindest wuerdest Du so diese "Luecke" ganz einfach umgehen.

    Nunja, einerseits ist es unnötig weil es 3D Texturen gibt.
    Andererseits ist die Schwachstelle dieser Methode der benötigte Speicher und man würde so die dreifache menge Speicher benötigen.



  • Heyho Osbios, heyho Gregor, heyho Community,

    ich hab jetzt ein wenig weiter Recherchiert und gelesen und habe mich dazu entschieden beide Vorschläge von Euch zu Implementieren und in meiner Arbeit auf zu nehmen.

    Das generelle Vorgehen bei den beiden Verfahren habe ich auch soweit verstanden.
    Lediglich zu Implementierung hätte ich noch eine Frage.

    Als Daten habe ich einen Stapel von 2D-Bildern vorliegen.
    Dieser würde beim 2D-Texture-Based-Volume-Rendering ja exakt den Textur-Daten einer Achse entsprechen.

    Wie Berechne ich mir aus diesem Datensatz sinnvolle Datensätze für die anderen beiden Achsen?

    Da steh ich grad noch was auf dem Schlauch 😉

    Wäre gut, wenn mir da jemand weiterhelfen könnte ^^

    Lieben Gruß


  • Mod

    JangoK schrieb:

    Wie Berechne ich mir aus diesem Datensatz sinnvolle Datensätze für die anderen beiden Achsen?

    auch fuer den fall dass ich mich wiederhole:

    raps schrieb:

    eigentlich renderst du nicht die schichten der textur, sondern schichten in die tiefe vom view-cone. du passt dabei die indizierung der textur so an, dass die UVWs inverse rotiert sind zur camera rotation. natuerlich benutzt du dafuer dann eine 3d textur, keine z * 2d texturen.



  • Hallo rapso,

    meine Frage setzt allerdings etwas früher an (wenn ich mich nicht Irre).

    Meinen Recherchen zufolge ist es notwendig die durch die Aufnahme vom MRT diskretisierten Daten des Objektes wieder zurück zu Rechnen, da gegebenenfalls auch Daten zwischen den Abtast-Schichten des MRT benötigt werden.
    Unabhängig von 2D oder 3D Textur.

    Methoden zur Rekonstruktion der Daten habe ich mittlerweile allerdings auch gefunden. Beschrieben und verglichen werden einige im Paper von Marschner et. al. "An Evaluation of Reconstruction Filters for Volume Rendering".

    Tut mir leid, falls die Frage unklar formuliert war.

    Lieben Gruß


  • Mod

    ich dachte dir ging es darum den existierenden scan zu visualisieren. daten zwischen den pixeln zu interpolieren klingt nach einem ganz anderem topic.

    wie waere es wenn du erst die visualisierung loest? wenn das geht, kannst du die daten immer noch erweitern. zuviel auf einmal kann am ende dazu fuehren dass nichts da ist 😉



  • Heyho rapso,

    du hast schon recht, mir geht es darum verschiedene Visualisierungs-Verfahren für MRT-Schichtdaten zu implementieren und zu vergleichen.

    In der Literatur steht allerdings beschrieben, dass zur Visualisierung mittels Direct-Volume-Rendering vorher eine Rekonstruktion und Klassifikation der Schichtdaten vorgenommen werden muss. Ansonsten kann Beispielsweise das 2D und/oder 3D-Texture-Based-Rendering garnicht vorgenommen werden, da Werte fehlen um die notwendigen Render-Schichten zu erzeugen.

    Daher muss ich scheinbar um das Problem der Visualisierung zu lösen, erst einmal das Problem der Rekonstruktion und Klassifizierung lösen. ^^



  • Du musst nicht unbedingt interpolieren.

    Wenn Du Direct Volume Rendering betreibst und dafür einen Raycasting-Algorithmus verwendest, dann ist letztendlich die Frage, wie Du den "Strahl" diskretisierst. Du kannst natürlich sagen, dass Du einen Strahl hast, der die Voxel nicht genau trifft und deshalb muss immer zwischen verschiedenen Voxeln interpoliert werden. Du könntest aber auch einen Bresenham Linienalgorithmus zur Erzeugung des Strahls verwenden. Der liefert Dir einen Strahl in Form von einer Menge diskreter Koordinaten, an denen sich jeweils ein Voxel befindet. Das Resultat davon ist möglicherweise um Nuancen schlechter als ein Algorithmus, der mit Interpolation arbeitet, dafür ist er aber auch wesentlich schneller. Du brauchst dort eben keine Interpolation und zudem läuft das Erzeugen der Linie mit Ganzzahlarithmetik.

    Ich habe vor langer Zeit auch mal etwas mit Direct Volume Rendering rumgespielt und dafür so einen Bresenham Algorithmus verwendet. Herausgekommen sind Darstellungen wie die da:

    https://i.imgur.com/i7oXNBq.png

    Ist vielleicht etwas grobpixelig. Andererseits wird das pixelige nicht direkt etwas mit dem Bresenham-Algorithmus zu tun haben.


  • Mod

    @JangoK

    mir ist nicht ganz klar was du rekonstruieren bzw klassifizieren willst. fuer die visualisierung sind eigentlich nur die schnittbilder noetig und die hast du, wie du sagtest.
    dann muss man das nur auf die GPU laden und raycastern wie z.B. bei http://demos.vicomtech.org/volren/ zu sehen (ein browser mit WebGL ist noetig).



  • @rapso

    Generell hast du recht.
    Angenommen ich möchte Raycasten kann ich das wie Gregor auch schon beschrieben hat vollkommen ohne Interpolation/Rekonstruktion machen.

    Allerdings geht es mir weniger darum irgend einen Algorithmus zu implementieren.
    Sondern mehr darum mehrere mögliche Verfahren zu beschreiben, zu testen und dann Anhand der Ergebnisse zu Vergleichen um begründen zu können warum ich mich für Verfahren XY entschieden habe.

    Zu den Verfahren gehört unter anderem auch das Raycasting, welches als Bildbasiertes Verfahren gilt.

    Allerdings gibt es im Bezug auf Direct-Volume-Rendering noch verfahren wie Splatting, welches Objektbasiert ist, oder Shear-Warp und Texture-Mapping, welche Mischformen sind.

    Bei diesen Verfahren ist dann eine Interpolation/Rekonstruktion der Daten notwendig.

    Und bei allen Verfahren ist eine Klassifikation notwendig, auch beim Raycasting.
    Denn die Definition der Objekteigenschaft (Grauwert XY ist transparent etc) ist ein Teil der Klassifikation.

    Des Weiteren gibt es auch noch das Indirect-Volume-Rendering. Wo dann Verfahren wie Marching-Cubes eine Rolle spielen um Oberflächen Approximationen zu erzeugen.

    Gruß

    Jango


  • Mod

    ich nehme an mit klassifizierung meinst du die transfer function, die wird oft nicht vor dem rendern gemacht, sondern waehrend des rendern, da grauwerte sehr viel kompakter sind und der zugriff auf das volume das performance kritischte ist (meistens). natuerlich ist das resultat etwas anders, je nachdem ob erst die transfer function oder erst die interpolation durchgefuehrt wird.

    wenn du also verfahren vergleichst, beachte die reihenfolge bei denen (vielleicht ist pre- und post- klassifizierung sogar etwas, was wert waere verglichen zu werden).

    und vergiss nicht ein paar schoene bilder davon in unseren screenshot thread zu posten 😉

    http://www.c-plusplus.net/forum/191889-160



  • Heyho, ich schon wieder 😉

    Ich hab den Theorie-Teil jetzt soweit abgeschlossen und bin gerade dabei (zu versuchen) das 3D-Based-Texture-Mapping zu implementieren.

    Allerdings habe ich keine Idee wie ich auch nur an nährend diese Blickrichtungsorientierten 2D-Schichten berechnen soll...

    Ich hab dazu viel theorie gefunden, aber kA wie ich das jetzt in die Praxis umsetzten kann. wäre nett wenn jemand mir da helfen könnte.

    Die Fragen sind also:

    Wie bestimme ich die bounding-Box um meine Textur?

    Wie berechne ich die Schichten auf die ich meine Textur ziehe aus dieser bounding-Box?

    Ich habe einen Ansatz mit Marching-Cubes gefunden.
    Den verstehe ich aber auch nicht so ganz um ihn selbst nach implementieren zu können..

    http://www.vmg.cs.bangor.ac.uk/Papers/05CGGM.pdf

    z.B. was bedeuten die Zahlen im Index bei GL_MODELVIEWMATRIX und woher kommt diese magische Tabelle die auf all meine Probleme Lösungen bietet? ^^

    Ich hoffe ihr könnt mir auch hier behilflich sein 🙂



  • Moin,

    ich beschäftige mich schon seit Jahren mit dem Thema und ich würde Dir raten das Rad nicht neu zu erfinden wenn Du nicht unbedingt musst.

    Es gibt da ein sehr gutes Toolkit namens VTK von Kiteware. Das basiert auf OpenGL ist auch noch OpenSource. Das bietet Dir alles was Du brauchst.
    Damit kannst Du Surfacerendern mit MarchingCubes, Raycasten und Schnittbilder erzeugen. Die haben sehr viele Beispiele und ich hatte damals schnell Ergebnisse.

    So kannst Du Dich auf Deine Visualisierung konzentrieren, denn die ist bei MRT Daten nicht so einfach wie beim CT mit der Hounsfield scala. Die Schnittbilder mal außen vor, musst Du bei den anderen Verfahren schon wissen was Du hervorheben möchtest(Knochen, Weichteile ...) und welche Voxel- Wertebereiche diese Strukturen in Deiner Serie haben.

    Ich denke für den Anfang werden Dir die Reslice Geschichten im VTK schon gut helfen. Und der Source Code ist recht leserlich, falls Du wissen willst wie die das machen.

    Ich hoffe es hilft Dir
    Gruß Andi


Anmelden zum Antworten