在处理数据的时候,一般会进行数据拟合,这时候免不了会有噪点,从而造成图像上的“飞点”。幸好Matlab自带一个平滑函数smooth
,笔者也是最近才晓得,做点笔记。
在Matlab Command Windows 中输入:
doc smooth
弹出来帮助文档,下面跟着帮助文档,记点有用的。
有关平滑的算法又叫滤波算法,滤波是什么意思?百度百科中写道:滤波(Wave filtering)是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施,滤波分为经典滤波和现代滤波。“滤”这个字让我想起了老妈在家里用的面粉筛
(图片来源于网络)就是过滤杂质的。把噪点想象成“杂质”,那么滤波的意思就显而易见了。
若窗口大小为5,则公式如下:
yy(1) = y(1)
yy(2) = (y(1) + y(2) + y(3))/3
yy(3) = (y(1) + y(2) + y(3) + y(4) + y(5))/5
yy(4) = (y(2) + y(3) + y(4) + y(5) + y(6))/5
...
如果理解滑动平均算法的话,其他算法也就好理解了。滑动平均算法可以看作和[1/n 1/n .. 1/n]
做卷积(相乘相加),其他算法:
就是将数据存储在GPU上面,可以加快计算效率,笔者曾经看到过一些GPU、CUP方面的知识并做了点总结,读者感兴趣可以看看:
https://blog.csdn.net/Gou_Hailong/article/details/113308630
如果想使用gpuArray的话,需安装支持它的相应matlab版本。
有关GPU的知识,笔者了解还尚浅,暂不能做详细的笔记
yy = smooth(y)
yy = smooth(y,span)
yy = smooth(y,method)
yy = smooth(y,span,method)
yy = smooth(y,'sgolay',degree)
yy = smooth(y,span,'sgolay',degree)
yy = smooth(x,y,___)
gpuarrayYY = smooth(gpuarrayY,___)
gpuarrayYY = smooth(gpuarrayX,gpuarrayY,___)
Method | 描述 |
---|---|
moving(默认) | 滑动平均平滑,滤波系数等于窗口大小的倒数 |
lowess | 局部加权线性回归平滑,使用加权线性最小二乘法和一级多项式模型进行局部回归 |
loess | 局部加权二次回归平滑,使用加权线性最小二乘法和二次多项式模型进行局部回归 |
sgolay | 多项式平滑,Savitzky-Golay滤波器。 广义移动平均,其滤波器系数由未加权的线性最小二乘回归和指定度数的多项式模型确定(默认值为2)。 该方法可以接受不一致的预测变量数据。 |
rlowess | 鲁棒局部加权线性回归平滑,“ lowess”的加强版,可为回归中的异常值分配较低的权重。 该方法将零权重分配给六个均值绝对偏差之外的数据。 |
rloess | 鲁棒局部加权二次回归平滑,“loess”的加强版,在回归中将较低的权重分配给离群值。 该方法将零权重分配给六个均值绝对偏差之外的数据。 |
x = (0:0.1:15)';
y = sin(x) + 0.5*(rand(size(x))-0.5);
y([90,110]) = 3;
yy1 = smooth(x,y,0.1,'loess');
yy2 = smooth(x,y,0.1,'rloess');
subplot(2,1,1)
plot(x,y,'b.',x,yy1,'r-')
set(gca,'YLim',[-1.5 3.5])
legend('Original data','Smoothed data using ''loess''',...
'Location','NW')
subplot(2,1,2)
plot(x,y,'b.',x,yy2,'r-')
set(gca,'YLim',[-1.5 3.5])
legend('Original data','Smoothed data using ''rloess''',...
'Location','NW')
可以看出rloess效果要好一些,一般情况下,可以无脑使用:
b=smooth(a,'rloess');
b=smooth(a,'rlowess');
matlab自带的平滑算法会改变原始数据,但是有时候笔者只想将一组数据中的离群数给剔除,不改变其他原始数据,所以笔者编写了个函数,如下所示:
不考虑前后向量长度的话,一句话就搞定:
c=b(abs(b-mean(b))<= 3*std(b));
要保持前后向量长度不变的话:
% rm data which > 3*std once
function data=rmNo(mat)
m=nanmean(mat);
s=std(mat);
dat=smooth(mat,'rlowess');
ind=find(abs(mat-m)>3*s);
data=mat;
for i=ind
data(i)=dat(i);
end
end
比如现在我有一组数据,经历过一次消噪,噪声水平设置标准为大于3倍标准差。消噪之后的数据标准差发生了变化,所以之前有可能不是噪点的数据也会变成噪点。我想把这些噪点给消了,那么就需要一个迭代过程:
% rm data which > 3*std iterate
function data=rmNo1(mat)
count=0;
mat0=mat;
mat1=mat0;
while true
m=nanmean(mat0);
s=std(mat0);
dat=smooth(mat0,'rlowess');
ind=find(abs(mat0-m)>3*s);
for i=ind
mat1(i)=dat(i);
end
count=count+1;mat0=mat1;
if count>5 || length(ind)==0
break;
end
end
data=mat1;
end
迭代终止条件为:迭代超过5次或前后两次迭代结果相同。