Python和科学计算认证群组  - 讨论区

标题:如何利用FFT消除光谱噪声

2011年08月02日 星期二 00:10

import numpy, pylab
from numpy import fft, pi, sin

x = numpy.arange(0,2,0.01)
signal = sin(2*pi*(x-1/4))
 
noise = 0.5*numpy.random.randn(len(x))

rawsignal = signal + noise

FFT = fft.fft(rawsignal)

pylab.plot(x,signal, label = 'noise free signal')
pylab.plot(x,rawsignal, label = 'noised signal')

pylab.plot(x,FFT, label = 'FFT signal')

pylab.legend()

为什么fft.fft()得到的结果不是有用信号?

 

2011年08月02日 星期二 06:47

FFT得到的是频域信号,和时域信号画在一起没有意义。下面是修改之后的程序:

import numpy, pylab

 

from numpy import fft, pi, sin, log10, abs

 

x = numpy.arange(0,2,0.01)

signal = sin(2*pi*(x-1/4))

 

noise = 0.5*numpy.random.randn(len(x))

 

rawsignal = signal + noise

 

FFT = fft.fft(rawsignal)

pylab.subplot(211)

pylab.plot(x,signal, label = 'noise free signal')

pylab.plot(x,rawsignal, label = 'noised signal')

pylab.subplot(212)

f = numpy.linspace(0, 0.5/(x[1]-x[0]), len(x)/2+1)

p = 20*log10(abs(FFT))[:len(x)/2+1]

pylab.plot(f,p, label = 'FFT signal')

pylab.legend()

由下图可以看到频率在1Hz处频谱有一个峰值,那个就是1Hz正弦波信号对应的频谱,其它的频率的频谱都是噪声信号的。根据信号的频谱设计一个滤波器对信号进行滤波即可。也可以用FFT滤波器,删除频谱中噪声信号的成分之后再用IFFT转换会时域信号。

2011年08月02日 星期二 15:43

请问 如何用FFT滤波器,删除频谱中噪声信号的成分之后再用IFFT转换会时域信号?

能否就上面的例子演示下。

 

2011年08月02日 星期二 18:15

你的例子中数据的长度不是2的整数次幂,你要滤波的实际数据是怎样的?

2011年08月03日 星期三 02:37

可以将例子中的数据长度改成2的任意整数次幂,我想看看FFT虑波去除噪生效果.

2011年08月03日 星期三 08:50

from numpy import arange, sin, random, fft, pi, linspace, log10, zeros

from pylab import subplot, plot, legend, semilogx

 

x = arange(0,2,1.0/2048)

signal = sin(2*pi*(5*x-1/4.0))

 

noise = 0.5*random.randn(len(x))

 

rawsignal = signal + noise

 

FFT = fft.rfft(rawsignal)

 

mask = zeros(len(FFT))

mask[10] = 1

 

subplot(211)

plot(x,signal, label = 'noise free signal')

plot(x,rawsignal, label = 'noised signal')

plot(x, fft.irfft(FFT*mask), label='fft filter', lw=2)

subplot(212)

f = linspace(0, 0.5/(x[1]-x[0]), len(x)/2+1)

p = 20*log10(abs(FFT))

semilogx(f,p, label = 'FFT signal')

legend()

滤波的结果和mask数组有关,这里只过滤出正弦波所对应的频率,所以滤波效果很好。

2011年08月03日 星期三 14:53

如果不知道有用信号频率的情况,如何设定 mask数组 ?

2011年08月03日 星期三 18:19

你还是举个实际的例子吧。如果只是正弦波的话,只要找到FFT中的最大值,将其ifft即可。

2011年08月03日 星期三 20:22

你发的这个数据是什么意思?逗号应该是小数点吗?

你用前面的程序把数据的频谱画出来看看。

2011年08月03日 星期三 20:45

代替 前面例子中的  signal = sin(2*pi*(5*x-1/4.0))

逗号应该是小数点(电脑系统导致的问题), 你的意思就是先画出原始信号的频谱,找到有用信号的频率位置 i ,再定义 mask[i] = 1 , 即可? 

2011年08月03日 星期三 20:58

是啊,你自己先试试看吧。

2011年08月03日 星期三 21:11

貌似我的原始信号fft后看不出特定频率的峰值, 此外频率轴

 f = numpy.linspace(0, 0.5/(x[1]-x[0]), len(x)/2+1),中间参数为什么不是 1/(x[1]-x[0])

 

2011年08月03日 星期三 21:57

这样的信号只需设计一个FIR低通滤波器,然后用filtfilt()滤波即可,不需要频域滤波。

2011年08月04日 星期四 09:03

x[1]-x[0] 是取样周期T,1/(x[1]-x[0])是取样频率Fs。而当取样频率为Fs时,它所取样的信号的最高频率为Fs/2。这个被称为香农定理。

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2024

    京ICP备05028076号