Как получить продолжение последовательности через обратное преобразования Фурье

Рейтинг: 0Ответов: 1Опубликовано: 18.06.2023

У меня есть последовательность чисел N и я хочу получить её продолжение из частотного преобразования Фурье.

from scipy.fft import fft, ifft
import matplotlib.pyplot as plt

N = np.arange(100)

N_fft = fft(N)
N_ifft = ifft(N_fft)

plt.plot(N_ifft)
plt.show()

В документации пишут что в параметры ifft можно добавить значение n для длинны выходящей последовательности, но в таком случае добавленные значения будут равны нулю. Как я могу получить следующие скажем 100 чисел идущие после последовательности N?

Ответы

▲ 0

Проще всего получить расширение диапазона исходного сигнала, прямо применив формулы для дискретного преобразования Фурье.

Пример на Delphi, вещественная и мнимая часть FFT хранятся в отдельных массивах. После проведения прямого Фурье-преобразования имеем массив комплексных отсчётов (два массива в этой реализации) гармоник длиной N - такой же, как исходный сигнал.

Новый сигнал будет иметь длину NN. Для каждой гармоники (внешний цикла по i) рассчитываем её вклад в сигнал в момент времени j по формуле из вики, добавляем реальную часть этого вклада в соответствующую ячейку Re2, накапливая сигнал в этом массиве. С нумпаем это, наверное, можно сделать векторно.

P.S. В примере использован истинно периодический сигнал. Не стоит ожидать, что для произвольного сигнала, в котором кажутся видны какие-то закономерности, продолжение (предсказание) будет более-менее точным.

var
  Re, Im, Re2: array of Double;
  i, j, N, NN: Integer;
begin
  N := 1024;
  NN := 2345;
  SetLength(Re, N);
  SetLength(Im, N);
  SetLength(Re2, NN);  //автоинициализация нулями!
  for i := 0 to N - 1 do begin
    Re[i] := Sin(10 * i * 2 * Pi / N) +  0.5 * Sin(17 * i * 2 * Pi / N);
    Im[i] := 0;
    Series1.AddXY(i, Re[i]);
  end;

  FFT1D(Re, Im, N, 1);


  //для вас главная эта часть    
  for i := 0 to N - 1 do begin
      for j := 0 to NN - 1 do
        Re2[j] := Re2[j] + Re[i] * Cos(2*Pi*j*i/N) - Im[i]*Sin(2*Pi*j*i/N);
  end;

  for I := 0 to NN - 1 do
    Series4.AddXY(i, Re2[i] + 2);

Результат (второй массив сдвинул вверх на 2 для удобства)

![введите сюда описание изображения