如何在执行 FFT 后将复数转换回 "normal" 数
How to convert complex numbers back into "normal" numbers after performing FFT
比如说,我有一个示例信号由三个余弦组成,每个余弦代表 4、6 和 8 频带。现在,我使用 FFT 将此信号放入频域,并在频域中切断不需要的 6 Hz 频带。最后,我想将信号从频域反转回时域。但是当我简单地使用 numpy.fft.ifft
时,我得到了复数数组,这不是进一步分析信号的最佳结果。如何在执行带通后反转 FFT,以便将实部和虚部作为一个数字携带的全部信息?我调查了 z = sqrt(real^2 + imaginary^2)
的事情,但它不是 "thing"。
下面我提供了一个工作示例。我会很感激你的帮助。
import numpy as np
from scipy.fftpack import fftfreq
# Define signal.
Fs = 128 # Sampling rate.
Ts = 1 / Fs # Sampling interval.
Time = np.arange(0, 10, Ts) # Time vector.
signal = np.cos(4*np.pi*Time) + np.cos(6*np.pi*Time) + np.cos(8*np.pi*Time)
def spectrum(sig, t):
"""
Represent given signal in frequency domain.
:param sig: signal.
:param t: time scale.
:return:
"""
f = fftfreq(sig.size, d=t[1]-t[0])
y = np.fft.fft(sig)
return f, np.abs(y)
def bandpass(f, sig, min_freq, max_freq):
"""
Bandpass signal in a specified by min_freq and max_freq frequency range.
:param f: frequency.
:param sig: signal.
:param min_freq: minimum frequency.
:param max_freq: maximum frequency.
:return:
"""
return np.where(np.logical_or(f < min_freq, f > max_freq), 0, sig)
freq, spec = spectrum(signal, Time)
signal_filtered = np.fft.ifft(bandpass(freq, spec, 5, 7))
print(signal_filtered)
"""
print(signal_filtered) result:
[ 2.22833798e-15 +0.00000000e+00j 2.13212081e-15 +6.44480810e-16j
1.85209996e-15 +1.23225456e-15j ..., 1.41336488e-15 -1.71179288e-15j
1.85209996e-15 -1.23225456e-15j 2.13212081e-15 -6.44480810e-16j]
"""
如果你想截掉5到7之间的频率,
那么您需要将频率保持在
(f < min_freq) | (f > max_freq)
相当于
np.logical_or(f < min_freq, f > max_freq)
因此,使用
return np.where(np.logical_or(f < min_freq, f > max_freq), sig, 0)
而不是
return np.where(np.logical_or(f < min_freq, f > max_freq), 0, sig)
因为 np.where
的第二个参数包含条件为真时 np.where
返回的值。
通过这一更改,您的代码产生了
[ 3.00000000 +0.00000000e+00j 2.96514652 +1.24442385e-15j
2.86160515 +2.08976636e-15j ..., 2.69239924 +4.71763845e-15j
2.86160515 +5.88163496e-15j 2.96514652 +6.82134642e-15j]
请注意,如果您的信号是真实的,您可以使用 rfft
对实数序列进行离散傅里叶变换,并使用 irfft
对其进行逆变换,并使用 rfftfreq
进行生成频率。
例如,
from __future__ import division
import numpy as np
import scipy.fftpack as fftpack
# Define signal.
Fs = 128 # Sampling rate.
Ts = 1 / Fs # Sampling interval.
Time = np.arange(0, 10, Ts) # Time vector.
signal = np.cos(4*np.pi*Time) + np.cos(6*np.pi*Time) + np.cos(8*np.pi*Time)
def spectrum(sig, t):
"""
Represent given signal in frequency domain.
:param sig: signal.
:param t: time scale.
:return:
"""
f = fftpack.rfftfreq(sig.size, d=t[1]-t[0])
y = fftpack.rfft(sig)
return f, np.abs(y)
def bandpass(f, sig, min_freq, max_freq):
"""
Bandpass signal in a specified by min_freq and max_freq frequency range.
:param f: frequency.
:param sig: signal.
:param min_freq: minimum frequency.
:param max_freq: maximum frequency.
:return:
"""
return np.where(np.logical_or(f < min_freq, f > max_freq), sig, 0)
freq, spec = spectrum(signal, Time)
signal_filtered = fftpack.irfft(bandpass(freq, spec, 5, 7))
print(signal_filtered)
产量
[ 3. 2.96514652 2.86160515 ..., 2.69239924 2.86160515
2.96514652]
注意这里必须使用scipy
的fftpack
;不要将 SciPy 的实现与 NumPy 的实现混用。
如果你想要一个严格的实数结果(减去舍入误差噪声),你的 IFFT 输入需要是 hermician 对称的(例如你需要确保复数数组的后半部分是复数共轭镜像上半场)。查看真实数据的初始 FFT,您会看到对称性。
但看起来您没有过滤负频率,因此向 IFFT 发送了一个不对称的输入,然后输出了一个复数结果。
比如说,我有一个示例信号由三个余弦组成,每个余弦代表 4、6 和 8 频带。现在,我使用 FFT 将此信号放入频域,并在频域中切断不需要的 6 Hz 频带。最后,我想将信号从频域反转回时域。但是当我简单地使用 numpy.fft.ifft
时,我得到了复数数组,这不是进一步分析信号的最佳结果。如何在执行带通后反转 FFT,以便将实部和虚部作为一个数字携带的全部信息?我调查了 z = sqrt(real^2 + imaginary^2)
的事情,但它不是 "thing"。
下面我提供了一个工作示例。我会很感激你的帮助。
import numpy as np
from scipy.fftpack import fftfreq
# Define signal.
Fs = 128 # Sampling rate.
Ts = 1 / Fs # Sampling interval.
Time = np.arange(0, 10, Ts) # Time vector.
signal = np.cos(4*np.pi*Time) + np.cos(6*np.pi*Time) + np.cos(8*np.pi*Time)
def spectrum(sig, t):
"""
Represent given signal in frequency domain.
:param sig: signal.
:param t: time scale.
:return:
"""
f = fftfreq(sig.size, d=t[1]-t[0])
y = np.fft.fft(sig)
return f, np.abs(y)
def bandpass(f, sig, min_freq, max_freq):
"""
Bandpass signal in a specified by min_freq and max_freq frequency range.
:param f: frequency.
:param sig: signal.
:param min_freq: minimum frequency.
:param max_freq: maximum frequency.
:return:
"""
return np.where(np.logical_or(f < min_freq, f > max_freq), 0, sig)
freq, spec = spectrum(signal, Time)
signal_filtered = np.fft.ifft(bandpass(freq, spec, 5, 7))
print(signal_filtered)
"""
print(signal_filtered) result:
[ 2.22833798e-15 +0.00000000e+00j 2.13212081e-15 +6.44480810e-16j
1.85209996e-15 +1.23225456e-15j ..., 1.41336488e-15 -1.71179288e-15j
1.85209996e-15 -1.23225456e-15j 2.13212081e-15 -6.44480810e-16j]
"""
如果你想截掉5到7之间的频率, 那么您需要将频率保持在
(f < min_freq) | (f > max_freq)
相当于
np.logical_or(f < min_freq, f > max_freq)
因此,使用
return np.where(np.logical_or(f < min_freq, f > max_freq), sig, 0)
而不是
return np.where(np.logical_or(f < min_freq, f > max_freq), 0, sig)
因为 np.where
的第二个参数包含条件为真时 np.where
返回的值。
通过这一更改,您的代码产生了
[ 3.00000000 +0.00000000e+00j 2.96514652 +1.24442385e-15j
2.86160515 +2.08976636e-15j ..., 2.69239924 +4.71763845e-15j
2.86160515 +5.88163496e-15j 2.96514652 +6.82134642e-15j]
请注意,如果您的信号是真实的,您可以使用 rfft
对实数序列进行离散傅里叶变换,并使用 irfft
对其进行逆变换,并使用 rfftfreq
进行生成频率。
例如,
from __future__ import division
import numpy as np
import scipy.fftpack as fftpack
# Define signal.
Fs = 128 # Sampling rate.
Ts = 1 / Fs # Sampling interval.
Time = np.arange(0, 10, Ts) # Time vector.
signal = np.cos(4*np.pi*Time) + np.cos(6*np.pi*Time) + np.cos(8*np.pi*Time)
def spectrum(sig, t):
"""
Represent given signal in frequency domain.
:param sig: signal.
:param t: time scale.
:return:
"""
f = fftpack.rfftfreq(sig.size, d=t[1]-t[0])
y = fftpack.rfft(sig)
return f, np.abs(y)
def bandpass(f, sig, min_freq, max_freq):
"""
Bandpass signal in a specified by min_freq and max_freq frequency range.
:param f: frequency.
:param sig: signal.
:param min_freq: minimum frequency.
:param max_freq: maximum frequency.
:return:
"""
return np.where(np.logical_or(f < min_freq, f > max_freq), sig, 0)
freq, spec = spectrum(signal, Time)
signal_filtered = fftpack.irfft(bandpass(freq, spec, 5, 7))
print(signal_filtered)
产量
[ 3. 2.96514652 2.86160515 ..., 2.69239924 2.86160515
2.96514652]
注意这里必须使用scipy
的fftpack
;不要将 SciPy 的实现与 NumPy 的实现混用。
如果你想要一个严格的实数结果(减去舍入误差噪声),你的 IFFT 输入需要是 hermician 对称的(例如你需要确保复数数组的后半部分是复数共轭镜像上半场)。查看真实数据的初始 FFT,您会看到对称性。
但看起来您没有过滤负频率,因此向 IFFT 发送了一个不对称的输入,然后输出了一个复数结果。