Ich habe in letzter Zeit mit tomographischen Rekonstruktionsalgorithmen herumgespielt. Ich habe bereits gute Implementierungen von FBP, ART, einem SIRT / SART-ähnlichen iterativen Schema und sogar der Verwendung von linearer Algebra (langsam!). Bei dieser Frage geht es nicht um eine dieser Techniken . Antworten in der Form "Warum sollte es jemand so machen, hier ist ein FBP-Code" sind nicht das, wonach ich suche.
Das nächste, was ich mit diesem Programm machen wollte, war " Komplettieren " und Implementieren der sogenannten " Fourier-Rekonstruktionsmethode ". Mein Verständnis ist, dass Sie eine 1D-FFT auf das Sinogramm "Exposures" anwenden, diese als radiale "Speichen eines Rades" im 2D-Fourier-Raum anordnen (dies ist eine nützliche Sache, die sich direkt aus dem zentralen Slice-Theorem ergibt). interpolieren Sie von diesen Punkten zu einem regelmäßigen Gitter in diesem 2D-Raum, und dann sollte es möglich sein, die Fourier-Transformation umzukehren, um das ursprüngliche Scan-Ziel wiederherzustellen.
Klingt einfach, aber ich habe nicht viel Glück gehabt, Rekonstruktionen zu bekommen, die in etwa wie das ursprüngliche Ziel aussehen.
Der folgende Python-Code (numpy / SciPy / Matplotlib) handelt von dem prägnantesten Ausdruck, den ich mir ausdenken konnte. Beim Ausführen wird Folgendes angezeigt:
Abbildung 1: das Ziel
Abbildung 2: Ein Sinogramm des Targets
Abbildung 3: Die FFT-ed-Sinogrammzeilen
Fig. 4: Die oberste Zeile ist der 2D-FFT-Raum, der aus den Fourier-Domain-Sinogrammzeilen interpoliert wird. Die untere Reihe ist (zu Vergleichszwecken) die direkte 2D-FFT des Ziels. Dies ist der Punkt, an dem ich anfange, misstrauisch zu werden; Die aus den Sinogramm-FFTs interpolierten Diagramme ähneln den durch direktes 2D-FFTing des Ziels erstellten Diagrammen ... und sind dennoch unterschiedlich.
Abbildung 5: Die inverse Fourier-Transformation von Abbildung 4. Ich hätte gehofft, dass dies als Ziel etwas besser erkennbar ist als es tatsächlich ist.
Irgendwelche Ideen, was ich falsch mache? Ich bin mir nicht sicher, ob mein Verständnis der Fourier-Methodenrekonstruktion grundlegend fehlerhaft ist oder ob mein Code nur einen Fehler enthält.
import math
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate
import scipy.fftpack
import scipy.ndimage.interpolation
S=256 # Size of target, and resolution of Fourier space
A=359 # Number of sinogram exposures
# Construct a simple test target
target=np.zeros((S,S))
target[S/3:2*S/3,S/3:2*S/3]=0.5
target[120:136,100:116]=1.0
plt.figure()
plt.title("Target")
plt.imshow(target)
# Project the sinogram
sinogram=np.array([
np.sum(
scipy.ndimage.interpolation.rotate(
target,a,order=1,reshape=False,mode='constant',cval=0.0
)
,axis=1
) for a in xrange(A)
])
plt.figure()
plt.title("Sinogram")
plt.imshow(sinogram)
# Fourier transform the rows of the sinogram
sinogram_fft_rows=scipy.fftpack.fftshift(
scipy.fftpack.fft(sinogram),
axes=1
)
plt.figure()
plt.subplot(121)
plt.title("Sinogram rows FFT (real)")
plt.imshow(np.real(np.real(sinogram_fft_rows)),vmin=-50,vmax=50)
plt.subplot(122)
plt.title("Sinogram rows FFT (imag)")
plt.imshow(np.real(np.imag(sinogram_fft_rows)),vmin=-50,vmax=50)
# Coordinates of sinogram FFT-ed rows' samples in 2D FFT space
a=(2.0*math.pi/A)*np.arange(A)
r=np.arange(S)-S/2
r,a=np.meshgrid(r,a)
r=r.flatten()
a=a.flatten()
srcx=(S/2)+r*np.cos(a)
srcy=(S/2)+r*np.sin(a)
# Coordinates of regular grid in 2D FFT space
dstx,dsty=np.meshgrid(np.arange(S),np.arange(S))
dstx=dstx.flatten()
dsty=dsty.flatten()
# Let the central slice theorem work its magic!
# Interpolate the 2D Fourier space grid from the transformed sinogram rows
fft2_real=scipy.interpolate.griddata(
(srcy,srcx),
np.real(sinogram_fft_rows).flatten(),
(dsty,dstx),
method='cubic',
fill_value=0.0
).reshape((S,S))
fft2_imag=scipy.interpolate.griddata(
(srcy,srcx),
np.imag(sinogram_fft_rows).flatten(),
(dsty,dstx),
method='cubic',
fill_value=0.0
).reshape((S,S))
plt.figure()
plt.suptitle("FFT2 space")
plt.subplot(221)
plt.title("Recon (real)")
plt.imshow(fft2_real,vmin=-10,vmax=10)
plt.subplot(222)
plt.title("Recon (imag)")
plt.imshow(fft2_imag,vmin=-10,vmax=10)
# Show 2D FFT of target, just for comparison
expected_fft2=scipy.fftpack.fftshift(scipy.fftpack.fft2(target))
plt.subplot(223)
plt.title("Expected (real)")
plt.imshow(np.real(expected_fft2),vmin=-10,vmax=10)
plt.subplot(224)
plt.title("Expected (imag)")
plt.imshow(np.imag(expected_fft2),vmin=-10,vmax=10)
# Transform from 2D Fourier space back to a reconstruction of the target
fft2=scipy.fftpack.ifftshift(fft2_real+1.0j*fft2_imag)
recon=np.real(scipy.fftpack.ifft2(fft2))
plt.figure()
plt.title("Reconstruction")
plt.imshow(recon,vmin=0.0,vmax=1.0)
plt.show()