Donnerstag, 4. September 2014

Dual-Energy Radiographie

Grundlagen

Die Möglichkeiten verschiedene Gewebedichten in Röntgenstrahlung darzustellen sind begrenzt. Knochen haben eine wesentlich höhere Dichte als Gewebe. Das führt bei Röntgenaufnahmen zum Abdecken von Gewebeinformationen. Eine Methode diese Informationen zu erhalten ist, die Knochenstrukturen in Röntgenaufnahmen zu isolieren und zu subtrahieren. Diese Technik wird Dual-Energy Radiologie genannt, da zwei Aufnahmen mit unterschiedlicher Strahlungsenergie dafür benötigt werden. Eine Aufnahme mit geringer Energie bildet Gewebestrukturen und Knochen ab. Eine zweite Aufnahme mit höherer Energie bildet nur Knochenstrukturen ab. Mit Hilfe der Dämpfungskoeffizienten der verschiedenen Gewebe bei verschiedener Energie können die Dicken der Gewebeschichten ermittelt werden.


Dämpfungen von Knochen und Gewebe bei verschiedenen Energien [0]


Berechnung

Die Intensität einer digitalen Röntgenaufnahme wird für jedes Pixel bestimmt als:
Ilo=μtloxt+μbloxb

Und
Ihi=μthixt+μbhixb

Wobei mit μtlo der lineare Dämpfungskoeffizient der niederenergetischen Röntgenstrahlung in Gewebe , mit xt die Gewebedicke, mit \mu_{blo} der lineare Dämpfungskoeffizient der Knochenstruktur bei niederenergetischen Röntgenstrahlung und mit xb der Dicke der Knochenstruktur bezeichnet wird. Ebenfalls gelten diese Werte für die Hochenergetische Strahlungsaufnahme mit μthi und μbhi als Dämpfungskoeffizienten. Beide dieser Bilder beinhaltet Informationen über Knochendicke und Gewebedicke.

Wenn nun die gewichtete Addition beider Bilder mit dem Korrekten Faktor klo oder khi durchgeführt wird:
I=kloIlo+khiIhi
(1)
Kann entweder die Kochenstruktur, oder die Gewebestruktur ausgebledet werden.
Aus (1) ergibt sich
I=(kloμtlo+khiμthi)xt+(kloμblo+khiμbhi)xb

 Bei korrekter Wahl der Koeffizienten kann zum Beispiel xt=0 erreicht werden und das Gewebe aus der Aufnahme ausgeblendet werden.
kloμtlo+khiμthi=0. Daher, kloμtlo=khiμthi, und
khiklo=μtloμthi


Dies zeigt, dass das Ausblenden der Gewebestruktur im Ergebnisbild erreicht werden kann, wenn das Verhältnis der Faktoren das negative Verhältnis von Gewebe bei beiden Strahlungsenergien ist. Gleiches gilt für das Ausblenden der Knochenstruktur.

Software

Das ganze wird nun in Software abgebildet [1]. Es stehen zwei Röntgenaufnahmen mit unterschiedlichem Energiewerten zur Verfügung. Die Aufnahmen sind im 8bit BMP Format abgespeichert. Jedes Pixel hat also einen Wert von 0 ... 255. Beide Bilder werden als Bitmap-Objekt geladen:
Bitmap e1 = new Bitmap("bild1.bmp");
Bitmap e2 = new Bitmap("bild2.bmp");
double[,] b = new double[e1.Width, e1.Height];
int[,] i = new int[e1.Width, e1.Height];
Bitmap r = new Bitmap(e1.Width, e1.Height,PixelFormat.Format8bppIndexed); // Ergebnisbild
BitmapData b1 = e1.LockBits(new Rectangle(0,0,e1.Width,e1.Height), ImageLockMode.ReadOnly, e1.PixelFormat);
BitmapData b2 = e2.LockBits(new Rectangle(0,0,e2.Width,e2.Height), ImageLockMode.ReadOnly, e2.PixelFormat);
BitmapData res = r.LockBits(new Rectangle(0,0,r.Width,r.Height), ImageLockMode.ReadOnly, r.PixelFormat);
view raw gistfile1.cs hosted with ❤ by GitHub

Um auf den Speicherbereich der Bitmap-Objekte zugreifen zu dürfen, müssen diese daraufhin gesperrt werden. Mit einem direkten Zugriff auf die Speicherbereiche der beiden Bilder kann eine Schleife schneller jeden Pixelwert bearbeiten, als würde jeder Pixel einzeln geladen werden müssen.

Um die Werte abspeichern zu können steht noch ein Array mit double Werten und eins mit int Werten zur Verfügung. Der erste Schritt ist es die beiden Bilder zu addieren. Dabei werden die Pixelwerte des niederenergetischen Bildes mit dem Faktor klo multipliziert und die Werte des hochenergetischen Bildes mit khi.
Anschließend wird der Minimal und Maximalwert des Ergebnisses ermittelt und die neuen Werte in das Integer-Array eingetragen.
// pointer to image memory
byte * i1Scan = (byte*) b1.Scan0.ToPointer();
byte * i2Scan = (byte*) b2.Scan0.ToPointer();
byte * irScan = (byte*) res.Scan0.ToPointer();
for (int x = 0; x < e1.Width; x++) for (int y = 0; y < e1.Height; y++)
{
byte in1 = *(i1Scan + y * b1.Stride + x);
byte in2 = *(i2Scan + y * b2.Stride + x);
// hier ein - anstatt + da (k_hi/k_lo) = - (µ_tlo/µ_thi)
b[x, y] = (klo * in1) - (khi * in2);
}
view raw gistfile1.cs hosted with ❤ by GitHub

Das Integer-Array dient als Quelle für die Ergebnisbilddaten und nach erfolgreichem Kopieren derselben können die drei Speicherbereiche wieder freigegeben werden.

for (int x = 0; x &lt; e1.Width; x++) for (int y = 0; y &lt; e1.Height; y++)
{
i[x, y] = (int)(map(b[x, y], min, max)+0.5);
}
view raw gistfile1.cs hosted with ❤ by GitHub

---
[0] http://www.icru.org/
[1] https://github.com/DasBasti/dual-energy-imaging

Keine Kommentare:

Kommentar veröffentlichen