【C#】フーリエ変換(FFT, DFT)プログラム

以前、Excelのマクロを使って、データ個数に応じて高速フーリエ変換(FFT)と離散フーリエ変換(DFT)の処理を自動で切り替えるマクロを作成したのですが、Excelではデータ数が多い時など、使いにくい場合もあるので、今度は、C#でフーリエ変換部分をライブラリ(*.dll)にし、そのライブラリを使ったプログラムを作成しました。

 

実行ブログラムはこちら FourierTransform.zip

ソースコードは、すべてGitHubで公開しています。

https://github.com/ImagingSolution/FourierCSharp

 

使用方法は以下の通りです。

 

プログラムの実行

zipファイルを解凍すると、

FourierTransform.exe

FourierCSharp.dll

sampledata

となっていますので、FourierTransform.exeをダブルクリックして実行してください。

 

フーリエ変換できるデータフォーマット

データは1行あたりに1つのデータのCSVファイルとなります。

例)

1
1.30939551
1.59096344
1.820538079
1.980767038
2.06331351
2.069803727
2.01139008
1.906994542
1.780482109
1.65716389
1.560123288
1.506883103
1.506883103
1.560123288

入力データに実数部と虚数部が含まれる場合は、1行あたりに

実数部、虚数部

とします。

例)

50, 0
0, -25
0, 0
0, -12.5
0, 0
0, 0

サンプルのデータとして、ZIPファイル内の sampledataフォルダ内にいくつかCSVファイルを入れてありますので、そちらを参考にしてください。

 

データの読込

メニューの File → LoadData をクリックし、CSVファイルを指定することで、データが読み込まれ、フーリエ変換の結果(フーリエ変換後の各周波数の大きさ)が表示されます。

 

フーリエ変換はデータの個数が2のn乗個の場合:FFT、その他の場合:DFTを行います。

 

フーリエ変換、逆フーリエ変換の切替

メニューの Fourier direction → Forward もしくは Backward をクリックすることで、離散フーリエ変換、逆離散フーリエ変換が切り替わります。

 

離散フーリエ変換は

$$F(t)=\sum _{ x=0 }^{ N-1 }{ f(x){ e }^{ -i\frac { 2\pi tx }{ N } } } $$

逆離散フーリエ変換は

$$f(t)=\frac { 1 }{ N } \sum _{ t=0 }^{ N-1 }{ F(t){ e }^{ i\frac { 2\pi xt }{ N } } } $$

で計算しています。

 

窓関数

メニューの Window→ Hamming, Hanning, Blackman のいづれかをクリックすることで、それぞれの窓関数を通します。

↓ 窓関数

 

ただし、窓関数を通すと、元に戻せないため、元に戻す場合は、再度、データ読込を行って下さい。

 

免責事項

ここに公開されているプログラムは自由に使って頂いて構いませんが、バグ等による責任は待てませんので、自己責任において参照下さい。

 

フリーウェアへ戻る

【Excel】高速フーリエ変換(FFT)のマクロ(VBA)

Excelには標準でフーリエ解析の機能を備えていますが、解析用のデータを変更してもフーリエ変換の結果は自動更新してくれないので、少し使い勝手の悪い物になっています。

 

そこで、エクセルのセルの部分にSUMAVERAGE のような関数と同じように動くマクロ(ユーザー定義関数)で作成したフーリエ変換の関数(Fourier)を作成しました。

ユーザー定義関数で作成しているため、解析用のデータを変更すると、フーリエ変換の結果も自動で変更されます。

 

 

ファイルのダウンロードはこちら↓より

fourier_transform_rev3.zip

(Excel2016推奨、それ以前だとファイルを開いた直後はフーリエ変換の値が0になるようです。)

 

使用方法

このファイルはマクロを使用しているため、ファイルを起動するとセキュリティ警告が表示さている場合は、コンテンツの有効化をクリックしてください。

 

まず、フーリエ変換の結果の出力先のセルを縦方向にデータ個数と同じ分だけ選択し、

