Son zamanlarda tomografik rekonstrüksiyon algoritmalarıyla oynuyorum. FBP, ART, SIRT / SART benzeri yinelemeli bir şema ve hatta düz doğrusal cebir (yavaş!) Kullanıyorum. Bu soru bu tekniklerin hiçbiriyle ilgili değildir ; "neden herkes bunu böyle yapsın, yerine bazı FBP kodu" formunun cevapları ben aradığım şey değil.
Bu programla bir sonraki yapmak istediğim şey " seti tamamlamak " ve " Fourier rekonstrüksiyon metodu " nu uygulamaktı . Bunu anladığım temelde sinogram "pozlamalarına" 1D FFT uygulamanız, bunları 2D Fourier uzayında radyal "tekerlek teli" olarak düzenlemenizdir (bunun doğrudan merkezi dilim teoreminden sonra yapılması yararlı bir şeydir) , bu noktalardan 2B alanda normal bir ızgaraya enterpolasyon uygulayın ve ardından orijinal tarama hedefini kurtarmak için Fourier dönüşümünü tersine çevirmek mümkün olmalıdır.
Kulağa basit geliyor, ama orijinal hedefe benzeyen herhangi bir rekonstrüksiyon elde etme şansım olmadı.
Aşağıdaki Python (numpy / SciPy / Matplotlib) kodu, yapmaya çalıştığım şeyle karşılaşabileceğim en özlü ifade hakkında. Çalıştırıldığında aşağıdakileri görüntüler:
Şekil 1: Hedef
Şekil 2: Hedefin bir sinogramı
Şekil 3: FFT-ed sinogram satırları
Şekil 4: üst sıra, Fourier-domain sinogram satırlarından enterpolasyonlu 2D FFT alanıdır; alt sıra (karşılaştırma amacıyla) hedefin doğrudan 2D FFT'sidir. Şüphelendiğim nokta bu; sinogram FFT'lerinden enterpole edilen araziler, doğrudan 2D-FFT hedefi ile yapılan çizimlere benziyor ... ama yine de farklı.
Şekil 5: Şekil 4'teki ters-Fourier dönüşümü, bunun hedef olarak gerçekte olduğundan biraz daha tanınabilir olacağını umuyordum.
Yanlış yaptığım hakkında bir fikrin var mı? Fourier yönteminin yeniden yapılandırılması konusundaki anlayışımın temelde kusurlu olup olmadığından emin değil miyim, yoksa kodumda sadece bir hata var.
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()