質問: plt.figure(figsize=(12, 12)) # グラフ表示 # オリジナル信号 fig.add_subplot(321) plt.xlabel('time(sec)', fontsize=14) plt.ylabel('signal', fontsize=14) plt.plot(t, f) # オリジナル信号 ->FFT fig.add_subplot(322) plt.xlabel('freqency(Hz)', fontsize=14) plt.ylabel('amplitude', fontsize=14) plt.plot(fq, F_abs_amp) # オリジナル信号 ->FFT ->周波数filter ->IFFT fig.add_subplot(323) plt.xlabel('time(sec)', fontsize=14) plt.ylabel('signal(freq.filter)', fontsize=14) plt.plot(t, F2_ifft_real) # オリジナル信号 ->FFT ->周波数filter fig.add_subplot(324) plt.xlabel('freqency(Hz)', fontsize=14) plt.ylabel('amplitude(freq.filter)', fontsize=14) # plt.vlines(x=[10], ymin=0, ymax=1, colors='r', linestyles='dashed') plt.fill_between([10 ,100], [0, 0], [1, 1], color='g', alpha=0.2) plt.plot(fq, F2_abs_amp) # オリジナル信号 ->FFT ->振幅強度filter ->IFFT fig.add_subplot(325) plt.xlabel('time(sec)', fontsize=14) plt.ylabel('signal(amp.filter)', fontsize=14) plt.plot(t, F3_ifft_real) # オリジナル信号 ->FFT ->振幅強度filter fig.add_subplot(326) plt.xlabel('freqency(Hz)', fontsize=14) plt.ylabel('amplitude(amp.filter)', fontsize=14) # plt.hlines(y=[0.2], xmin=0, xmax=100, colors='r', linestyles='dashed') plt.fill_between([0 ,100], [0, 0], [0.2, 0.2], color='g', alpha=0.2) plt.plot(fq, F3_abs_amp) plt.tight_layout() ```
回答: ``` # 正規化 + 交流成分2倍 F = F/(N/2) F[0] = F[0]/2 ``` 正規化が必要な理由ですが、データの点数によってFFTの結果で得られる振幅が変わってしまうからです。 そのため、データ点数Nで割ってあげることで正規化しています。 N/2の理由ですが、FFTの結果にはナイキスト周波数を中心に鏡像が現れます。 その鏡像にも振幅分のデータは振り分けられていることになりますので、解析に使う周波数領域のデータの振幅も1/2になってしまいます。 そのため、解析に使う部分のデータを2倍することで辻褄を合わせています。 ``` # 振幅を元のスケールに戻す f2 = np.real(f2*N) ``` これは、正規化したデータに対してIFFTしたので、Nを乗算することで元のスケールに戻しているのでしょう。 > > 特に後者はなぜ虚数を捨てるのかよくわかりません。 > > > 元の信号波形には虚部が存在しないからでしょう。 実際の計算結果には虚部にも値はありますが計算誤差によるものとみなして捨てています。 > > 他のサイトだと、「振幅を元のスケールに戻す」という作業をしていないケースもあるようです。 > > > FFTの結果に対してなんらかの調整を行った結果に対してIFFTを行った場合は、その調整を元に戻す処理が必要です。 ``` F2_ifft_real = F2_ifft.real * 2 # 実数部の取得、振幅を元スケールに戻す ``` が、そうですがフィルタ処理を行った結果、ナイキスト周波数を超えるデータもすべて0にしていますので、鏡像部のデータも一緒にクリアされてしまっています。 これは、実質データの振幅が半分になっていることになりますので、元に戻すためには2倍してやる必要があります。 ``` F3_ifft = np.fft.ifft(F3) # IFFT F3_ifft_real = F3_ifft.real # 実数部の取得 ``` は、F3自体には正規化の処理は行ってないですよね。 なので、F3のIFFT結果にはスケールを戻す処理は必要ないのです。