масштабирование по Кисффту - PullRequest
8 голосов
/ 12 апреля 2011

Я хочу вычислить быструю корреляцию с использованием БПФ и библиотеки kissfft, а масштабирование должно быть точнымКакое масштабирование необходимо (вперед и назад) и какое значение я должен использовать для масштабирования моих данных?

Ответы [ 2 ]

11 голосов
/ 12 апреля 2011

3 наиболее распространенных коэффициента масштабирования БПФ:

  • 1,0 вперед БПФ, 1,0 / N обратное БПФ

  • 1,0 / N БПФ вперед, 1,0 обратное БПФ

  • 1,0 / sqrt (N) в обоих направлениях, БПФ и IFFT

Учитывая любую возможную неоднозначность в документации и при любом масштабировании пользователь ожидает, что он будет «правильным» для своих целей, лучше всего просто подавать чистую синусоидальную волну с известной (1.0 float или 255 integer) амплитудой и точно периодической в Длина FFT до рассматриваемого FFT (и / или IFFT), и посмотрите, совпадает ли масштабирование с одним из вышеупомянутых, может отличаться от указанного выше на 2X или sqrt (2), или желаемое масштабирование является чем-то совершенно другим.

например. Напишите модульный тест для kissfft в вашей среде для ваших типов данных.

6 голосов
/ 12 апреля 2011

умножьте каждый частотный отклик на 1 / sqrt (N) для общего масштабирования 1 / N

В псевдокоде:

ifft( fft(x)*conj( fft(y) )/N ) == circular_correlation(x,y)

По крайней мере, это верно для кисффта с типами с плавающей запятой.

Вывод следующего примера кода на c ++ должен выглядеть примерно так:

круговая корреляция [1, 3i, 0 0 ....] с самим собой = (10,0), (1.19796e-10,3), (- 4.91499e-08,1.11519e- 15), (1.77301e-08, -1.19588e-08) ...

#include <complex>
#include <iostream>
#include "kiss_fft.h"
using namespace std;

int main()
{
    const int nfft=256;
    kiss_fft_cfg fwd = kiss_fft_alloc(nfft,0,NULL,NULL);
    kiss_fft_cfg inv = kiss_fft_alloc(nfft,1,NULL,NULL);

    std::complex<float> x[nfft];
    std::complex<float> fx[nfft];
    memset(x,0,sizeof(x));
    x[0] = 1;
    x[1] = std::complex<float>(0,3);

    kiss_fft(fwd,(kiss_fft_cpx*)x,(kiss_fft_cpx*)fx);
    for (int k=0;k<nfft;++k) {
        fx[k] = fx[k] * conj(fx[k]);
        fx[k] *= 1./nfft;
    }
    kiss_fft(inv,(kiss_fft_cpx*)fx,(kiss_fft_cpx*)x);
    cout << "the circular correlation of [1, 3i, 0 0 ....] with itself = ";
    cout
        << x[0] << ","
        << x[1] << ","
        << x[2] << ","
        << x[3] << " ... " << endl;
    kiss_fft_free(fwd);
    kiss_fft_free(inv);
    return 0;
}
...