Python FFT中的DC项-常数项的振幅

Python FFT中的DC项-常数项的振幅,python,numpy,matplotlib,signal-processing,fft,Python,Numpy,Matplotlib,Signal Processing,Fft,我创建了一个FFT类/对象,它接收存储在2D数组中的信号,并在将其打印到matplotlib图之前生成其输入的后续FFT 经过大量阅读后,我意识到由于加窗,数据集中需要理想的2^x个点和整数个周期,峰值的振幅永远不会100%准确(但将大致正确) 然而,当我将直流偏移添加到信号中时,出于某种原因,0 Hz频率的峰值始终是实际直流/恒定偏移的两倍!例如,如果我在x Hz的正弦波上加2,在FFT上得到x Hz处的峰值,在0处得到4的峰值 为什么会这样?我能纠正一下吗 谢谢 我使用的代码如下: impo

我创建了一个FFT类/对象,它接收存储在2D数组中的信号,并在将其打印到matplotlib图之前生成其输入的后续FFT

经过大量阅读后,我意识到由于加窗,数据集中需要理想的2^x个点和整数个周期,峰值的振幅永远不会100%准确(但将大致正确)

然而,当我将直流偏移添加到信号中时,出于某种原因,0 Hz频率的峰值始终是实际直流/恒定偏移的两倍!例如,如果我在x Hz的正弦波上加2,在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缩放时为半个纯正弦振幅,但直流分量和N/2余弦分量除外,这两个分量未被分为2个FFT结果,因此没有减半。

简单地对信号执行
np.fft.fft(hTArray[:,1])
有什么不对?如果你没有得到正确的直流分量的振幅,我会说你的因子
((2.0)*self.buff/(self.N*(self.scaling))
一定是错的。这个因子对所有项的影响都是一样的,但只有DC/0Hz项始终是它的真实值的两倍。我怎么才能纠正这个错误呢?使用python rfft可以避免这个问题吗?谢谢将所有结果除以2。然后,将两个复共轭对半相加,使镜像结果加倍(与乘以2相同)。DC组件没有镜像(或者有人说是镜像的,但已经添加到它自己),因此不需要额外的乘以2。