この記事では、Python言語とNumPyを用いた高速逆フーリエ変換(IFFT)の使い方をソースコード付きで解説します。
高速逆フーリエ変換
高速逆フーリエ変換(Inverse Fast Fourier Transform:IFFT)とは、その名の通り高速フーリエ変換の逆の処理です。
周波数領域に変換したデータを、再度時間軸のデータに戻します。
PythonモジュールNumpyでは「numpy.fft.ifft」を用いることで高速逆フーリエ変換を実装できます。
書式
f = numpy.fft.ifft(F)
パラメータ | 内容 |
---|---|
F | 周波数信号(Numpy配列:ndarray) |
f | 返り値(時間信号) |
ソースコード
サンプルプログラムのソースコードです。
①時間信号の生成
適当な信号(=周波数2の正弦波+周波数4の正弦波+ランダムノイズ)を生成し、データをCSVファイルに出力します。
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt def main(): # データのパラメータ N = 16 # サンプル数 dt = 0.1 # サンプリング間隔 fq1, fq2 = 2, 4 # 周波数 t = np.arange(0, N*dt, dt) # 時間軸 # 時間信号を生成(周波数10の正弦波+周波数20の正弦波+ランダムノイズ) f = np.sin(2*np.pi*fq1*t) + np.sin(2*np.pi*fq2*t) + 0.3 * np.random.randn(N) # 時間信号をCSVファイルに出力(小数点第二位まで) np.savetxt("data.csv", f, fmt='%.3f') if __name__ == "__main__": main()
■data.csvの中身
-0.092 1.608 -0.396 0.070 -1.945 0.331 1.762 -0.412 0.154 -1.589 0.857 1.581 -0.058 0.481 -1.548 -0.018
②フーリエ変換
①で作成したCSVファイル(data.csv)を読み込みます。
そして、時間信号を高速フーリエ変換します。
変換後の周波数信号をCSVファイル(fdata.csv)に出力します。
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt def main(): f = np.genfromtxt("data.csv", dtype='float') # 高速フーリエ変換 F = np.fft.fft(f) # 変換後のデータ(周波数領域)を保存 np.savetxt("fdata.csv", F, fmt='%.3f') if __name__ == "__main__": main()
■fdata.csvの中身
(0.786+0.000j) (-0.676+0.894j) (0.033+-1.158j) (5.612+-6.567j) (-2.616+0.390j) (0.349+0.116j) (4.097+-0.664j) (-6.269+0.029j) (-3.318+0.000j) (-6.269+-0.029j) (4.097+0.664j) (0.349+-0.116j) (-2.616+-0.390j) (5.612+6.567j) (0.033+1.158j) (-0.676+-0.894j)
③逆フーリエ変換
②で作成したCSVファイル(fdata.csv)を読み込みます。
そして、周波数信号を高速逆フーリエ変換します。
変換後の時間信号をCSVファイル(data2.csv)に出力します。
# -*- coding: utf-8 import numpy as np import matplotlib.pyplot as plt import ast def main(): # データのパラメータ N = 16 # サンプル数 dt = 0.1 # サンプリング間隔 # CSVのロード(データ型は虚数:complex) F = np.genfromtxt("fdata.csv", dtype='complex', converters={0: lambda s: ast.literal_eval(s.decode())}) # 高速逆フーリエ変換 f = np.fft.ifft(F) # 実部の値のみ取り出し f = f.real # 変換後のデータ(時間領域)を保存 np.savetxt("data2.csv", f, fmt='%.3f') if __name__ == "__main__": main()
■data2.csvの中身
-0.092 1.608 -0.396 0.070 -1.945 0.331 1.762 -0.412 0.154 -1.589 0.857 1.581 -0.058 0.481 -1.548 -0.018
実行結果
「data.csv」と「data2.csv」の中身が一致しています。
周波数領域で信号データを弄らなかったので、正しい結果が得られたことがわかります。
周波数領域で操作すると「ローパスフィルタによるノイズ除去」などができます。
それらについては下記ページにまとめています。
– | 関連記事 |
---|---|
1 | 【NumPy】フーリエ変換とハイパスフィルタでノイズ抽出 |
2 | 【NumPy】フーリエ変換とローパスフィルタでノイズ除去 |
3 | Python入門 サンプル集 |
4 | NumPy入門 サンプル集 |
コメント
コメント失礼します。
今,高速逆フーリエ変換のコードを探しています。
本当は勉強すべきだと思うのですが,今どうしても時間がなくて勉強できません。
そこで,このページを見つけたのですが,このコードを少しだけ変えて
逆フーリエ変換のみのコードにできるのでしょうか。
もしできたら教えていただけませんか。
丸投げのような形になって申し訳ありません。
よければご教授お願いします。
※ゆうき 様
コメントありがとうございます。
コードを3つに分け、「逆変換のみのコード③」も追記しました。
③のコードでは、汎用性を持たすために、周波数信号(虚数)が記載されたテキスト形式のファイルを読み込んで高速逆フーリエ変換しています。
お返事が遅くなり申し訳ありません。
丁寧な対応・返信ありがとうございます。
ただ,僕の手元にある時間軸のデータ(サンプル数8192,時間刻み0.01s)をこのプログラムで動かすとFFT前とIFFT後で値が一致していませんでした。
プログラム内のどこを変えれば良いのでしょうか。
サンプル数の場所だけ変えるのではダメだったのでしょうか。
素人質問で申し訳ありません。
※ゆうき様
コメントありがとうございます。
刻み時間(サンプリング間隔)も変更していますでしょうか。
変更済みでしたら以下のコードを加えて正規化をされてみてはどうでしょうか。
参考:https://python.joho.info/programming/python/numpy-ifft-lowpass-denoise/
何度も失礼します。
先ほどの質問なのですが,グラフに起こしたところ形は変換前後で一致していました。
これは何が原因なのでしょうか。