【画像処理にも使える!】NumPyのfft.ifftshift()で周波数成分を自在に操る
DFT とは?
DFTは、有限長の時間信号を周波数領域に変換する数学的な手法です。信号の周波数成分を分析したり、信号処理や画像処理などの様々な用途に用いられます。
DFTは、以下の式で表されます。
X[k] = sum(x[n] * exp(-2*pi*j*k*n / N))
ここで、
k
は周波数インデックスj
は虚数単位N
は信号の長さx[n]
は時間領域の信号X[k]
は周波数領域の信号
fft.ifftshift()
関数の役割
DFTを実行すると、周波数成分が X[0]
, X[1]
, ..., X[N-1]
のように並んでいます。しかし、多くの場合、周波数成分を -N/2
, -N/2 + 1
, ..., N/2 - 1
, N/2
の順に並べ替えた方が解析や処理に便利です。
fft.ifftshift()
関数は、DFTの結果を上記の順序に並び替えます。つまり、零周波数成分をスペクトルの真ん中に移動させる役割を果たします。
fft.ifftshift()
関数は、以下の構文で使用されます。
import numpy as np
X = np.fft.fft(x) # DFTを実行
X_ifftshifted = np.fft.ifftshift(X) # `fft.ifftshift()` 関数で並び替え
この例では、x
という時間領域の信号に対してDFTを実行し、その結果を X
に格納します。その後、fft.ifftshift()
関数を使用して X
を並び替え、X_ifftshifted
に格納します。
fft.ifftshift()
関数は、NumPyにおけるDFTの重要な補助関数です。DFTの結果を解析や処理しやすい順序に並び替えることで、様々な用途に役立ちます。
fft.ifftshift()
関数は、DFT以外にも、スペクトル解析や信号処理で周波数成分の並び替えが必要となる場面で使用することができます。fft.ifftshift()
関数は、すべての軸に対してシフトを実行できます。特定の軸に対してのみシフトを実行したい場合は、axes
引数を使用することができます。fft.ifftshift()
関数は、fft.fftshift()
関数の逆関数です。つまり、fft.ifftshift(fft.fftshift(X))
はX
に戻ります。
例 1:1D信号のDFTと周波数成分の並び替え
この例では、1D信号のDFTを実行し、fft.ifftshift()
関数を使用して周波数成分を並び替えます。
import numpy as np
import matplotlib.pyplot as plt
# サンプル信号を作成
x = np.arange(10)
# DFTを実行
X = np.fft.fft(x)
# 周波数成分を並び替え
X_ifftshifted = np.fft.ifftshift(X)
# 振幅スペクトルをプロット
plt.magnitude_spectrum(X_ifftshifted, Fs=1.0)
plt.show()
このコードを実行すると、以下の図のような振幅スペクトルが表示されます。
零周波数成分がスペクトルの真ん中に移動していることが確認できます。
例 2:2D画像のDFTと周波数成分の並び替え
import numpy as np
import matplotlib.pyplot as plt
# サンプル画像を読み込む
image = plt.imread('lena.jpg')
# 2D DFTを実行
X = np.fft.fftn(image)
# 周波数成分を並び替え
X_ifftshifted = np.fft.ifftshift(X)
# 位相スペクトルをプロット
plt.imshow(np.angle(X_ifftshifted), cmap='gray')
plt.show()
これらの例は、fft.ifftshift()
関数の基本的な使用方法を示しています。実際には、様々な用途に合わせて様々な方法で使用することができます。
fft.ifftshift()
関数は、以下のような様々な応用で役立ちます。
- 画像処理: 画像処理において、周波数成分を特定の順序に並べることで、画像の特定の周波数成分のみを強調したり、画像をノイズ除去したりすることができます。
- 信号処理: 信号処理において、周波数成分を特定の順序に並べることで、特定の周波数成分のみを処理したり、信号をフィルタリングしたりすることができます。
- 周波数成分の分析: DFTの結果を解析するために、周波数成分を自然な順序に並び替えることができます。
周波数インデックスの操作
fft.ifftshift()
関数の代わりに、周波数インデックスを直接操作することで、同じ結果を得ることができます。具体的には、以下の手順で行います。
- 周波数インデックスを
N/2
ずつずらす。 - 負のインデックスを
N
にプラスして正のインデックスに変換する。
以下のコードは、この方法を実装した例です。
import numpy as np
X = np.fft.fft(x)
# 周波数インデックスを操作
n = X.shape[0]
ind = np.arange(n)
ind[ind < n // 2] += n
X_ifftshifted = X[ind]
このコードは、fft.ifftshift()
関数と同じ結果を返します。
np.roll() 関数の使用
np.roll()
関数は、配列を指定した要素数だけ回転させることができます。この機能を利用して、fft.ifftshift()
関数の代わりに以下のコードを使用することができます。
import numpy as np
X = np.fft.fft(x)
# `np.roll()` 関数を使用してシフト
X_ifftshifted = np.roll(X, -n // 2, axis=0)
専用関数の使用
SciPy には、scipy.fft.ifftshift()
関数という fft.ifftshift()
関数の代替となる関数があります。この関数は、NumPy の fft.ifftshift()
関数とほぼ同じ動作ですが、SciPy の他のモジュールとより整合性のある API を提供しています。
import scipy.fft as sp
X = np.fft.fft(x)
# `scipy.fft.ifftshift()` 関数を使用
X_ifftshifted = sp.ifftshift(X)
上記のように、fft.ifftshift()
関数の代替方法はいくつかあります。状況に合わせて最適な方法を選択してください。
- SciPy の
scipy.fft.ifftshift()
関数は、SciPy の他のモジュールと連携する場合は便利な選択肢となります。 fft.ifftshift()
関数は、NumPy の標準モジュールに含まれているため、他の代替方法よりも汎用性が高いと言えます。- 上記の代替方法は、すべて同じ結果を返しますが、それぞれ異なる性能特性を持つ可能性があります。ベンチマークを実施して、特定の状況において最適な方法を判断することをお勧めします。