【NumPy】高速逆フーリエ変換 (IFFT)

この記事では、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入門 サンプル集
関連記事

コメント

  1. ゆうき より:

    コメント失礼します。
    今,高速逆フーリエ変換のコードを探しています。
    本当は勉強すべきだと思うのですが,今どうしても時間がなくて勉強できません。

    そこで,このページを見つけたのですが,このコードを少しだけ変えて
    逆フーリエ変換のみのコードにできるのでしょうか。
    もしできたら教えていただけませんか。
    丸投げのような形になって申し訳ありません。

    よければご教授お願いします。

    • 管理人 より:

      ※ゆうき 様
      コメントありがとうございます。
      コードを3つに分け、「逆変換のみのコード③」も追記しました。
      ③のコードでは、汎用性を持たすために、周波数信号(虚数)が記載されたテキスト形式のファイルを読み込んで高速逆フーリエ変換しています。

  2. ゆうき より:

    お返事が遅くなり申し訳ありません。
    丁寧な対応・返信ありがとうございます。

    ただ,僕の手元にある時間軸のデータ(サンプル数8192,時間刻み0.01s)をこのプログラムで動かすとFFT前とIFFT後で値が一致していませんでした。
    プログラム内のどこを変えれば良いのでしょうか。
    サンプル数の場所だけ変えるのではダメだったのでしょうか。
    素人質問で申し訳ありません。

  3. ゆうき より:

    何度も失礼します。

    先ほどの質問なのですが,グラフに起こしたところ形は変換前後で一致していました。
    これは何が原因なのでしょうか。