Chcę wdrożyć Fast Cosine Transform. Czytałem na wikipedii , że istnieje szybka wersja DCT, która jest obliczana podobnie do FFT. Próbowałem przeczytać cytowany artykuł Makhoul * dla implementacji FTPACK i FFTW, które są również używane w Scipy , ale nie byłem w stanie wyodrębnić faktycznego algorytmu. Oto co mam do tej pory:
Kod FFT:
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])
Kod 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
Próba 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])
*JOT. Makhoul, „Szybka transformacja kosinusowa w jednym i dwóch wymiarach”, IEEE Trans. Acoust. Speech Sig. Proc. 28 (1), 27–34 (1980).
Odpowiedzi:
N
x
k
arange(N)
Typ 2 DCT przy użyciu 4N FFT i bez zmian
Sygnał
[a, b, c, d]
staje się[0, a, 0, b, 0, c, 0, d, 0, d, 0, c, 0, b, 0, a]
.Następnie weź FFT, aby uzyskać widmo
[A, B, C, D, 0, -D, -C, -B, -A, -B, -C, -D, 0, D, C, B]
następnie wyrzuć wszystko oprócz pierwszego
[A, B, C, D]
i gotowe:Typ 2 DCT przy użyciu lustrzanego odbicia 2N FFT (Makhoul)
[a, b, c, d]
[a, b, c, d, d, c, b, a]
[A, B, C, D, 0, D*, C*, B*]
[A, B, C, D]
Typ 2 DCT z wykorzystaniem 2N FFT wyściełany (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]
Typ 2 DCT przy użyciu N FFT (Makhoul)
[a, b, c, d, e, f]
[a, c, e, f, d, b]
[A, B, C, D, C*, B*]
Na mojej maszynie są one w przybliżeniu tej samej prędkości, ponieważ generowanie
exp(-1j*pi*k/(2*N))
trwa dłużej niż FFT. :REźródło
exp(-1j*pi*k/(2*N))
czy jest skrót do tego kroku?exp(-1j*pi*k/(2*N))
w swoim kodzie , ponieważ przesunięcie ćwiartki jest konieczne, aby mapowanie DCT na DFT działało. O co pytasz?pozwolić
Następnie podaje DCT
Więc w zasadzie tworzysz2 N. sekwencja długości y( n ) gdzie jest pierwsza połowa x ( n ) a druga połowa to x ( n ) wywrócony. Następnie po prostu weź FFT i pomnóż ten wektor przez rampę fazową. Wreszcie weź tylko prawdziwą rolę i masz DCT.
Oto kod w MATLAB.
Edytować:
Uwaga: Formuła DCT, której używa, to:
Istnieje kilka sposobów skalowania podsumowania, więc może nie pasować dokładnie do innych implementacji. Na przykład MATLAB używa:
wherew(0)=1N−−√ and w(1...N−1)=2N−−√
You can account for this by properly scaling the output.
źródło
For true scientific computing, the amount of memory usage is important too. Therefore the N point FFT is more attractive to me. This is only possible due to Hermitian Symmetry of the signal. The reference Makhoul is given here. And actually has the algorithm for calculating DCT and IDCT or DCT10 and DCT01.
http://ieeexplore.ieee.org/abstract/document/1163351/
źródło