我有一个长度为T的实矢量时间序列x和一个长度为t <&lt;&lt; T. h是傅立叶空间中的滤波器,真实且对称。大概是1 / f。
我想用h过滤x得到y。
假设t == T且长度为T的FFT可以适合存储器(两者都不是真的)。要在python中获取我的过滤后的x,我会这样做:
import numpy as np
from scipy.signal import fft, ifft
y = np.real( np.ifft( np.fft(x) * h ) ) )
由于条件不成立,我尝试了下面的黑客攻击:
这是一个好策略吗?如何以良好的方式选择填充P?这样做的正确方法是什么?我不太了解信号处理。这是一个学习的好机会。
我正在使用cuFFT来加快速度,因此如果大部分操作都是FFT,那就太棒了。实际问题是3D。另外,我并不关心非因果过滤器中的伪影。
谢谢, 保罗。
答案 0 :(得分:6)
你走在正确的轨道上。该技术称为overlap-save processing。 t
是否足够短,以至于该长度的FFT适合内存?如果是这样,您可以选择B
块大小B > 2*min(length(x),length(h))
,以便进行快速转换。然后当你处理时,你放弃y_b
的前半部分,而不是从两端掉落。
要了解为什么要放弃上半部分,请记住频谱乘法与时域中的循环卷积相同。与零填充h
进行对比会在结果的前半部分产生奇怪的毛刺瞬变,但到了后半部分所有瞬态都消失了,因为x
中的圆形包络点与零部分对齐h
。用"Theory and Application of Digital Signal Processing" by Lawrence Rabiner and Bernard Gold中的图片对此进行了很好的解释。
重要的是,您的时域过滤器至少在一端逐渐变为0,这样您就不会出现响铃现象。您提到h
在频域中是真实的,这意味着它具有全0阶段。通常,这种信号仅以循环方式连续,并且当用作滤波器时将在整个频带中产生失真。创建合理滤波器的一种简单方法是在频域中使用0相位,逆变换和旋转进行设计。例如:
def OneOverF(N):
import numpy as np
N2 = N/2; #N has to be even!
x = np.hstack((1, np.arange(1, N2+1), np.arange(N2-1, 0, -1)))
hf = 1/(2*np.pi*x/N2)
ht = np.real(np.fft.ifft(hf)) # discard tiny imag part from numerical error
htrot = np.roll(ht, N2)
htwin = htrot * np.hamming(N)
return ht, htrot, htwin
(我对Python很陌生,请告诉我是否有更好的方法来编写代码)。
如果您比较ht
,htrot
和htwin
的频率响应,您会看到以下内容(x轴的归一化频率最高为pi
):
ht
,在顶部,有很多波纹。这是由于边缘的不连续性。 htrot
,在中间,更好,但仍然有波纹。 htwin
很好而且很平滑,代价是以稍高的频率展平。请注意,您可以使用较大的N值来扩展直线段的长度。
我写过关于不连续性的问题,如果你想看到更多的细节,还在another SO question写了一个Matlab / Octave例子。