web-dev-qa-db-ja.com

pythonでfft値に関連付けられた頻度を抽出する方法

Numpyでfft関数を使用すると、複雑な配列になりました。正確な周波数値を取得する方法は?

35
ria

_np.fft.fftfreq_は、係数に関連付けられた周波数を示します。

_import numpy as np

x = np.array([1,2,1,0,1,2,1,0])
w = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x))

for coef,freq in Zip(w,freqs):
    if coef:
        print('{c:>6} * exp(2 pi i t * {f})'.format(c=coef,f=freq))

# (8+0j) * exp(2 pi i t * 0.0)
#    -4j * exp(2 pi i t * 0.25)
#     4j * exp(2 pi i t * -0.25)
_

OPは、周波数をヘルツ単位で見つける方法を尋ねます。式はfrequency (Hz) = abs(fft_freq * frame_rate)であると思います。

これを示すコードを次に示します。

まず、440 Hzでwaveファイルを作成します。

_import math
import wave
import struct

if __== '__main__':
    # http://stackoverflow.com/questions/3637350/how-to-write-stereo-wav-files-in-python
    # http://www.sonicspot.com/guide/wavefiles.html
    freq = 440.0
    data_size = 40000
    fname = "test.wav"
    frate = 11025.0
    amp = 64000.0
    nchannels = 1
    sampwidth = 2
    framerate = int(frate)
    nframes = data_size
    comptype = "NONE"
    compname = "not compressed"
    data = [math.sin(2 * math.pi * freq * (x / frate))
            for x in range(data_size)]
    wav_file = wave.open(fname, 'w')
    wav_file.setparams(
        (nchannels, sampwidth, framerate, nframes, comptype, compname))
    for v in data:
        wav_file.writeframes(struct.pack('h', int(v * amp / 2)))
    wav_file.close()
_

これにより、ファイル_test.wav_が作成されます。データを読み込み、FFTし、最大電力の係数を見つけ、対応するfft周波数を見つけてから、ヘルツに変換します。

_import wave
import struct
import numpy as np

if __== '__main__':
    data_size = 40000
    fname = "test.wav"
    frate = 11025.0
    wav_file = wave.open(fname, 'r')
    data = wav_file.readframes(data_size)
    wav_file.close()
    data = struct.unpack('{n}h'.format(n=data_size), data)
    data = np.array(data)

    w = np.fft.fft(data)
    freqs = np.fft.fftfreq(len(w))
    print(freqs.min(), freqs.max())
    # (-0.5, 0.499975)

    # Find the peak in the coefficients
    idx = np.argmax(np.abs(w))
    freq = freqs[idx]
    freq_in_hertz = abs(freq * frate)
    print(freq_in_hertz)
    # 439.8975
_
57
unutbu

DFT値に関連付けられている周波数(Python)

fft 、高速フーリエ変換により、 fast DFT、離散フーリエの計算を可能にするアルゴリズムの大きなファミリーのメンバーを理解します。等サンプリングされた信号の変換。

[〜#〜] dft [〜#〜] [〜#〜] n [〜#〜] 複素数のリストをリストに変換します [〜#〜] n [〜#〜] 複素数、両方のリストは周期 [〜#〜] n [〜 #〜]

ここでは、 fft numpy実装を扱います。

多くの場合、あなたは考える

  • 長さ [〜#〜] n [〜#〜] の時間領域で定義された信号 x 、一定間隔 dt
  • そのDFT [〜#〜] x [〜#〜] (ここでは具体的にX = np.fft.fft(x))、その要素はサンプリングレート dw

いくつかの定義

  • xサンプルでdtでサンプリングされた信号Nの周期(別名期間)は

    _T = dt*N
    _
  • Xの基本周波数(Hzおよびrad/s)、DFTは

    _df = 1/T
    dw = 2*pi/T # =df*2*pi
    _
  • 一番上の周波数は ナイキスト周波数

    _ny = dw*N/2
    _

    (それは_dw*N_ではありません)

DFTの特定の要素に関連付けられた周波数

特定のインデックス_0<=n<N_のX = np.fft.fft(x)の要素に対応する頻度は、次のように計算できます。

_def rad_on_s(n, N, dw):
    return dw*n if n<N/2 else dw*(n-N)
_

または単一のスイープで

_w = np.array([dw*nif n<N/2 else dw*(n-N) for n in range(N)])
_

hz単位の周波数を考慮する場合は、_s/w/f/_

_f = np.array([df*n if n<N/2 else df*(n-N) for n in range(N)])
_

それらの周波数を使用する

元の信号x-> yを、周波数関数のみの形式で周波数領域に演算子を適用して変更したい場合は、w'砂

_Y = X*f(w)
y = ifft(Y)
_

_np.fft.fftfreq_の紹介

もちろんnumpyには便利な関数_np.fft.fftfreq_があり、次元のものではなく次元のない周波数を返しますが、簡単

_f = np.fft.fftfreq(N)*N*df
w = np.fft.fftfreq(N)*N*dw
_
30
gboffi

頻度は配列の単なるインデックスです。インデックスnでは、頻度は2ですπn /配列の長さ(単位あたりのラジアン)。考慮してください:

>>> numpy.fft.fft([1,2,1,0,1,2,1,0])
array([ 8.+0.j,  0.+0.j,  0.-4.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+4.j,
        0.+0.j])

結果は、インデックス0、2、および6でゼロ以外の値になります。8つの要素があります。これの意味は

       2πit/8 × 0       2πit/8 × 2       2πit/8 × 6
    8 e           - 4i e           + 4i e
y ~ ———————————————————————————————————————————————
                          8
5
kennytm