web-dev-qa-db-ja.com

FFT実数/虚数/ absパーツの解釈

私は現在、離散フーリエ変換について学び、それをよりよく理解するためにnumpyで遊んでいます。

「sin x sin x sin」信号​​をプロットして、4つの非ゼロ点を持つクリーンなFFTを取得しました。 「うーん、「sin + sin + sin + sin」信号​​をこれらの振幅と周波数でプロットすると、同じ「sin x sin x sin」信号​​が得られるはずですよね?

まあ...

(最初は「x」信号、2番目は「+」信号です)

enter image description here

どちらも同じ振幅/周波数を共有しますが、いくつかの類似点があることを確認できても、同じ信号ではありません。

わかりました、FFTの絶対値のみをプロットしたので、いくつかの情報を失ったと思います。

次に、両方の信号の実数部、虚数部、および絶対値をプロットしました。

enter image description here

今、私は混乱しています。このすべてをどうすればよいですか?数学の観点からDFTについて読みました。複雑な値は単位円からくることを理解しています。それがどのように機能するかを理解するために、ヒルベルト空間についても学ぶ必要がありました(そしてそれは苦痛でした!...そして私は表面を引っかいただけです)。これらの実数/虚数プロットがconcreteが数学の世界の外にあるかどうかを理解したいだけです:

  • abs(fft):周波数+振幅
  • real(fft):?
  • 想像(fft):?

コード:

import numpy as np
import matplotlib.pyplot as plt
N = 512 # Sample count
fs = 128 # Sampling rate
st = 1.0 / fs # Sample time
t = np.arange(N) * st # Time vector

signal1 = \
1   *np.cos(2*np.pi * t) *\
2   *np.cos(2*np.pi * 4*t) *\
0.5 *np.cos(2*np.pi * 0.5*t)

signal2 = \
0.25*np.sin(2*np.pi * 2.5*t) +\
0.25*np.sin(2*np.pi * 3.5*t) +\
0.25*np.sin(2*np.pi * 4.5*t) +\
0.25*np.sin(2*np.pi * 5.5*t)



_, axes = plt.subplots(4, 2)

# Plot signal
axes[0][0].set_title("Signal 1 (multiply)")
axes[0][0].grid()
axes[0][0].plot(t, signal1, 'b-')

axes[0][1].set_title("Signal 2 (add)")
axes[0][1].grid()
axes[0][1].plot(t, signal2, 'r-')

# FFT + bins + normalization
bins = np.fft.fftfreq(N, st)    
fft  = [i / (N/2) for i in np.fft.fft(signal1)]
fft2 = [i / (N/2) for i in np.fft.fft(signal2)]

# Plot real
axes[1][0].set_title("FFT 1 (real)")
axes[1][0].grid()
axes[1][0].plot(bins[:N/2], np.real(fft[:N/2]), 'b-')

axes[1][1].set_title("FFT 2 (real)")
axes[1][1].grid()
axes[1][1].plot(bins[:N/2], np.real(fft2[:N/2]), 'r-')

# Plot imaginary
axes[2][0].set_title("FFT 1 (imaginary)")
axes[2][0].grid()
axes[2][0].plot(bins[:N/2], np.imag(fft[:N/2]), 'b-')

axes[2][1].set_title("FFT 2 (imaginary)")
axes[2][1].grid()
axes[2][1].plot(bins[:N/2], np.imag(fft2[:N/2]), 'r-')

# Plot abs
axes[3][0].set_title("FFT 1 (abs)")
axes[3][0].grid()
axes[3][0].plot(bins[:N/2], np.abs(fft[:N/2]), 'b-')

axes[3][1].set_title("FFT 2 (abs)")
axes[3][1].grid()
axes[3][1].plot(bins[:N/2], np.abs(fft2[:N/2]), 'r-')

plt.show()
13
Cyrille

各周波数ビンについて、magnitudesqrt(re^2 + im^2)は、対応する周波数でのコンポーネントの振幅を示します。 phaseatan2(im, re)は、そのコンポーネントの相対位相を示します。データウィンドウの中心の周りの対称プロパティ(偶数対奇数)に関心がない限り、実数部と虚数部は、それ自体では特に有用ではありません。

22
Paul R

いくつかの基準点、たとえば固定時間ウィンドウの中心に関して、同じ周波数の正弦波と余弦波は異なって見えます(任意の固定時間基準点に対して異なる開始位相を持っています)。また、整数の周期幅に対して数学的に直交するため、変換の独立した基底ベクトル成分を表すことができます。

FFT結果の実際の部分は、各周波数成分が余弦波にどの程度似ているか、虚数成分、各成分が正弦波にどれだけ似ているかです。サイン成分とコサイン成分をさまざまな比率で組み合わせると、任意の位相または望ましい位相の正弦波を作成できるため、FFT結果を完成させることができます。

マグニチュードだけでは、正弦波と余弦波の違いはわかりません。 IFFT(imag(FFT))は、純粋な余弦とは異なる位相を持つ信号の再構成を台無しにします。 IFFT(re(FFT))および純粋な正弦波(FFTアパーチャウィンドウに関して)と同じです。

10
hotpaw2

3つのcos関数の積で構成される信号1を4つのcos関数の合計に変換できます。これは、4つの正弦関数の合計である関数2に違いをもたらします。

Cos関数は偶数関数cos(-x)== cos(x)です。偶関数のフーリエ変換は純粋に現実です。これが、関数1のfftの虚数部のプロットにゼロに近い値(1e-15)のみが含まれている理由です。

サイン関数は、奇数の関数sin(-x)== -sin(x)です。奇数の関数のフーリエ変換は純粋な虚数です。これが、関数2のfftの実数部のプロットにゼロに近い値(1e-15)のみが含まれている理由です。

FFTとDFTをより詳細に理解したい場合は、電気工学の信号解析の教科書をお読みください。

2
Heinz M.