Beschreibung

Die erste Aufgabe beschäftigt sich mit der Vorverarbeitung der Daten. Dieser Schritt dient dazu bestimmte Merkmale aus den erhobenen Daten hervorzuheben oder andere zu unterdrücken. Es kommt häufig vor, dass volumetrische Daten nach der Aufnahme verrauscht sind (z.B. Computertomographie-Daten). Mittels Filter ist es möglich solche Einflüsse zu reduzieren. In der Vorverarbeitung werden oft auch zusätzliche Informationen von den ursprünglichen Daten abgeleitet, welche später in der Visualisierungs-Pipeline verwendet werden, um bestimmte Merkmale der Daten besser hervorzuheben. Das Ziel dieser Übung ist es, die verschiedenen Eigenschaften von unterschiedlichen Filtern zu lernen und zu verstehen, wie sie auf einen volumetrischen Datensatz angewendet werden. Nach dieser Übung soll der Nutzen und die Notwendigkeit dieses Schritts in der Visualisierungs-Pipeline klar sein.

Exercise  1

Smoothing Filter gehören wohl zu den beliebtesten Algorithmen in der Signalverarbeitung. Im Allgemeinen ist es ihr Ziel das Rauschen zu unterdrücken und gleichzeitig das Signal so gut es geht zu erhalten. Das Filtern erfolgt in der Regel mittels einer Faltung des Signals mit einer Filter Funktion (auch Kernel genannt). Bei volumetrischen Daten bedeutet das Filtern, dass jedes Voxel mit einem neuen Wert ersetzt wird, welcher sich aus einer gewichteten Summe aller Voxel im Bereich des Kernels errechnet. Der tatsächliche Wert hängt dabei von der Filterfunktion und der Kernelgröße ab. In diesem Beispiel werden drei verschiedene Filterfunktionen verwendet:
  • Average Filter
  • Gauß Filter
  • Bilateraler Filter (Zusatzaufgabe)
Ziel der Aufgabe ist es ein Verständnis für die verschiedenen Filterfunktionen zu erhalten und wie man sie am besten einsetzt. Im Zuge der Übung ist es erforderlich einige Elemente der Filterungen zu implementieren. Zu den Einzelheiten siehe die Liste der Aufgaben weiter unten.

Neben dem Smoothing der Daten soll in dieser Übung auch ein zusätzliches Merkmal aus den Daten extrahiert werden, der Gradient. Der Gradient beschreibt die Richtung der größten Änderung in den Datenwerten an einer bestimmten Stelle des Volumens. Der Gradient wird häufig in einem Vorverarbeitungsschritt berechnet damit man sich die wiederholte Berechnung in weiteren Schritten der Visualisierungs-Pipeline erspart. In der Visualisierung 1 Übung wird der Gradient in Exercise 2 und 3 benötigt, um die Visualisierung zu verbessern.

Die Berechnung der Gradienten kann im Allgemeinen auch als ein Filterprozess mittels Faltung gesehen werden. Es dabei aber ein spezieller Kernel verwendet welcher den Gradienten extrahiert. Ähnlich wie beim Smoothing gibt es auch beim Extrahieren der Gradienten verschiedene Methoden welche sich durch ihre Komplexität und der Qualität der Ergebnisse unterscheiden. In dieser Übung werden drei verschiedene Methoden behandelt:
  • Rückwärts-Differenzen-Methode
  • Zentral-Differenzen-Methode
  • Sobel Methode
In den einzelnen Aufgaben müssen einzelne Berechnungen für das Extrahieren der Gradienten implementiert werden.

Sowohl das Smoothing als auch das Extrahieren der Gradienten kann mittels einer 3D Faltung mit den entsprechenden Filtern durchgeführt werden. Als Ergebnis erhalten wir nach diesen Faltungen ein neues Volumen welches in vier Komponenten den Datenwert (evtl. mit Smoothing) und die drei Vektorkomponenten des Gradienten enthält. Dieses Volumen wird dann in den weiteren Schritten der Visualisierungs-Pipeline verwendet. Für die Implementierung ist es nur notwendig einige Code Fragmente zu vervollständigen. Das Verwalten und Übergeben der Daten übernimmt das vorhandene Framework.

Zur Architektur des Plugins:

Im C++ Code kann auf jeden Skalarwert an jedem Voxel im Originaldatensatz zugegriffen werden. Der neu errechnete Wert nach der Filter Funktion wird in ein Ausgabe-Volumen geschrieben. Abhängig vom Filter-Type kann auf den Skalarwert entweder mittels Transformer oder einem Iterator zugegriffen werden. Für Filter mit einer fixen Kernel-Größe wird der Transformer verwendet. Bei einer variablen Kernel-Größe erweist sich der Iterator als bessere Wahl. Der Algorithmus für manche Filter mit einer fixen Kernel-Größe (z.B. Zentral-Differenzen-Methode) wird daher in der transform()-Methode implementiert. Im Falle eines Filters mit variierender Größe (z.B. Gauß Filter) wird die Faltung in einem Iterator implementiert.

Der Code welcher in dieser Exercise erweitert werden soll befindet sich in der EditorVislabFilterExcercise.cpp|h Datei. Nach der Implementierung soll es möglich sein die verschiedenen Parameter für die Filter mittels der GUI Elemente des dazugehörigen Plugins zu kontrollieren.

Programmieraufgaben

TODOBeschreibung
1 Gradient by Central Differences:
Im ersten Task sollten die Gradienten im Volumen mittels der Zentralen-Differenzen-Methode (central difference) berechnet werden. An der jetzigen Stelle für diese Berechnung im Code steht die Berechnung mittels der Rückwärts-Differenzen-Methode (backward difference). Diese soll so erweitert und verändert werden dass anstatt der Rückwärts-Differenz die Zentral-Differenz für die Berechnung verwendet wird. Die Implementierung erfolgt in der Methode transform in der CentralDifferenceGradientFilter Klasse.

