Eu estava escrevendo uma implementação simples de transformação de Fourier e observei a equação DFT na wikipedia para referência , quando notei que estava fazendo algo diferente e, depois de pensar nisso, senti que a versão da wikipedia deveria estar errada, porque é muito simples pensar em uma sinal que quando Fourier transformado (com essa equação) retornará um espectro incorreto: Como a equação envolve o sinal ao redor do plano complexo apenas uma vez (devido àcom ), qualquer sinal que seja periódico um número par de vezes (ao envolver o plano complexo) não terá espectro, pois os picos comuns (ao redor do círculo unitário) que apareceriam durante uma DFT serão cancelam-se mutuamente (quando um número par deles aparecer).
Para verificar isso, escrevi um código que produzia a seguinte imagem, que parece confirmar o que meus pensamentos.
"Tempo usando a equação" usa a equação com um vetor de tempo (portanto, o tempo no qual foi amostrado, por exemplo). Pode ser encontrado na função abaixo.
ft
A equação da Wikipedia, vinculada acima, é copiada aqui para referência: Pode ser encontrado na função .
ft2
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
def ft(t, s, fs):
freq_step = fs / len(s)
freqs = np.arange(0, fs/2 + freq_step, freq_step)
S = []
for freq in freqs:
real = np.sum(s * np.cos(2*np.pi*freq * t))
compl = np.sum(- s * np.sin(2*np.pi*freq * t))
tmpsum = (real**2 + compl**2) ** 0.5
S.append(tmpsum)
return S, freqs
def ft2(s, fs): # Using wikipedia equation
nump=len(s)
freq_step = fs / nump
freqs = np.arange(0, fs/2 + freq_step, freq_step)
S = []
for i, freq in enumerate(freqs):
real = np.sum(s * np.cos(2*np.pi*freq * i/nump))
compl = np.sum(- s * np.sin(2*np.pi*freq * i/nump))
tmpsum = (real**2 + compl**2) ** 0.5
S.append(tmpsum)
return S, freqs
def main():
f = 5
fs = 100
t = np.linspace(0, 2, 200)
y = np.sin(2*np.pi*f*t) + np.cos(2*np.pi*f*2*t)
fig = plt.figure()
ax = fig.add_subplot(311)
ax.set_title('Signal in time domain')
ax.set_xlabel('t')
ax.plot(t, y)
S, freqs = ft(t, y, fs)
ax = fig.add_subplot(312)
ax.set_xticks(np.arange(0, freqs[-1], 2))
ax.set_title('Time using equation')
ax.set_xlabel('frequency')
ax.plot(freqs, S)
S, freqs = ft2(y, fs)
ax = fig.add_subplot(313)
ax.set_title('Using Wiki equation')
ax.set_xlabel('frequency')
ax.set_xticks(np.arange(0, freqs[-1], 2))
ax.plot(freqs, S)
plt.tight_layout()
plt.show()
main()
Obviamente, parece bastante improvável que eu tenha encontrado aleatoriamente um erro em uma página wiki de alto perfil. Mas não vejo erro no que fiz?
fonte
Respostas:
Você tem um bug
ft2
. Você está incrementandoi
efreq
juntos. Não é assim que você deseja que sua soma funcione. Eu brinquei com consertá-lo, mas ficou confuso. Decidi reescrevê-lo de uma perspectiva discreta, em vez de tentar usar a terminologia contínua. Na DFT, a taxa de amostragem é irrelevante. O que importa é quantas amostras são usadas (N
). Os números do compartimento (k
) correspondem à frequência em unidades de ciclos por quadro. Tentei manter o código o mais intacto possível para que ele permanecesse facilmente compreensível. Também desenrolei os loops de cálculo da DFT para, esperançosamente, revelar sua natureza um pouco melhor.Espero que isto ajude.
Ced
fonte
Eu não vou olhar através do seu código. a página da wikipedia parece boa, mas é um bom exemplo da "guerra de formatação" ou "guerra de notação" ou "guerra de estilo" entre matemáticos e engenheiros elétricos. algumas delas, acho que as pessoas de matemática estão certas. EEs nunca deveriam ter adotado "j "para a unidade imaginária. isto dito, esta é uma expressão melhor da DFT e a inversa é:
DFT:
iDFT:
porque engenheiros elétricos que fazem DSP gostam de usarx [ n ] como uma sequência de amostras em "tempo" e X[ k ] como a sequência de amostras discretas em "frequência". os matemáticos podem gostar mais disso:
DFT:
iDFT:
e isso é o mesmo que a página da Wikipedia.
pode ser necessário prestar mais atenção ao uso de+ ou - no expoente e como isso se traduz em + ou - contra o pecado( ⋅ ) prazo.
fonte
Voltei a isso e tentei derivar a versão discreta que ajudou a fazer as coisas mais sensatas:
De alguma formafktn= f( n , k , N)
assim
Feito!
fonte