= Fourier( データのセル)

と入力し、Enterではなく、Ctrl + Shift + Enterキー を入力します。

これで、フーリエ変換の結果が複素数で表示されます。

 

複素数はいらないから、絶対値だけ欲しいという場合にはFourierAbs関数を使って下さい。(使い方は同じです。)

 

フーリエ変換の結果は標準のフーリエ解析の結果と同じになるようにしていますが、10の-15乗ぐらいの誤差が出ています。

 

フーリエ変換の結果の複素数の大きさを計算するには、Excelの標準関数の IMABS関数 で求まります。

 

同様に位相は IMARGUMENT関数 で求まります。

 

このマクロのポイント!

  • 窓関数に対応
    = Fourier( データのセル, “Hamming”)
    のように入力することで、入力データに対して窓関数を通します。
    対応している窓関数の名前は
    ハミング Hamming
    ハニング Hanning
    ブラックマン Blackman

    の3つ。

  • FFT/DFTの自動切換え
    マクロ処理内部で、フーリエ変換するデータ個数が2のN乗個の場合はFFT、それ以外の場合はDFTとなり、データの個数が2のN乗個の制限はありません。

 

逆フーリエ変換を追加

2018.6.19追記

逆フーリエ変換に対応したIFourier関数を追加しました。

逆フーリエ変換の計算は別シートの逆フーリエ変換のシートを参照ください。

 

使用方法については、普通のフーリエ変換の時と同じように

= IFourier( データのセル)

と入力し、Enterではなく、Ctrl + Shift + Enterキー を入力します。

ただし、逆フーリエ変換なので、データのセルの部分は、基本的に複素数となります。

 

逆フーリエ変換の結果はこちら↓です。

 

上の絵を見ても分かるように、虚数成分の10の-15乗程度の誤差が入ってしまっているので、複素数の実部だけを取得するIMREAL関数で実部を取得すると、ほぼフーリエ変換の時に用いたデータに戻っていることが確認できるかと思います。

 

 

フーリエ変換へ戻る

【Excel】フーリエ解析(FFT)

ここではExcelの標準の機能であるフーリエ解析について紹介したいと思います。

フーリエ変換は、ざっくり言うと信号の中から各周波数ごとの大きさ位相を求める変換です。

この”信号”と言っている部分が音や画像のような測定データの場合、この”信号(データ)”に対してフーリエ変換を行うのが離散フーリエ変換となります。

しかし、離散フーリエ変換は処理速度が遅いので、離散フーリエ変換を行うんだけど、データ個数を2のn乗(2, 4, 8, 16, 32・・・)個に制限することで、高速に処理することができる処理アルゴリズムが高速フーリエ変換[Fast Fourier Transform(FFT)]となります。

 

ここで、フーリエ変換の公式ですが、主に以下の3つの公式があります。下図の公式を見て頂くと分かりますが、異なるのはシグマの頭についているデータ個数Nに関する係数のみ異なります。
いくつも公式があるのは、おそらくプログラム的な都合で、

1番目の公式が本来の公式?
2番目の公式は、フーリエ変換では各周波数の大きさが相対的にどの周波数が大きいのか?を解析的に用いる場合が多く、離散フーリエ変換しかしない(逆変換をしない)場合も多いので、1/Nの計算を省き処理を軽くしたかった?エクセルでは、この2番目の公式を用いています。
3番目の公式は離散フーリエ変換と逆離散フーリエ変換のプログラムをできるだけ共通にしたかったため?異なるのは e の乗数の符号のみとなります。

N :   データ個数
t:   全データに含まれる波の個数(何周期分か?)
x :   データのインデックス番号 x = 0, 1, 2,… , N-1

データの準備

エクセルのフーリエ解析はFFTなので、データの個数は2のn乗個(2, 4, 8, 16, 32, 64・・・)に限られ、最大4096個まで処理が可能です。

今回はデータの個数は32個用意しました。
実際にフーリエ解析したいデータは各自、用意してください。
データはどこかに1列に書いておけば大丈夫です。(あとで、データの場所を指定します)

