DFTの結果から振幅スペクトラムと位相スペクトラムを求める

はじめに

DFTの各基底ベクトルは複素ベクトルのため、DFTによって得られた結果も複素ベクトルです。つまり、結果の各要素は複素数であり、実部と虚部を持ちます。
結果の複素ベクトルの各要素に対して、複素数の大きさを計算した結果が振幅スペクトラムに、複素数の偏角を計算した結果が位相スペクトラムに該当します。

振幅と位相を求める

scipyとnumpyを使うと以下の通り簡単に計算できます。

import numpy
import scipy.fftpack

spectrum  = scipy.fftpack.fft([0, 1, 0, -1])
amplitude = numpy.absolute(spectrum)
phase     = numpy.angle(spectrum)

amplitudeが振幅スペクトラムで、phaseが位相スペクトラムです。

振幅と位相から信号を復元する

振幅スペクトラム、位相スペクトラムから元のスペクトラムを復元する場合は以下の通りに計算します。

spectrum = amplitude * (numpy.cos(phase) + numpy.sin(phase) * 1j)

解説

Pythonでは複素数型が組込型で用意されており、scipyのfftの結果は複素数型の配列になります。

位相スペクトラムが複素数の偏角、振幅スペクトラムが複素数の大きさなので、単純に極形式の通りに計算することで、元の複素数を表すことができます。

なお、1jは虚数単位なので、実数にかけることで虚部とすることができます。実数と虚数の加算は、実部と虚部を持つ複素数になります。(Pythonでは、実数に対しては虚部0jを、虚数に対しては実部0を拡張し、複素数化して計算します。)

つまり、上記の計算は、実部をcos(phase)で計算し、虚部をsin(phase)で計算し、大きさとしてamplitudeをかけているというだけです。

補足

numpy.angle()は、numpy.arctan2()を使った計算と同様の計算を行います。
numpy.arctan2()が引数に虚部と実部を持つ1複素数の位相を計算するのに対し、numpy.angle()は複素数配列を引数にとり、位相を配列で返すという違いがあるだけです。