Savitzky-Golay 滤波器

python 数据、曲线平滑处理——Savitzky-Golay 滤波器

Savitzky-Golay 滤波器
关于Savitzky-Golay 滤波器,可以在scipy里看到关于这个函数的定义:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.savgol_filter.html

Savitzky-Golay平滑滤波是光谱预处理中常用滤波方法,它的核心思想是对一定长度窗口内的数据点进行k阶多项式拟合,从而得到拟合后的结果。对它进行离散化处理后后,S-G 滤波其实是一种移动窗口的加权平均算法,但是其加权系数不是简单的常数窗口,而是通过在滑动窗口内对给定高阶多项式的最小二乘拟合得出。

Savitzky-Golay平滑滤波被广泛地运用于数据流平滑除噪,是一种在时域内基于局域多项式最小二乘法拟合的滤波方法。这种滤波器最大的特点在于在滤除噪声的同时可以确保信号的形状、宽度不变。

使用平滑滤波器对信号滤波时,实际上是拟合了信号中的低频成分,而将高频成分平滑出去了。如果噪声在高频端,那么滤波的结果就是去除了噪声,反之,若噪声在低频段,那么滤波的结果就是留下了噪声。

总之,平滑滤波是光谱分析中常用的预处理方法之一。用Savitzky-Golay方法进行平滑滤波,可以提高光谱的平滑性,并降低噪音的干扰。S-G平滑滤波的效果,随着选取窗宽不同而不同,可以满足多种不同场合的需求。

代码实现
1.python中Savitzky-Golay滤波器调用如下:

tmp_smooth = scipy.signal.savgol_filter(tmp,53,3)

2.python中Savitzky-Golay滤波器调用如下:

y_smooth = scipy.signal.savgol_filter(y,53,3)  
# 亦或
y_smooth2 = savgol_filter(y, 99, 1, mode= 'nearest')

# 备注:
y:代表曲线点坐标(x,y)中的y值数组
window_length:窗口长度,该值需为正奇整数。例如:此处取值53
k值:polyorder为对窗口内的数据点进行k阶多项式拟合,k的值需要小于window_length。例如:此处取值3
mode:确定了要应用滤波器的填充信号的扩展类型。(This determines the type of extension to use for the padded signal to which t

调参规律:

现在看一下window_length和k这两个值对曲线的影响。

(1)window_length对曲线的平滑作用: window_length的值越小,曲线越贴近真实曲线;window_length值越大,平滑效果越厉害(备注:该值必须为正奇整数)。

(2)k值对曲线的平滑作用: k值越大,曲线越贴近真实曲线;k值越小,曲线平滑越厉害。另外,当k值较大时,受窗口长度限制,拟合会出现问题,高频曲线会变成直线。
典型范例:

# 用于生成问题描述中示例曲线的代码如下:
import numpy as np

Size = 100
x = np.linspace(1, Size,Size)

data = np.random.randint(1, Size, Size)
print(data)

array([33, 19,  2, 56, 11, 38,  3, 45,  4, 20, 59,  3, 71, 94, 85, 23, 93,
       65, 23, 99, 38, 43, 41, 96, 46, 56, 79,  1, 38, 90, 97, 88,  2, 72,
       25, 51, 70, 42,  4, 86, 26, 44, 40, 49,  5, 37, 10, 99, 40, 88, 34,
       99, 26,  6, 20, 37, 22, 88, 13, 68, 54, 95, 15,  4, 58, 20, 51, 89,
       81,  1, 41, 21, 17, 52, 84, 46, 76, 44, 90, 72, 96, 32, 12, 50, 81,
       64, 67, 99, 42, 35, 70, 79, 21, 51, 56, 10, 23, 21, 25, 64])

# 可视化图线
plt.plot(x, data)

# 使用Savitzky-Golay 滤波器后得到平滑图线
from scipy.signal import savgol_filter

y = savgol_filter(data, 5, 3, mode= 'nearest')
# 可视化图线
plt.plot(x, y, 'b', label = 'savgol')
posted on 2021-07-03 19:29  诺诺子  阅读(5039)  评论(0编辑  收藏  举报