結果が分かりやすくなるように、

全く振動していない(t=0)データ(値=3)と、
2周期分(t=2)のデータ(振幅=2、位相=30°)と、
4周期分(t=4)のデータ(振幅=1、位相=-60°)

の3つの波形を合計したデータに対してフーリエ変換を行います。

Excelでフーリエ解析の手順

Excelでフーリエ解析を行うには分析ツールというのを表示する必要があります。

この分析ツールの表示方法は下記のページを参照下さい。

【Excel】分析ツールの表示

 

メニューのデータデータ分析を選択します。
ホーム→データ分析にあるデータ分析とは別なので注意してください。

 

表示されたウィンドウからフーリエ解析を選択しOKを押します。

 

 

表示されたウィンドウの入力範囲の部分にある上矢印の部分をクリックします。

 

 

この状態で、フーリエ解析を行うデータを選択(2のn乗個の最大4096個まで)し、それでよければ下矢印をクリックします。

フーリエ解析の結果の出力先はいくつか選べるのですが、今回は新規ワークシートにするとして、OKボタンをクリックします。

 

 

そしてこれ↓がフーリエ変換された結果です。

フーリエ変換の結果の見方

※ここから先は、入力データが実数(虚数成分が無い)の場合を前提として説明します。

フーリエ変換の結果は

96
0
27.7128129211021+16i
0
7.99999999999999-13.856406460551i
0
0

のように複素数(実数と虚数成分が含まれる)が並んでいますが、これは上から順にt=0、1、2、…の時の結果になっています。

tの値は、FFTに用いたデータ全体に何周期分の波が含まれているか?を表しています。

tの値から周波数f(Hz)を求めるには、データ全体のサンプリング時間をΔt(sec)とすると、周波数は

$$f=\frac{t}{\triangle t}  (Hz)$$

となります。

ここで、フーリエ変換の結果に、tの値と周波数fを書き加えます。

この結果を見ると、多少の計算誤差はありますが、 t= 2 と t = 30、 t = 4 と t = 28 の値が、虚数成分(i の係数)の正負が異なるだけで、似ている事がわかります。

この実数は同じで虚数の正負が異なる値を複素共役と言います。

フーリエ変換の入力データが実数の場合、必ずこのようになるのですが、t と N – t が共役となるため、フーリエ変換では、 t = 0~N/2 までの結果のみを使う場合がよくあります。

 

フーリエ変換の結果から各周波数の振幅Aを求めるには、フーリエ変換の結果(複素数[実数と虚数])の大きさ |F(t)| を用いると

t = 0 と t = N/2のとき

$$A=|F(t)| / N$$

t = 1 ~ N/2-1 のとき

$$A=|F(t)| / N \times 2$$

となります。

エクセルで複素数の大きさを求めるには IMABS()関数 を用います。

さらに複素数の偏角(位相)を求めるには IMARGUMENT()関数 を用いますが、偏角の結果はラジアン単位なので、度の単位に変換するには DEGREES()関数 を用います。

 

これらの事をエクセルの結果に複素数の大きさ、各周波数ごとの振幅および位相を追加すると以下のようになります。

これで、データをFFTして、各周波数ごとの振幅(A)と位相(φ)を求める事ができています。

各周波数ごと(各tごと)の波形は

$$A_{t} \cos(2\pi t\frac{x}{N}+\phi_{t})$$

となります。

 

今回のFFT解析に用いたExcelファイル(*.xlsx)は、下記リンクをクリックしてダウンロードできます。

フーリエ解析(FFT)_rev1.zip

 

パワースペクトルは??

FFT解析は、各周波数のパワースペクトルを求めること!

みたいな認識もあるかと思いますが、ここまでの説明にパワースペクトルが出てきていません。

パワースペクトルは、FFTで求めた各周波数の結果(複素数)の大きさを振幅スペクトルと言い、振幅スペクトルを2乗したものをパワースペクトルと言います。

