web-dev-qa-db-ja.com

FFT出力について

DFT/FFT計算の出力を理解するのに助けが必要です。

私は経験豊富なソフトウェアエンジニアであり、主要な周波数を見つけるなど、スマートフォンの加速度計の読み取り値を解釈する必要があります。残念ながら、私は15年前に大学のEEクラスのほとんどを眠っていましたが、ここ数日間DFTとFFTを読んでいます(ほとんど役に立たないようです)。

「EEクラスを受講してください」という応答はありません。私の雇用主が私に支払うなら、私は実際にそれをすることを計画しています。 :)

だからここに私の問題があります:

32 Hzで信号をキャプチャしました。これは、32ポイントの1秒のサンプルで、Excelでグラフ化したものです。

enter image description here

その後、いくつかの FFTコード で書かれたJavaコロンビア大学から(「 Javaでの信頼性が高く高速なFFT = ")。

このプログラムの出力は次のとおりです。インプレースFFTを実行していると思われるため、入力と出力の両方に同じバッファーを再利用します。

Before: 

Re: [0.887  1.645  2.005  1.069  1.069  0.69  1.046  1.847  0.808  0.617  0.792  1.384  1.782  0.925  0.751  0.858  0.915  1.006  0.985  0.97  1.075  1.183  1.408  1.575  1.556  1.282  1.06  1.061  1.283  1.701  1.101  0.702  ]

Im: [0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  ]

After: 

Re: [37.054  1.774  -1.075  1.451  -0.653  -0.253  -1.686  -3.602  0.226  0.374  -0.194  -0.312  -1.432  0.429  0.709  -0.085  0.0090  -0.085  0.709  0.429  -1.432  -0.312  -0.194  0.374  0.226  -3.602  -1.686  -0.253  -0.653  1.451  -1.075  1.774  ]

Im: [0.0  1.474  -0.238  -2.026  -0.22  -0.24  -5.009  -1.398  0.416  -1.251  -0.708  -0.713  0.851  1.882  0.379  0.021  0.0  -0.021  -0.379  -1.882  -0.851  0.713  0.708  1.251  -0.416  1.398  5.009  0.24  0.22  2.026  0.238  -1.474  ]

したがって、この時点で、出力の先頭または末尾を作成することはできません。実部が成分余弦波の振幅であり、虚部が成分正弦波の振幅であるなど、DFTの概念を理解しています。素晴らしい本「 デジタル信号処理の科学者および技術者ガイド 」からこの図に従うこともできます。 enter image description here

私の具体的な質問は次のとおりです。

  1. FFTの出力から、「最も発生している周波数」を見つけるにはどうすればよいですか?これは私の加速度計データの分析の一部です。実数(コサイン)または虚数(サイン)配列を読み取る必要がありますか?

  2. 時間領域に32ポイントの入力があります。 FFTの出力は、実数の場合は16要素の配列で、虚数の場合は16要素の配列ではありませんか?プログラムがサイズ32の実数および虚数の配列出力を提供するのはなぜですか?

  3. 前の質問に関連して、出力配列のインデックスをどのように解析すればよいですか? 32 Hzでサンプリングされた32個のサンプルの入力を考えると、16要素の配列出力のインデックスはサンプリングレート(32 Hz)の1/2まで均一に広がる必要があるため、各要素が正しいことを理解しています配列の(32 Hz * 1/2)/ 16 = 1 Hzを表しますか?

  4. FFT出力に負の値があるのはなぜですか?値は正弦波の振幅を表すと思いました。たとえば、Real [3] = -1.075の出力は、周波数3の余弦波に対して-1.075の振幅を意味するはずです。そうですか?振幅はどのように負になりますか?

77
  1. 複素数の実数部分または想像力のある部分(実際の配列および虚数配列は何であるか)を探すべきではありません。代わりに、sqrt(real * real + imag * imag)として定義されている周波数の大きさを探したいです。この数は常に正です。これで、検索する必要があるのは最大値のみです(配列の最初のエントリを無視します。これはDCオフセットであり、周波数依存情報を持ちません)。

  2. 複素数から複素数のFFTを使用しているため、32の実数出力と32の虚数出力が得られます。 32個のサンプルを64個の値(または32個の複素数値)に変換し、虚数部をゼロに拡張したことを思い出してください。これにより、周波数結果が2回発生する対称FFT出力が得られます。出力0からN/2で使用する準備ができたら、出力N/2からNでミラーリングします。出力N/2からNを単純に無視するのが最も簡単です。これらは必要ありません。 FFTの計算方法に関するアーティファクトです。

  3. Fft-bin方程式への周波数は(bin_id * freq/2)/(N/2)です。ここで、freqはサンプル周波数(別名32 Hz、NはFFTのサイズ)です。あなたの場合、これはビンごとに1 Hzに単純化されます。 N/2からNまでのビンは負の周波数を表します(奇妙な概念、私は知っています)。あなたの場合、これらは最初のN/2周波数の単なる鏡であるため、重要な情報は含まれていません。

  4. 各ビンの実部と虚部は複素数を形成します。実数部と虚数部が負で、周波数自体の大きさが正であれば問題ありません(質問1に対する私の回答を参照)。複素数を読むことをお勧めします。それらがどのように機能するのか(そしてなぜそれらが役立つのか)を説明することは、単一のstackoverflow-questionで説明できることを超えています。

注:また、自己相関とは何か、および信号の基本周波数を見つけるためにどのように使用されるかを読むこともできます。これが本当に欲しいものだと思う。

76

すでにいくつかの良い答えがありますが、FFTの前に時間領域データに window function を本当に適用する必要があることを付け加えます。

9
Paul R

1)最初のインデックス(DCコンポーネント))に加えて、最高値を持つ実配列のインデックスを探します。おそらく、32 Hzよりかなり高いサンプルレートが必要です。意味のある結果を得るために、ウィンドウサイズを大きくします。

2)両方のアレイの後半は、前半のミラーです。たとえば、実配列(1.774)の最後の要素は2番目の要素(1.774)と同じであり、虚数配列(1.474)の最後の要素はnegative2番目の要素。

3)32 Hzのサンプルレートで取得できる最大周波数は16 Hz( ナイキスト制限 )であるため、各ステップは2 Hzです。前述したように、最初の要素は0 Hz(つまり、DC offset)であることを忘れないでください。

4)確かに、負の振幅は完全に理にかなっています。これは、信号が「反転」することを意味します。標準FFTは、t = 0で通常値= 1であるコサインに基づいているため、時間= 0で値= -1の信号は負の振幅を持ちます。 。

5
duskwuff

ウィンドウ関数を使用しても、「最も頻繁に発生する周波数」が複数のFFTビンに飛び散ることがあります。そのため、より長いウィンドウ、複数のウィンドウ、または補間を使用して、スペクトルピークの周波数をより適切に推定する必要があります。

4
hotpaw2