Gần đây tôi đã chơi xung quanh với các thuật toán tái cấu trúc chụp cắt lớp. Tôi đã có các triển khai FBP, ART, sơ đồ lặp giống như SIRT / SART và thậm chí sử dụng đại số tuyến tính thẳng (chậm!). Câu hỏi này không phải là về bất kỳ kỹ thuật nào ; câu trả lời của mẫu "tại sao mọi người sẽ làm theo cách đó, đây là một số mã FBP" không phải là những gì tôi đang tìm kiếm.
Điều tiếp theo tôi muốn làm với chương trình này là " hoàn thành bộ " và thực hiện cái gọi là " phương pháp tái tạo Fourier ". Hiểu biết của tôi về điều này về cơ bản là bạn áp dụng FFT 1D cho "phơi sáng" hình sin, sắp xếp chúng thành "nan hoa của bánh xe" trong không gian Fourier 2D (đây là một điều hữu ích để thực hiện trực tiếp từ định lý lát trung tâm) , nội suy từ các điểm đó đến một lưới thông thường trong không gian 2D đó, và sau đó có thể đảo ngược biến đổi Fourier để khôi phục mục tiêu quét ban đầu.
Nghe có vẻ đơn giản, nhưng tôi đã không gặp nhiều may mắn khi nhận được bất kỳ sự tái tạo nào trông giống như mục tiêu ban đầu.
Mã Python (numpy / SciPy / Matplotlib) dưới đây là về biểu thức ngắn gọn nhất mà tôi có thể nghĩ ra về những gì tôi đang cố gắng thực hiện. Khi chạy, nó sẽ hiển thị như sau:
Hình 1: mục tiêu
Hình 2: hình sin của mục tiêu
Hình 3: các hàng hình sin của FFT-ed
Hình 4: hàng trên cùng là không gian FFT 2D được nội suy từ các hàng hình sin của miền Fourier; hàng dưới cùng là (để so sánh) FFT 2D trực tiếp của mục tiêu. Đây là điểm mà tôi bắt đầu nghi ngờ; các ô được nội suy từ các FFT hình sin trông tương tự như các ô được tạo bằng cách trực tiếp 2D-FFTing mục tiêu ... và khác nhau.
Hình 5: biến đổi nghịch đảo Fourier của Hình 4. Tôi đã hy vọng điều này sẽ dễ nhận biết hơn một chút so với mục tiêu so với thực tế.
Có ai biết tôi đang làm gì sai không? Không chắc chắn nếu sự hiểu biết của tôi về việc xây dựng lại phương pháp Fourier về cơ bản là thiếu sót, hoặc chỉ có một số lỗi trong mã của tôi.
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()