パワーという響きから、どうしても力?みたいなのをイメージしてしまいますが、どちらかというと、C言語でn乗の計算をするときに pow関数 を用いると思いますが、このn乗の方に近いでしょうか?(本当のところはよく知りません。。)

 

各周波数ごとに求められたFFTの結果(複素数)を a + bi とすると

$$振幅スペクトル=\sqrt{a^{2}+b^{2}}$$

$$パワーペクトル=(振幅スペクトル)^{2}=a^{2}+b^{2}$$

となることから、プログラム的にはパワースペクトルの計算の方がルートの計算をしていない分だけ計算コストが低くなります。

エクセルでは、IMABS()関数で振幅スペクトルを求め、振幅スペクトルを2乗(^2)することで、パワースペクトルを求める事になり、計算コストが増えてしまい、ちょっと微妙。。

複素共役の性質

入力データが実数のときのFFTの結果で tN – t が共役になると説明しましたが、

複素数 a + bi と、共役の複素数 a – bi と足し合わせると

$$(a+bi)+(a-bi) = 2a$$

となるので、虚数成分は打ち消しあい、実数成分が2倍となります。

この性質から、振幅を求める際に、t = 1 ~ N/2-1 のとき、最後に x 2 を付けているのは、そのためです。

 

 

フーリエ変換へ戻る

参考

【参考書籍】信号処理入門

この本は、知り合いの人から勧められた本なのですが、私も勧めたくなる本でした。

 

画像処理を勉強すると、とりあえずの集大成的なものがフーリエ変換だと思います。

しかし、いきなり公式が出来てきて何だか良く分からないままFFTまでやってみたりと、とても難しいという印象のまま終わってみたりもします。

この本は、そんなもう一度ちゃんとフーリエ変換を理解したいという人にはオススメです。
図が多めで、そんなに難しくは無いと思います。

 

信号処理の概要から始まり、ベクトル→内積→正規直交基底→フーリエ変換→DFT→FFTという流れで説明されています。

この流れがまさにお見事!

フーリエ変換の公式などは本の後半に書いてありますが、いきなり最後の部分を見るのではなく、最初から丁寧に読むと良いと思います。

 

今ではフーリエ変換って正規直交基底との内積でしょ!?

画像処理だと正規化相関も内積、3×3フィルタみたいのも内積、というぐらいの認識でいます。

内積ってサイコ―!!と思えるようになったのも、この本のおかげです。

 

 

目次

1 信号処理とは
1.1 信号処理はどんなとき必要か
1.2 どんな信号があるか
1.3 アナログ信号とディジタル信号
1.4 サンプリング問題
2 信号処理の例
2.1 波形の平滑化
2.2 雑音の圧縮
3 数学の準備体操
3.1 信号処理を学ぶために
3.2 信号の表現
3.3 2次元ベクトルの距離と内積
3.4 正規直交基
3.5 多次元ベクトル空間から関数空間へ
3.6 正規直交関数系
4 相関関数
4.1 関数の類似性を測る
4.2 相互相関関数
4.3 自己相関関数
5 フーリエ級数展開
5.1 フーリエ級数展開とは
5.2 偶関数と奇関数
5.3 周期が2πでない場合
5.4 複素フーリエ級数展開
5.5 パーシバルの定理
5.6 フーリエ級数展開の実例
5.7 フーリエ級数展開の重要な性質
6 DFTとFFT
6.1 ディジタル信号のフーリエ解析
6.2 離散フーリエ変換(DFT)
6.3 DFTの性質
6.4 高速フーリエ変換(FFT)
7 フーリエ変換
7.1 フーリエ級数展開からフーリエ変換へ
7.2 フーリエ変換の性質
7.3 デルタ関数と白色雑音
8 線形システムの解析
8.1 線形システム解析へのアプローチ
8.2 入出力信号の関係
8.3 インパルス応答
8.4 周波数領域でのシステムの表現

 

 

と言っても、フーリエ変換は、あまり使わないな~

 

使える数学へ戻る