Python FFT 中的直流项 - 常数项的幅度
DC Term in Python FFT - Amplitude of Constant Term
我创建了一个 FFT class/object,它获取存储在二维数组中的信号并生成其输入的后续 FFT,然后将其打印到 matplotlib 图。
经过大量阅读,我意识到由于开窗,理想情况下需要在数据集中有 2^x 个点和整数个周期,峰值的幅度永远不会100% 准确(但大致正确)。
但是,当我向信号添加直流偏移时,出于某种原因,0 Hz 频率的峰值始终恰好是实际 DC/constant 偏移的两倍!例如,如果我将 2 加到 x Hz 的正弦波上,我会在 FFT 上得到 x Hz 处的峰值,以及 0 处的 4 峰值。
这是为什么 - 我可以更正吗?
谢谢!
我使用的代码如下:
import numpy as np
import matplotlib.pyplot as plt
class FFT:
def __init__(self, time, signal, buff=1, scaling=2, centre=False):
self.signal = signal
self.buff = buff
self.time = time
self.scaling = scaling
self.centre = centre
if (centre):
self.scaling = 1
def fft(self):
self.Y = np.fft.fft(self.signal, self.buff * len(self.signal)) # Do fft on signal and store
if (self.centre is True):
self.Y = np.fft.fftshift(self.Y) # centre 0 frequency in centre
self.__graph__()
def __graph__(self):
self.N = len(self.Y) / self.scaling # get FFT length (halved to avoid reflection)
print (self.N)
self.fa = 1 / (self.time[1] - self.time[0]) # get time interval & sampling frequency of FFT
if (self.centre is True):
self.t_axis = np.linspace(-self.fa / 2 * self.scaling, self.fa / 2 * self.scaling, self.N, endpoint=True) # create x axis vector from 0 to nyquist freq. (fa/2) with N values
else:
self.t_axis = np.linspace(0, self.fa / self.scaling, self.N, endpoint=True) # create x axis vector from 0 to nyquist freq. (fa/2) with N values
def show(self, absolute=True):
if absolute:
plt.plot(self.t_axis, ((2.0) * self.buff / (self.N * (self.scaling))) * np.abs(self.Y[0:self.N]))
else:
plt.plot(self.t_axis, ((2.0) * self.buff / (self.Ns * (self.scaling))) * self.Y[0:self.N]) # multiply y axis by 2/N to get actual values
plt.grid()
plt.show()
def sineExample(start=0, dur=128, samples=16384):
t = np.linspace(start, dur + start, samples, True)
print(t)
f = 10.0 # Frequency in Hz
A = 10.0 # Amplitude in Unit
retarr = np.zeros(len(t))
retarr = np.column_stack((t, retarr))
for row in range(len(retarr)):
retarr[row][1] = A * np.sin(2 * np.pi * f * retarr[row][0]) + 2 # Signal
print(retarr)
return retarr
hTArray = sineExample()
# plt.plot(hTArray[:,0], hTArray[:,1])
# plt.grid()
# plt.show()
myFFT = FFT(hTArray[:, 0], hTArray[:, 1], scaling=2,centre=False)
myFFT.fft()
myFFT.show()
其实恰恰相反。严格实数数据的全复数 FFT 结果中的所有其他频率被分成 2 个结果箱并镜像为复数共轭,因此当按 1/N 缩放时纯正弦波幅度的一半,除了 DC 分量和 N/2 余弦分量,未拆分为 2 个 FFT 结果,因此未减半。
我创建了一个 FFT class/object,它获取存储在二维数组中的信号并生成其输入的后续 FFT,然后将其打印到 matplotlib 图。
经过大量阅读,我意识到由于开窗,理想情况下需要在数据集中有 2^x 个点和整数个周期,峰值的幅度永远不会100% 准确(但大致正确)。
但是,当我向信号添加直流偏移时,出于某种原因,0 Hz 频率的峰值始终恰好是实际 DC/constant 偏移的两倍!例如,如果我将 2 加到 x Hz 的正弦波上,我会在 FFT 上得到 x Hz 处的峰值,以及 0 处的 4 峰值。
这是为什么 - 我可以更正吗?
谢谢!
我使用的代码如下:
import numpy as np
import matplotlib.pyplot as plt
class FFT:
def __init__(self, time, signal, buff=1, scaling=2, centre=False):
self.signal = signal
self.buff = buff
self.time = time
self.scaling = scaling
self.centre = centre
if (centre):
self.scaling = 1
def fft(self):
self.Y = np.fft.fft(self.signal, self.buff * len(self.signal)) # Do fft on signal and store
if (self.centre is True):
self.Y = np.fft.fftshift(self.Y) # centre 0 frequency in centre
self.__graph__()
def __graph__(self):
self.N = len(self.Y) / self.scaling # get FFT length (halved to avoid reflection)
print (self.N)
self.fa = 1 / (self.time[1] - self.time[0]) # get time interval & sampling frequency of FFT
if (self.centre is True):
self.t_axis = np.linspace(-self.fa / 2 * self.scaling, self.fa / 2 * self.scaling, self.N, endpoint=True) # create x axis vector from 0 to nyquist freq. (fa/2) with N values
else:
self.t_axis = np.linspace(0, self.fa / self.scaling, self.N, endpoint=True) # create x axis vector from 0 to nyquist freq. (fa/2) with N values
def show(self, absolute=True):
if absolute:
plt.plot(self.t_axis, ((2.0) * self.buff / (self.N * (self.scaling))) * np.abs(self.Y[0:self.N]))
else:
plt.plot(self.t_axis, ((2.0) * self.buff / (self.Ns * (self.scaling))) * self.Y[0:self.N]) # multiply y axis by 2/N to get actual values
plt.grid()
plt.show()
def sineExample(start=0, dur=128, samples=16384):
t = np.linspace(start, dur + start, samples, True)
print(t)
f = 10.0 # Frequency in Hz
A = 10.0 # Amplitude in Unit
retarr = np.zeros(len(t))
retarr = np.column_stack((t, retarr))
for row in range(len(retarr)):
retarr[row][1] = A * np.sin(2 * np.pi * f * retarr[row][0]) + 2 # Signal
print(retarr)
return retarr
hTArray = sineExample()
# plt.plot(hTArray[:,0], hTArray[:,1])
# plt.grid()
# plt.show()
myFFT = FFT(hTArray[:, 0], hTArray[:, 1], scaling=2,centre=False)
myFFT.fft()
myFFT.show()
其实恰恰相反。严格实数数据的全复数 FFT 结果中的所有其他频率被分成 2 个结果箱并镜像为复数共轭,因此当按 1/N 缩放时纯正弦波幅度的一半,除了 DC 分量和 N/2 余弦分量,未拆分为 2 个 FFT 结果,因此未减半。