In der Übung ist das Volumen so definiert, dass jedes Voxel 4 Werte enthält. Mittels der Methode Get(int index) kann man auf einen dieser Werte zugreifen. Der Voxelwert mit dem Index 3 entält den (möglicherweise gefilterten) Datenwert. Die Voxelwerte mit den Indices von 0 bis 2 enthalten die drei verschiedenen Gradientenrichtungen (x, y und z). Diese müssen bei diesem Task neu berechnet werden.

Weitere Informationen zur Berechnung der endlichen Differenzen-Methode im Allgemeinen: http://en.wikipedia.org/wiki/Finite_difference

Weitere Informationen zur Berechnung der Zentral-Differenz:
Eindimensionaler Fall und mehrdimensionaler Fall
2 Gradient by Sobel Filter:
In diesem Task soll ein Sobel Kernel zur Berechnung der Gradienten implementiert werden. Die meisten Teile der Implementierung des Sobel Kernels sind bereits im Code enthalten. Die Aufgabe besteht darin die fehlenden Werte für die y-Richtung einzutragen. Der Task muss in der Methode transform der Klasse SobelGradientFilter gelöst werden.

Weitere Informationen über den Sobel Operator: Sobel Operator
3 Implement 3D Convolution:
Faltung ist die Operation die zum Filtern von Daten mittels eines Filter Kernels von beliebiger Größe verwendet wird (z.B. Gauß Filter, Durchschnittsfilter). Für volumetrische Daten ist es notwendig eine drei dimensionale Version der Faltungsoperation zu implementieren, damit die Faltung ein korrektes Ergebnis liefert. Die Faltung, welche zurzeit in der Methode computeConvolution implementiert ist, führt die Faltung nur in zwei Dimensionen auf einzelnen Schichten durch. Daher sind die resultierenden Werte nach dem Filtern auch sehr niedrig, da der Kernel schon für den dreidimensionalen Fall normiert ist.
Die Aufgabe in diesem Task besteht nun darin die Faltung auf drei Dimensionen zu erweitern. Als Resultat sollte man beim Average-Filter dieselben Ergebnisse bekommen wie in der Referenzlösung.

Hinweis: Nicht darauf vergessen den linear_index auch auf 3 Dimensionen (z.B. k*slice + j*row + i) zu erweitern, da dieser beim Gaußschen Filtern benötigt wird.

Weitere Informationen über die Faltung: Diskrete Faltung
4 Compute the correct Size of the Gaussian Smoothing Filter Kernel:
Ein Filter-Kernel für einen Gauß-Filter wird mittels der Gaußfunktion berechnet. Die Größe des Filters hängt dabei vom sigma Parameter ab. In diesem Task sollte die korrekte Minimalgröße in der Methode computeGaussianKernel( float fSigma ) berechnet werden.

Mehr Informationen zum Gauß-Filter und der Berechnung der geeigneten Filtergröße findet sich hier: Gauß-Filter
5 Fill a Gaussian Kernel with Real Values:
Ein Kernel für den Gauß-Filter wird mittels der mathematischen Formel der Gaußfunktion berechnet. Die Berechnung der einzelnen Werte für den 3D Filter Kernel erfolgt in der Methode computeGaussianKernel( float fSigma, int iWidth, int iHeight, int iDepth ). Das Sigma für die Berechnung wird über das GUI geliefert. Die Werte iWidth, iHeight und iDepth liefern die Größe des Kernels.

Weitere Informationen über den Gauß-Filtern: Gauß-Filter
und die Gauß-Filter-Kernel: Gauß-Filter-Kernel.
BONUS Implement 3D Bilateral Filter:
Smoothing Filter (z.B. Gauß Filter) dienen dazu Rauschen aus den Daten zu filtern. Jedoch haben sie auch den Nachteil, dass Details (wie etwa Kanten) unscharf werden. Das bilaterale Filtern ist eine einfache, nicht-iterative Methode für das kanten-erhaltende Filtern. In der Zusatzaufgabe sollte diese Methode implementiert werden. Die dazugehörige Stelle im Code findet sich bei TODO BONUS.

Mehr Informationen zum bilateralen Filtern kann im Originalpaper gefunden werden: Bilateral Filter
Zusätzlich könnten diese Folien über das bilaterale Filtern von Nutzen sein: Bilateral Filter Folien

User Interface

Folgende GUI-Parameter stehen zur Verfügung um das Filtern und die Gradientenberechnung zu beeinflussen:
NameEffektZeigt Auswirkungen
Auto-RecomputeWenn diese Option aktiviert ist wird eine Berechnung des gefilterten Volumens nach Änderung eines Parameters automatisch gestartet. Wenn es inaktiv ist, werden keine Berechnungen durchgeführt bis die Option wieder aktiviert wird. Der Fortschritt des Filterprozesses wird am unteren Rand in einer Progress-Bar dargestellt.immer
Gradient FilterMethode welche zur Berechnung der Gradienten verwendet wird.ab Task 1
Smoothing FilterMethode welche zum Smoothen der Daten verwendet wird. Bei None werden die Eingangsdaten gar nicht geglättet.ab Task 3
Gaussian - SigmaDie Standardabweichung für den Gauß-Filter. Diese Option ist nur aktiv wenn Gaussian als Smoothing-Methode ausgewählt ist.ab Task 4
Bilateral - Sigma DomainStandardabweichung für die räumliche Domäne beim bilateralen Filtern.ab BONUS
Bilateral - Sigma RangeStandardabweichung für den Intensitätsbereich beim bilateralen Filtern.ab BONUS