Saya telah bermain-main dengan algoritma rekonstruksi tomografi baru-baru ini. Saya sudah memiliki implementasi kerja yang bagus dari FBP, ART, skema iterasi seperti SIRT / SART dan bahkan menggunakan aljabar linear lurus (lambat!). Pertanyaan ini bukan tentang salah satu dari teknik itu ; jawaban dari bentuk "mengapa ada orang yang melakukannya seperti itu, inilah beberapa kode FBP" bukan yang saya cari.
Hal berikutnya yang ingin saya lakukan dengan program ini adalah " melengkapi perangkat " dan mengimplementasikan apa yang disebut " metode rekonstruksi Fourier ". Pemahaman saya tentang ini pada dasarnya adalah bahwa Anda menerapkan 1D FFT ke sinogram "eksposur", mengatur mereka sebagai "jari-jari roda" radial dalam ruang 2D Fourier (bahwa ini adalah hal yang berguna untuk dilakukan mengikuti langsung dari teorema slice pusat) , interpolasi dari titik-titik tersebut ke kisi-kisi biasa dalam ruang 2D itu, dan kemudian dimungkinkan untuk membalik Fourier-transform untuk memulihkan target pemindaian asli.
Kedengarannya sederhana, tetapi saya belum beruntung mendapatkan rekonstruksi yang terlihat seperti target asli.
Kode Python (numpy / SciPy / Matplotlib) di bawah ini adalah tentang ekspresi paling ringkas yang bisa saya dapatkan dari apa yang saya coba lakukan. Saat dijalankan, ini menampilkan yang berikut:
Gambar 1: target
Gambar 2: sinogram dari target
Gambar 3: baris sinogram FFT-ed
Gambar 4: baris atas adalah ruang FFT 2D yang diinterpolasi dari baris sinogram Fourier-domain; baris bawah adalah (untuk tujuan perbandingan) 2D FFT langsung dari target. Ini adalah titik di mana saya mulai curiga; plot yang diinterpolasi dari sinogram FFT terlihat mirip dengan plot yang dibuat oleh 2D-FFT langsung target ... namun berbeda.
Gambar 5: transformasi invers-Fourier dari Gambar 4. Saya berharap ini akan sedikit lebih dikenali sebagai target daripada yang sebenarnya.
Ada ide yang saya lakukan salah? Tidak yakin apakah pemahaman saya tentang rekonstruksi metode Fourier secara mendasar cacat, atau hanya ada beberapa bug dalam kode saya.
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()