要检查这一点,我编写了一些代码,产生了以下图像,这似乎证实了我的想法。
“使用等式的时间”的用法等式
$$ X_f = \ sum_ {n = 0} ^ {N-1} x_n(\ cos(2 \ pi f t_n)-i \ sin(2 \ pi f t_n))$$
,其中$ t $是时间向量(例如,采样$ x_n $的时间$ t_n $)。可以在下面的函数
ft
中找到。上面链接的维基百科方程式复制到此处,以供参考:
$$ X_f = \ sum_ {n = 0} ^ {N- 1} x_n \ left(\ cos \ left(2 \ pi f \ frac {n} {N} \ right)-i \ sin \ left(2 \ pi f \ frac {n} {N} \ right)\ right )$$
可以在函数
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()
显然,我不太可能在如此高的温度下随机发现错误个人资料Wiki页面。但是我看不到自己做过的错误吗?
#1 楼
您在ft2
中有错误。您将同时增加i
和freq
。那不是您希望汇总工作的方式。我搞砸了修复它,但它变得混乱了。我决定从不连续的角度重写它,而不是尝试使用连续的术语。在DFT中,采样速率无关紧要。重要的是使用了多少样本(N
)。档号(k
)然后对应于频率,以每帧周期为单位。我试图使您的代码尽可能完整,以使您容易理解。我还展开了DFT计算循环,希望可以更好地揭示它们的性质。希望对您有所帮助。
Ced
import numpy as np import matplotlib.pyplot as plt def ft(t, s, fs): freq_step = fs / len(s) freqs = np.arange(0, fs/2, 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 ft3(s, N): # More efficient form of wikipedia equation S = [] slice = 0.0 sliver = 2*np.pi/float(N) for k in range(N/2): sum_real = 0.0 sum_imag = 0.0 angle = 0.0 for n in range(N): sum_real += s[n] * np.cos(angle) sum_imag += -s[n] * np.sin(angle) angle += slice slice += sliver tmpsum = (sum_real**2 + sum_imag**2) ** 0.5 S.append(tmpsum) return S def ft4(s, N): # Using wikipedia equation S = [] for k in range(N/2): sum_real = 0.0 sum_imag = 0.0 for n in range(N): sum_real += s[n] * np.cos(2*np.pi*k*n/float(N)) sum_imag += -s[n] * np.sin(2*np.pi*k*n/float(N)) tmpsum = (sum_real**2 + sum_imag**2) ** 0.5 S.append(tmpsum) return S def ft5(s, N): # Roots of Unity Weighted Sum sliver = 2 * np.pi / float( N ) root_real = np.zeros( N ) root_imag = np.zeros( N ) angle = 0.0 for r in range(N): root_real[r] = np.cos( angle ) root_imag[r] = -np.sin( angle ) angle += sliver S = [] for k in range( N/2 ): sum_real = 0.0 sum_imag = 0.0 r = 0 for n in range( N ): sum_real += s[n] * root_real[r] sum_imag += s[n] * root_imag[r] r += k if r >= N : r -= N tmpsum = np.sqrt( sum_real*sum_real + sum_imag*sum_imag ) S.append( tmpsum ) return S def main(): N = 200 fs = 100.0 time_step = 1.0 / fs t = np.arange(0, N * time_step, time_step) f = 5.0 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 = ft3(y, N) ax = fig.add_subplot(313) ax.set_title('Using Wiki equation') ax.set_xlabel('frequency') ax.set_xticks(np.arange(0, freqs[-1], 2)) print len(S), len(freqs) ax.plot(freqs, S) plt.tight_layout() plt.show() main()
评论
$ \ begingroup $
顺便说一句,您可能遇到了问题,因为我的代码假定使用python3;)
$ \ endgroup $
– Nimitz14
18年4月27日在18:33
$ \ begingroup $
@ Nimitz14,没什么大不了的。我在数字上添加了“ float()”和一堆“ .0”。您的代码运行良好,我唯一需要删除的是“ plt.style.use('ggplot')”语句。
$ \ endgroup $
–雪铁龙·道格(Cedron Dawg)
18年4月27日在18:46
$ \ begingroup $
@ Nimitz14,我忘了提了,我在代码中添加了ft5例程,该例程预先计算了单位值的根,并真正显示了如何为每个bin使用相同的根来计算DFT。
$ \ endgroup $
–雪铁龙·道格(Cedron Dawg)
18年4月27日在21:19
#2 楼
我不会看你的代码。维基百科页面看起来还不错,但这是数学家和电气工程师之间“格式大战”或“符号大战”或“风格大战”的一个很好的例子。其中一些,我认为数学界人士是正确的。 EE永远不要为虚构单位采用“ $ j $”。也就是说,这是DFT的更好表达,反之则是:DFT:
$$ X [k] = \ sum \ limits_ {n = 0} ^ {N-1 } x [n] \,e ^ {-j 2 \ pi nk / N} $$
iDFT:
$$ x [n] = \ frac {1} {N} \ sum \ limits_ {k = 0} ^ {N-1} X [k] \,e ^ {j 2 \ pi nk / N} $$
因为执行DSP的电气工程师喜欢使用$ x [n] $是“时间”中的样本序列,$ X [k] $是“频率”中的离散样本序列。数学家可能会更喜欢这样:
DFT:
$$ X_k = \ sum \ limits_ {n = 0} ^ {N-1} x_n \,e ^ {-i 2 \ pi nk / N} $$
iDFT:
$$ x_n = \ frac {1} {N} \ sum \ limits_ {k = 0} ^ {N-1} X_k \, e ^ {i 2 \ pi nk / N} $$
,与Wikipedia页面相同。
您可能需要更加注意使用指数中的$ + $或$-$以及如何相对于$ \ sin(\ cdot)$项将其转换为$ + $或$-$。
评论
$ \ begingroup $
如果我们使用i而不是j,就不能说ICE人是ELI。 ELJ JCE男子没有相同的戒指。文明将受到威胁
$ \ endgroup $
–user28715
18年4月26日在3:30
$ \ begingroup $
以利亚(Elijah)是汁人吗?
$ \ endgroup $
–罗伯特·布里斯托-约翰逊
18年4月26日在9:59
$ \ begingroup $
@ user28715好吧,在那种情况下,我的当前值不是负1的平方根。...youtube.com/watch?v=2yqjMiFUMlA
$ \ endgroup $
– Peter K.♦
20年1月15日在15:21
#3 楼
我回到了这一点,并尝试导出离散版本,这使事情变得更有意义:以某种方式$ f_k t_n = f(n,k,N)$
$ f_k = \ frac {f_s} {N} k $和$ t_n = \ frac {T} {N} n $
$ f_s = \ frac {N} {T} $
$ f_k t_n = \ frac {f_s} {N} k \ frac {T} {N} n = \ frac {N} {TN} k \ frac {T} { N} n = \ frac {kn} {N} $
完成!
评论
为了更深入地了解DFT的含义,我建议您阅读我的前两篇博客文章:“复杂单位圆的指数性质”(dsprelated.com/showarticle/754.php)和“ DFT图形解释:质心”加权根源”(dsprelated.com/showarticle/768.php)。谢谢,我来看看。老实说,由于代码中的一个非常愚蠢的错误而引起的关注,我实在感到非常惊讶。
我也很惊讶连续与离散的关系虽然很大。我的博客全都涉及离散案例,而没有提及连续案例,这与将离散案例作为连续案例的样本版本进行教学有所不同。