如何在 python 中从频域转换到时域
How to convert from frequency domain to time domain in python
我知道这是信号处理的基础,但是,我不确定我的方法有什么问题。我有一个信号作为阻尼正弦信号,采样频率为 5076Hz,样本数为 15,000。我从以下网站找到了如何将信号从时域转换为频域并设法获得 FFT 和频率值。代码可以在 link:
下面找到
Machine Learning with Signal Processing Techniques
def get_fft_values(y_values, T_s, N, f_s):
f_values = np.linspace(0.0, 1.0/(2.0*T), N//2)
fft_values_ = np.fft.rfft(y_values)
fft_values = 2.0/N * np.abs(fft_values_[0:N//2])
return f_values, fft_values
我设法获得了频率和 FFT 值。但是,我需要实现滤波器来去除信号中的一些噪声,因此,我创建了以下函数来实现滤波器部分:
def butter_bandpass(lowcut, highcut, fs, order):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='bandpass', output='ba')
return b, a
def butter_bandpass_filter(data, lowcut, highcut, fs, order):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
y = filtfilt(b=b, a=a, x=data)
# y = lfilter(b=b, a=a, x=data)
return y
我知道我需要执行以下步骤:
- 转换为频域
- 应用带通滤波器去除您不关心的频率
关于
- 通过逆傅里叶变换转换回时域
所以,我创建了以下逆变换函数,但是,我无法取回过滤后的信号,而且振幅几乎与原始信号不匹配。
(对于我的情况,我需要重新取样)
def get_ifft_values(fft_values, T, N, f_s):
# Time axis:
N = 9903
S_T = 1 / S_F
t_n = S_T * N # seconds of sampling
# Obtaining data in order to plot the graph:
x_time = np.linspace(0, t_n, N)
ifft_val = np.fft.irfft(fft_values, n=N)
y_s, x_time = scipy.signal.resample(x=ifft_val, num=N, t=x_time)
return x_time, y_s
我做错了什么?
编辑 1:
基于@Han-Kwang Nienhuys 的回答。我编辑了上面的代码并将其应用于以下方法:
##### Converting the signal into fft:
f_val, fft_val = get_fft_values(y_values=y, T=S_T, N=N, f_s=S_F)
# Applying bandpass filter:
fft_filt_val = butter_bandpass_filter(data=fft_val, lowcut=50, highcut=600, fs=S_F, order=2)
# Applying the inverse transform of the frequency domain:
x_time, y = get_ifft_values(fft_values=fft_filt_val, T=S_T, N=N, f_s=S_F)
以下是信号的结果:
- 原始信号的FFT:
- 原始信号的滤波 FFT:
- 来自滤波 FFT 的转换信号:
- 不应用带通滤波器:
有几个问题:
- 您正在使用
np.fft.fft
,它是一个复值离散傅里叶变换,包含的频率高达 Nyqvist 频率的两倍。高于 Nyqvist 频率的频率可以等效地解释为负频率。你确实是在使用频率切片[:N//2]
,但是如果你想要逆变换起作用,你还需要处理另一半频谱。
- 不要取FFT数据的绝对值。滤波器必须对复值系数进行运算。
- 如果您使用
scipy.signal.filtfilt
:该函数对时域数据进行操作,而不是对频域数据进行操作。
对于实值输入数据,使用实值 FFT 更容易,其表现更像您预期的那样:
n = len(y)
yf = np.fft.rfft(y)
fstep = f_sampling / n
freqs = np.arange(len(yf)) * fstep
要转换回来,使用np.fft.irfft
。
我知道这是信号处理的基础,但是,我不确定我的方法有什么问题。我有一个信号作为阻尼正弦信号,采样频率为 5076Hz,样本数为 15,000。我从以下网站找到了如何将信号从时域转换为频域并设法获得 FFT 和频率值。代码可以在 link:
下面找到Machine Learning with Signal Processing Techniques
def get_fft_values(y_values, T_s, N, f_s):
f_values = np.linspace(0.0, 1.0/(2.0*T), N//2)
fft_values_ = np.fft.rfft(y_values)
fft_values = 2.0/N * np.abs(fft_values_[0:N//2])
return f_values, fft_values
我设法获得了频率和 FFT 值。但是,我需要实现滤波器来去除信号中的一些噪声,因此,我创建了以下函数来实现滤波器部分:
def butter_bandpass(lowcut, highcut, fs, order):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='bandpass', output='ba')
return b, a
def butter_bandpass_filter(data, lowcut, highcut, fs, order):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
y = filtfilt(b=b, a=a, x=data)
# y = lfilter(b=b, a=a, x=data)
return y
我知道我需要执行以下步骤:
- 转换为频域
- 应用带通滤波器去除您不关心的频率 关于
- 通过逆傅里叶变换转换回时域
所以,我创建了以下逆变换函数,但是,我无法取回过滤后的信号,而且振幅几乎与原始信号不匹配。 (对于我的情况,我需要重新取样)
def get_ifft_values(fft_values, T, N, f_s):
# Time axis:
N = 9903
S_T = 1 / S_F
t_n = S_T * N # seconds of sampling
# Obtaining data in order to plot the graph:
x_time = np.linspace(0, t_n, N)
ifft_val = np.fft.irfft(fft_values, n=N)
y_s, x_time = scipy.signal.resample(x=ifft_val, num=N, t=x_time)
return x_time, y_s
我做错了什么?
编辑 1:
基于@Han-Kwang Nienhuys 的回答。我编辑了上面的代码并将其应用于以下方法:
##### Converting the signal into fft:
f_val, fft_val = get_fft_values(y_values=y, T=S_T, N=N, f_s=S_F)
# Applying bandpass filter:
fft_filt_val = butter_bandpass_filter(data=fft_val, lowcut=50, highcut=600, fs=S_F, order=2)
# Applying the inverse transform of the frequency domain:
x_time, y = get_ifft_values(fft_values=fft_filt_val, T=S_T, N=N, f_s=S_F)
以下是信号的结果:
- 原始信号的FFT:
- 原始信号的滤波 FFT:
- 来自滤波 FFT 的转换信号:
- 不应用带通滤波器:
有几个问题:
- 您正在使用
np.fft.fft
,它是一个复值离散傅里叶变换,包含的频率高达 Nyqvist 频率的两倍。高于 Nyqvist 频率的频率可以等效地解释为负频率。你确实是在使用频率切片[:N//2]
,但是如果你想要逆变换起作用,你还需要处理另一半频谱。 - 不要取FFT数据的绝对值。滤波器必须对复值系数进行运算。
- 如果您使用
scipy.signal.filtfilt
:该函数对时域数据进行操作,而不是对频域数据进行操作。
对于实值输入数据,使用实值 FFT 更容易,其表现更像您预期的那样:
n = len(y)
yf = np.fft.rfft(y)
fstep = f_sampling / n
freqs = np.arange(len(yf)) * fstep
要转换回来,使用np.fft.irfft
。