(著)山たー
第3回では画像再構成を試みましたがうまくいきませんでした。今回はフィルタ補正逆投影(filtered back projection: FBP)法と呼ばれる方法を用いて画像の再構成をすることを考えます。とは言え、特別にFBP法と呼ばれてはいるのですが、実はFBP法は変数変換を行った2次元逆フーリエ変換と同じです。なので数学的には前回述べた画像再構成法と同じことです。
フィルタ補正逆投影法
$F(u,v)$の2次元逆フーリエ変換を極座標で表すと、$dudv=|J|d\omega d\theta, J= \left[ \begin{array}{cc} \cos\theta&-\omega\sin\theta\\ \sin\theta&\omega\cos\theta \end{array} \right]=\omega $ により、
となります。よってFBP法では次の手順を踏みます。
[Step1]
投影データ$p(r,\theta)$の$r$に関する1次元フーリエ変換$P(\omega,\theta)$を次式によって求める. $$P(\omega,\theta)=\int_{-\infty}^{\infty}p(r,\theta)\exp(-j\omega r)dr$$ [Step2]
$P(\omega,\theta)$を2次元逆フーリエ変換する.
Step2は投影データの空間で高周波強調を行うフィルタ(ランプフィルタ(下図))を作用させ、逆フーリエ変換を行うということを意味しています。もしランプフィルタを除いて計算すると、画像がぼやけてしまいます。ランプフィルタはJacobianに基づくので、人為的に新たな処理を加えているというわけではないのですが、結果として合理的な処理をしていることが分かります。これは大変興味深い点です。
FBP法による画像の再構成
前回と同じテストデータを用いてFBP法により画像の再構成をすると、次図のようになります。
明瞭な像が再構成できていることが分かります。このように、変数変換をした2次元フーリエ逆変換を用いればデータの欠損は無くなるのです。
※実はライブラリを使っているので、あまり説得力のない説明である。
ソースコード
thetaNumは投影の方向の数であるので、これを小さくすれば復元度は下がります。なお、このコードはscikit-imageの"Radon transform - skimage v0.14dev docs""
[http://scikit-image.org/docs/dev/auto_examples/transform/plot_radon_transform.html]
を参考にしました。
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt from skimage.io import imread from skimage import data_dir from skimage.transform import radon from skimage.transform import iradon #画像のインポート image = imread(data_dir + "/phantom.png", as_grey=True) imgNum=max(image.shape) thetaNum=500 theta = np.linspace(0., 180., thetaNum, endpoint=False) #ラドン変換 sinogram = radon(image, theta=theta, circle=True) #元画像とサイノグラムの表示 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5)) ax1.set_title("Original") ax1.imshow(image, cmap=plt.cm.Greys) ax2.set_title("Radon transform\n(Sinogram)") ax2.set_xlabel("Projection angle (deg)") ax2.set_ylabel("Projection position (pixels)") ax2.imshow(sinogram, cmap=plt.cm.hot, extent=(0, 180, 0, sinogram.shape[0]), aspect='auto') fig.tight_layout() plt.show() #FBPによる画像の復元(filterのデフォルトはランプフィルタ. filter=Noneでフィルタなしに) reconstruction_fbp = iradon(sinogram, theta=theta, circle=True) #復元画像と元の画像の誤差 error = reconstruction_fbp - image #平均二乗誤差 print('FBP rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2))) #結果表示 imkwargs = dict(vmin=-0.2, vmax=0.2) fig2, (ax3, ax4) = plt.subplots(1, 2, figsize=(8, 4.5), sharex=True, sharey=True, subplot_kw={'adjustable': 'box-forced'}) ax3.set_title("Reconstruction\nFiltered back projection") ax3.imshow(reconstruction_fbp, cmap=plt.cm.Greys) ax4.set_title("Reconstruction error\nFiltered back projection") ax4.imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs) plt.show()
参考文献
・日本医用画像工学会(2012)『医用画像工学ハンドブック』, 日本医用画像工学会
・"Radon transform - skimage v0.14dev docs""
[http://scikit-image.org/docs/dev/auto_examples/transform/plot_radon_transform.html]
コメントをお書きください