Эффективный расчет автокорреляции с использованием БПФ

12

Я пытаюсь вычислить автокорреляцию на платформе, где единственный доступный ускоренный примитив - это (I) FFT. У меня проблема, хотя.

Я прототипировал его в MATLAB . Я, однако, немного смущен. Я предположил, что это работает просто следующим образом (это из памяти, поэтому извиняюсь, если я немного ошибся).

 autocorr = ifft( complex( abs( fft( inputData ) ), 0 ) )

Однако я получаю другой результат, чем при использовании xcorrфункции. Теперь я полностью ожидаю, что не получу левую сторону автокорреляции (так как это отражение правой стороны и, следовательно, в любом случае не нужно). Однако проблема в том, что моя правая сторона, как представляется, сама отражается на полпути. Что фактически означает, что я получаю примерно половину ожидаемого объема данных.

Так что я уверен, что, должно быть, я делаю что-то очень простое, но я просто не могу понять, что.

Goz
источник
1
Быть осторожен. Если данные не являются детерминированными, мы обычно можем только оценить автокорреляционную последовательность. Существует две распространенные версии автокорреляционных оценок: предвзятые и несмещенные. Беспристрастные результаты в автокорреляционных оценках, которые являются статистически несмещенными. Однако дисперсия может быть очень большой для лагов высокого порядка, что приводит к проблемам, если, например, автокорреляционная оценка используется в матричных инверсиях. Смещенные образцы демонстрируют статистическое смещение, но с меньшей дисперсией (и среднеквадратичной ошибкой). Оба статистически согласованы. У вас есть ненормированная предвзятая оценка выше.
Брайан

Ответы:

16

Пикенетты, конечно, правы. БПФ реализует круговую свертку, в то время как xcorr () основана на линейной свертке. Кроме того, вам необходимо также возвести в квадрат абсолютное значение в частотной области. Вот фрагмент кода, который обрабатывает все заполнение нулями, сдвиг и усечение.

%% Cross correlation through a FFT
n = 1024;
x = randn(n,1);
% cross correlation reference
xref = xcorr(x,x);

%FFT method based on zero padding
fx = fft([x; zeros(n,1)]); % zero pad and FFT
x2 = ifft(fx.*conj(fx)); % abs()^2 and IFFT
% circulate to get the peak in the middle and drop one
% excess zero to get to 2*n-1 samples
x2 = [x2(n+2:end); x2(1:n)];
% calculate the error
d = x2-xref; % difference, this is actually zero
fprintf('Max error = %6.2f\n',max(abs(d)));
Hilmar
источник
Вау, что работал красавицей. Прямая C-версия (однопоточная, без SIMD) моего трекера высоты тона работала за 0,8 секунды, используя вышеописанный метод, в отличие от версии на базе примитивов Intel Performance, которая работала за 0,4 секунды. Это восхитительно! Спасибо
Гоз
3

N2N1[(N1),N1]0

2N12N12N12N1

N2N1N

N1N2N102N12N1

Вкратце: вы должны были сделать это (чтобы адаптироваться к вашему языку программирования):

autocorr = ifft( complex( abs(fft(inputData, n=2*N-1))**2, 0 ) )

Или в MATLAB:

autocorr = ifft(abs(fft(inputData, 2*N-1)).^2)
Жан-Луи Дюррио
источник
0

Основная причина того, что требуемый выходной сигнал функции xcorr не похож на применение функции FFT и IFFT, заключается в том, что при применении этих функций к сигналам конечный результат получается циклически извилистым .

Основное различие между линейной и круговой сверткой можно найти в линейной и круговой свертке .

Проблема может быть решена путем начального заполнения нуля сигнала и усечения конечного вывода IFFT .

Venu
источник