Я хочу реализовать быстрое косинусное преобразование. Я прочитал в википедии , что есть быстрая версия DCT, которая аналогично вычисляется для FFT. Я попытался прочитать процитированную статью Makhoul * для реализаций FTPACK и FFTW, которые также используются в Scipy , но я не смог извлечь фактически алгоритм. Это то, что я до сих пор:
БПФ код:
def fft(x):
if x.size ==1:
return x
N = x.size
x0 = my_fft(x[0:N:2])
x1 = my_fft(x[0+1:N:2])
k = numpy.arange(N/2)
e = numpy.exp(-2j*numpy.pi*k/N)
l = x0 + x1 * e
r = x0 - x1 * e
return numpy.hstack([l,r])
Код DCT:
def dct(x):
k = 0
N = x.size
xk = numpy.zeros(N)
for k in range(N):
for n in range(N):
xn = x[n]
xk[k] += xn*numpy.cos(numpy.pi/N*(n+1/2.0)*k)
return xk
Испытание FCT:
def my_fct(x):
if x.size ==1:
return x
N = x.size
x0 = my_fct(x[0:N:2]) # have to be set to zero?
x1 = my_fct(x[0+1:N:2])
k = numpy.arange(N/2)
n = # ???
c = numpy.cos(numpy.pi/N*(n+1/2.0)*k)
l = x0 #???
r = x0 #???
return numpy.hstack([l,r])
* J. Махул, "Быстрое косинусное преобразование в одном и двух измерениях", IEEE Trans. Acoust. Речь Сиг. Proc. 28 (1), 27-34 (1980).
Ответы:
Я читал об этом , и есть несколько способов сделать это, используя разного размера N. Мой Matlab ржавый, так что здесь они находятся в Python ([0,1,2,...,N−1]
N
это длина входного сигналаx
,k
являетсяarange(N)
= ):DCT типа 2 с использованием 4N FFT и без смен
Сигнал
[a, b, c, d]
становится[0, a, 0, b, 0, c, 0, d, 0, d, 0, c, 0, b, 0, a]
,Затем возьмите БПФ, чтобы получить спектр
[A, B, C, D, 0, -D, -C, -B, -A, -B, -C, -D, 0, D, C, B]
затем выбросьте все, кроме первого
[A, B, C, D]
, и все готовоТип 2 DCT с использованием 2N БПФ зеркальный (Махул)
[a, b, c, d]
становится[a, b, c, d, d, c, b, a]
. Возьмите БПФ этого, чтобы получить[A, B, C, D, 0, D*, C*, B*]
, затем выбросьте все, но[A, B, C, D]
и умножьте это на (сдвиг половины выборкиТип 2 DCT с использованием 2N FFT (Makhoul)
[a, b, c, d]
становится[a, b, c, d, 0, 0, 0, 0]
. Возьмите БПФ этого, чтобы получить[A, B, C, D, E, D*, C*, B*]
, затем выбросьте все, но[A, B, C, D]
и умножьте это на чтобы получить DCT:DCT типа 2 с использованием N FFT (Makhoul)
Сигнал2e−jπk2N
[a, b, c, d, e, f]
становится[a, c, e, f, d, b]
, затем возьмите БПФ, чтобы получить[A, B, C, D, C*, B*]
. Умножьте на а затем принять реальное участие:На моей машине они все примерно одинаковой скорости, поскольку генерация
exp(-1j*pi*k/(2*N))
занимает больше времени, чем FFT. : Dисточник
exp(-1j*pi*k/(2*N))
или есть ярлык для этого шага?exp(-1j*pi*k/(2*N))
в своем коде , потому что сдвиг четверти выборки необходим для работы отображения DCT-DFT. Что заставляет вас спрашивать?Я не уверен, какой метод использует бумага, на которую вы ссылались, но я вывел это раньше, и вот что я получил в итоге: (Предполагая, что - это ввод)x(n)
позволять
DCT тогда дается
Таким образом, вы в основном создаете последовательность длиной y ( n ), где первая половина - x ( n ), а вторая половина - x ( n ).2N y(n) x(n) x(n) обратном порядке. Затем просто возьмите БПФ и умножьте этот вектор на фазовый сдвиг. Наконец, возьмите только реальную часть, и у вас есть DCT.
Вот код в MATLAB.
Редактировать:
Примечание. Используемая формула DCT:
Существует несколько способов масштабирования суммирования, поэтому оно может не совпадать точно с другими реализациями. Например, MATLAB использует:
Вы можете объяснить это, правильно масштабируя вывод.
источник
Для истинных научных вычислений также важно количество используемой памяти. Поэтому точка N БПФ более привлекательна для меня. Это возможно только благодаря эрмитовой симметрии сигнала. Ссылка Махул дана здесь. И фактически имеет алгоритм расчета DCT и IDCT или DCT10 и DCT01.
http://ieeexplore.ieee.org/abstract/document/1163351/
источник