首页/文章/ 详情

白噪声最小二乘拟合及傅里叶变换降噪

2年前浏览2379


在信号处理中常常需要用到曲线拟合,这里介绍一下利用最小二乘拟合一般曲线的方法,并对滤掉信号中白噪声的方法作些介绍。


为了测试拟合算法的好坏,先模拟出一个信号作为检验算法的例子:


1

用白噪声产生模拟信号

对于理论信号y=y(x),一般可用rand(size(x)) 和randn(size(x)) 生成随机噪声信号,两者的区别在于rand 生成的噪声信号都是正值,而randn 生成的噪声信号则是正负跳跃分布的,所以randn 作为白噪声信号,更符合实际情况:


   

f0=@(c,x)( (x>=0&x<c(1))*0 (x>=c(1)&x<c(2))*c(3)/(c(2)-c(1)).*(x-c(1)) (x>=c(2)&x<c(4)).*( (c(5)-c(3))/(c(4)-c(2))*(x-c(2)) c(3) ) (x>=c(4)&x<c(6))*c(5)/(c(4)-c(6)).*(x-c(6)) (x>=c(6))*0 ); 

disp('real c0'); 

c0=[1, 2, 1, 5, 2, 6] 

x_int=0:0.002:10; 

y_int=f0(c0,x_int); 

%(x_int, y_int) is perfect zigzag signal 

%sig=y_int 0.5*rand(size(x_int)); 

sig=y_int 0.5*randn(size(x_int));

rand noise

randn noise


2

最小二乘折线拟合

考虑到需要拟合的函数是个分段的折线函数,首先需要建立含有固定参数的折线函数的数学模型,算法如下图:



按照这个算法,用matlab搭建的代码如下:


   

% try zigzag fitting 

f2=@(c,x)( (x>=0&x<c(1))*0 (x>=c(1)&x<c(2))*c(3)/(c(2)-c(1)).*(x-c(1)) (x>=c(2)&x<c(4)).*( (c(5)-c(3))/(c(4)-c(2))*(x-c(2)) c(3) ) (x>=c(4)&x<c(6))*c(5)/(c(4)-c(6)).*(x-c(6)) (x>=c(6))*0 );

c0=[1.1, 1.5, 1.8, 5.4, 2.5, 5.6];

c_fit=nlinfit(x_int,sig,f2,c0);

y2=f2(c_fit,x_int);

figure();

plot(x_int,sig,'blue');

hold on

plot(x_int,y2,'red --','linewidth',2);

legend('sig','zigzag fitting');


真实参数:1,2,1,5,2,6


拟合参数:1.0237,2.06,1.0107,4.9479,2.1101,6.0005


可以看到,拟合的参数多少和真实的参数存在一些差异,但是已经非常接近。


3

傅里叶变换降噪

如果要进一步提高拟合的精度,需要设法降低白噪声的干扰。因为白噪声是一种宽谱的干扰,所以常用的带通滤波处理是不可行的,这里可以考虑对信号进行傅立叶变换,滤掉其中强度较弱的白噪声频域成分。


     

Fs=1/(x_int(2)-x_int(1));

nfft=length(sig);

sig_fft_comp=fft(sig);

sig_fft_real=2*abs(sig_fft_comp)/nfft;

% adjust the distribution of spectrum according to double frequency direction

sig_fft_real_adjust=[sig_fft_real(round(nfft/2 1):end),sig_fft_real(1:round(nfft/2))];

f_double=linspace(-Fs/2,Fs/2,nfft);

% apply the A(f) strength filter

Af_level=0.01;

Af_lim=Af_level*max(sig_fft_real);

i_fd=find(sig_fft_real<Af_lim);

sig_fft_fit=sig_fft_comp;

sig_fft_fit(i_fd)=0;

figure();

plot(f_double,sig_fft_real_adjust);

xlabel('f(Hz)');

ylabel('A(f)');

xlim([f_double(1),f_double(end)]);

hold on

plot(f_double,Af_lim*ones(size(f_double)),'red --','linewidth',1);

legend('spectrum','Af limit');

% reconstruct the signal with filtered spectrum

sig_fit=ifft(sig_fft_fit);

% perform fitting for the A filtered signal

disp('fit c0 after A filter');

c_fit3=nlinfit(x_int,sig_fit,f2,c0)

y3=f2(c_fit3,x_int);

% compare signal and fitted signal

figure();

plot(x_int,sig,'black',x_int,sig_fit,'red');

hold on

plot(x_int,y3,'green --','linewidth',2);

legend('sig','Fourier fit','zigzag fit');


傅里叶降噪后结果如下:


此时算得的拟合系数是:1.0677,1.8680, 0.9665,5.0140,1.9736,5.9895。


这比降噪前的效果稍好了一些,更贴近与真实的折线系数。但是编程的复杂度上升了很多,在对拟合的精度要求不是太高的情况下,可以不用作傅里叶降噪的处理。


【免责声明】本文自博客园DocNan的博客,版权归原作者所有,仅用于学习等,对文中观点判断均保持中立,若您认为文中来源标注与事实不符,若有涉及版权等请告知,将及时修订删除,谢谢大家的关注!



来源:CAE之家
代码&命令科普声学理论
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2022-09-19
最近编辑:2年前
CAE之家
硕士 | CAE仿真负责人 个人著作《汽车NVH一本通》
获赞 1132粉丝 5926文章 918课程 19
点赞
收藏
作者推荐
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