FFT를 통한 빠른 코사인 변환


15

빠른 코사인 변환을 구현하고 싶습니다. 나는 Wikipedia 에서 FFT와 유사하게 계산되는 DCT의 빠른 버전이 있다고 읽었습니다 . 나는 인용 읽으려고 Makhoul을 * 종이,도에서 사용되는 FTPACK 및 FFTW 구현 Scipy ,하지만 실제 알고리즘을 추출 할 수 없었다. 이것이 내가 지금까지 가진 것입니다.

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])

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])

*제이. Makhoul, "1 차원과 2 차원의 빠른 코사인 변환"IEEE Trans. 아쿠 스트. 연설 시그. Proc. 28 (1), 27-34 (1980).


2
DCT 코드가 올바른지 또는 무언가를 묻고 있습니까?
Jim Clay

귀하의 의견에 감사드립니다. 처음에 다른 문장을 추가했습니다. 저의 목표는 FFT를 기반으로 FCT를 구현하는 것입니다.
Framester

답변:


18

Nxkarange(N)[0,1,2,...,N1]

4N FFT를 사용하고 시프트가없는 타입 2 DCT

신호 [a, b, c, d]

[0, a, 0, b, 0, c, 0, d, 0, d, 0, c, 0, b, 0, a].

그런 다음 FFT를 사용하여 스펙트럼을 얻습니다.

[A, B, C, D, 0, -D, -C, -B, -A, -B, -C, -D, 0, D, C, B]

그런 다음 첫 번째 이외의 모든 것을 버리고 [A, B, C, D]완료되었습니다.

u = zeros(4 * N)
u[1:2*N:2] = x
u[2*N+1::2] = x[::-1]

U = fft(u)[:N]
return U.real

2N FFT 미러링을 사용하는 유형 2 DCT (Makhoul)

[a, b, c, d]됩니다 [a, b, c, d, d, c, b, a]. 그것의 FFT를 가져 와서 [A, B, C, D, 0, D*, C*, B*]모든 것을 버리고[A, B, C, D] 곱하십시오.이자형제이π케이2

y = empty(2*N)
y[:N] = x
y[N:] = x[::-1]

Y = fft(y)[:N]

Y *= exp(-1j*pi*k/(2*N))
return Y.real

2N FFT 패딩을 사용한 유형 2 DCT (Makhoul)

[a, b, c, d]됩니다 [a, b, c, d, 0, 0, 0, 0]. 그것의 FFT를 가져 와서 [A, B, C, D, E, D*, C*, B*]모든 것을 버리고[A, B, C, D] 곱하십시오.2이자형제이π케이2

y = zeros(2*N)
y[:N] = x

Y = fft(y)[:N]

Y *= 2 * exp(-1j*pi*k/(2*N))
return Y.real

N FFT (Makhoul)를 사용하는 유형 2 DCT

신호 [a, b, c, d, e, f]가되고 [a, c, e, f, d, b]FFT를 가져옵니다 [A, B, C, D, C*, B*]. 곱하기2이자형제이π케이2

v = empty_like(x)
v[:(N-1)//2+1] = x[::2]

if N % 2: # odd length
    v[(N-1)//2+1:] = x[-2::-2]
else: # even length
    v[(N-1)//2+1:] = x[::-2]

V = fft(v)

V *= 2 * exp(-1j*pi*k/(2*N))
return V.real

내 컴퓨터에서는 생성 속도 exp(-1j*pi*k/(2*N))가 FFT보다 오래 걸리기 때문에 속도가 거의 같습니다 . :디

In [99]: timeit dct2_4nfft(a)
10 loops, best of 3: 23.6 ms per loop

In [100]: timeit dct2_2nfft_1(a)
10 loops, best of 3: 20.1 ms per loop

In [101]: timeit dct2_2nfft_2(a)
10 loops, best of 3: 20.8 ms per loop

In [102]: timeit dct2_nfft(a)
100 loops, best of 3: 16.4 ms per loop

In [103]: timeit scipy.fftpack.dct(a, 2)
100 loops, best of 3: 3 ms per loop

2
큰 대답은 구현에 많은 도움이되었습니다! 추가 참고 사항 : 신호 길이가 홀수 인 경우 마지막 방법 인 "N FFT를 사용하는 유형 2 DCT"가 여전히 올바르게 작동합니다. 마지막 요소는 중간 요소로 이동합니다. 이 사실에 대한 수학과 코드를 확인했습니다.
Nayuki

1
@Nayuki 당신은 exp(-1j*pi*k/(2*N))그 단계에 대한 지름길을 생성 하고 있습니까?
endolith

DCT-to-DFT 매핑이 작동하려면 1/4 샘플 시프트가 필요하기 때문에 코드exp(-1j*pi*k/(2*N)) 에서 생성 하고 있습니다. 무엇을 물어 보나요?
Nayuki

안녕하세요, Type III DCT에서 DCT-II의 역수를 계산하려면 어떻게 작동합니까?
Jack H

8

엑스()

허락하다

와이()={엑스(),=0,1,...,1엑스(21),=,+1,...,21

그런 다음 DCT는

(케이)=아르 자형이자형{이자형제이π케이2에프에프{와이()}}

2와이()엑스()엑스()

MATLAB의 코드는 다음과 같습니다.

function C = fdct(x)
    N = length(x);
    y = zeros(1,2*N);
    y(1:N) = x;
    y(N+1:2*N) = fliplr(x);
    Y = fft(y);
    k=0:N-1;
    C = real(exp(-j.* pi.*k./(2*N)).*Y(1:N));

편집하다:

참고 : 사용중인 DCT 공식은 다음과 같습니다.

(케이)=2=01엑스()코사인(π케이2(2+1))

합계를 확장하는 방법에는 여러 가지가 있으므로 다른 구현과 정확하게 일치하지 않을 수 있습니다. 예를 들어 MATLAB은 다음을 사용합니다.

(케이)=(케이)=01엑스()코사인(π케이2(2+1))

(0)=1w(1...N1)=2N

출력을 올바르게 스케일링하여이를 설명 할 수 있습니다.


1
y (n)은 2N 길이가 아닌 N 길이 여야합니다. 이것이 2N 신호에서 2N FFT 대신 N- 길이 신호에서 N- 길이 DCT를 계산하여 4 배 계산 속도를 얻는 방법입니다. fourier.eng.hmc.edu/e161/lectures/dct/node2.html www-ee.uta.edu/dip/Courses/EE5355/Discrete%20class%201.pdf
endolith

0

진정한 과학 컴퓨팅의 경우 메모리 사용량도 중요합니다. 따라서 N 포인트 FFT가 더 매력적입니다. 이것은 신호의 Hermitian Symmetry로 인해 가능합니다. 참조 Makhoul이 여기에 제공됩니다. 실제로 DCT 및 IDCT 또는 DCT10 및 DCT01을 계산하는 알고리즘이 있습니다.
http://ieeexplore.ieee.org/abstract/document/1163351/

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.