第一阶段的方法是根据单位时间内的加速度绝对值差值来判断震颤程度,存在很多问题。因此设想采用更加高级的算法来加以改进。

这部分的主要工作有:  1 学习数字信号处理的滤波算法,重点学习python下使用FIR滤波算法

                                       2 利用python的数据分析工具对传感器信号加以分析,利用好更多的信号数据


FIR滤波器很简单,它实际上是一个全零点模型(MA滑动平均模型),滤波器系数只包含滑动平均的B,而自回归的A=1。滤波过程就是X和B的卷积,再联系滤波器的原理,容易知道,FIR滤波器的系数B就是滤波器的冲激响应h。

因此它的设计就简单了,只要设定滤波器的频率响应H,进行ifft后就得到冲激响应h,把h直接作为滤波器系数B对原信号滤波即可。



经查找,python下可以通过scipy.signal这个科学计算模块实现对信号的处理滤波。python在科学计算领域有三个非常受欢迎库,numpy、SciPy、matplotlib。numpy是一个高性能的多维数组的计算库,SciPy是构建在numpy的基础之上的,它提供了许多的操作numpy的数组的函数。SciPy是一款方便、易于使用、专为科学和工程设计的python工具包,它包括了统计、优化、整合以及线性代数模块、傅里叶变换、信号和图像图例,常微分方差的求解等。
 

基础知识:

傅立叶变换的形象讲解:https://zhuanlan.zhihu.com/p/19763358

图片说明(摘自上面链接):

numpy教程:快速傅里叶变换模块numpy.fft  https://blog.csdn.net/pipisorry/article/details/51050297

下面主要是对官方文档的复现与翻译:

巴特沃斯滤波器https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.butter.html

scipy.signal.butterNWnbtype ='低'模拟=假输出='ba'fs =无

参数:

: int

过滤器的顺序。

Wn : array_like

给出临界频率的标量或长度为2的序列。对于巴特沃斯滤波器,这是增益下降到通带的1 / sqrt(2)的点(“-3 dB点”)。

对于数字滤波器,Wnfs的单位相同。默认情况下, fs为2个半周/采样,因此这些从0到1归一化,其中1是奈奎斯特频率。(因此,Wn处于半周期/样本中。)

对于模拟滤波器,Wn是角频率(例如rad / s)。

btype : {' lowpass ',' highpass ','bandpass','bandstop'},可选

过滤器的类型。默认为'低通'。

模拟 : bool,可选

如果为True,则返回模拟滤波器,否则返回数字滤波器。

输出 : {'ba','zpk','sos'},可选

输出类型:分子/分母('ba'),极点零('zpk')或二阶段('sos')。默认为'ba'。

fs : float,可选

数字系统的采样频率。

版本1.2.0中的新功能。

返回:

b,a : ndarray,ndarray

分子(b)和分母(a)IIR滤波器的多项式。只有返回output='ba'

z,p,k : ndarray,ndarray,float

IIR滤波器传递函数的零点,极点和系统增益。只有返回output='zpk'

sos : ndarray

IIR滤波器的二阶截面表示。只有返回output=='sos'

例子:左图高通,右图低通

#设计模拟滤波器并绘制其频率响应,显示关键点:
from scipy import signal
import matplotlib.pyplot as plt

b, a = signal.butter(4, 100, 'low', analog=True)
w, h = signal.freqs(b, a)
plt.semilogx(w, 20 * np.log10(abs(h)))
plt.title('Butterworth filter frequency response')
plt.xlabel('Frequency [radians / second]')
plt.ylabel('Amplitude [dB]')
plt.margins(0, 0.1)
plt.grid(which='both', axis='both')
plt.axvline(100, color='green') # cutoff frequency
plt.show()

#产生由10 Hz和20 Hz组成的信号,以1 kHz采样
t = np.linspace(0, 1, 1000, False)  # 1 second
sig = np.sin(2*np.pi*10*t) + np.sin(2*np.pi*20*t)
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.plot(t, sig,color='red')
ax1.set_title('10 Hz and 20 Hz sinusoids')
ax1.axis([0, 1, -2, 2])

#设计15 Hz的数字高通滤波器以消除10 Hz音调,并将其应用于信号。(建议在过滤时使用二阶段格式,以避免传递函数(ba)格式的数值错误):
sos = signal.butter(10, 15, 'hp', fs=1000, output='sos')
filtered = signal.sosfilt(sos, sig)
ax2.plot(t, filtered,color='green')
ax2.set_title('After 15 Hz high-pass filter')
ax2.axis([0, 1, -2, 2])
ax2.set_xlabel('Time [seconds]')
plt.tight_layout()
plt.show()

 

 使用IIR或FIR滤波器沿一维过滤数据:https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lfilter.html

scipy.signal.lfilter 

scipy.signal.lfilterbax轴= -1zi =无

使用IIR或FIR滤波器沿一维过滤数据。

使用数字滤波器过滤数据序列x。这适用于许多基本数据类型(包括对象类型)。滤波器是标准差分方程的直接形式II转置实现(见注释)。

参数:

: array_like

1-D序列中的分子系数向量。

: array_like

1-D序列中的分母系数向量。如果a[0] 不是1,则ab都归一化a[0]

: array_like

N维输入数组。

axis : int,可选

输入数据阵列的轴,沿着该轴应用线性滤波器。过滤器沿该轴应用于每个子阵列。默认值为-1。

zi : array_like,可选

过滤器延迟的初始条件。它是长度的向量(或用于N维输入的向量的数组) 。如果zi为None或未给出,则假定初始休息。有关更多信息,请参阅max(len(a), len(b)) - 1lfiltic

返回:

: 数组

数字滤波器的输出。

zf : array,可选

如果zi为None,则不返回,否则,zf保存最终的滤波器延迟值。

例子:右图为只有filt:

from scipy import signal
import matplotlib.pyplot as plt
import numpy as np

#生成要过滤的噪声信号
t = np.linspace(-1, 1, 201)
x = (np.sin(2*np.pi*0.75*t*(1-t) + 2.1) +
     0.1*np.sin(2*np.pi*1.25*t + 1) +
     0.18*np.cos(2*np.pi*3.85*t))
xn = x + np.random.randn(len(t)) * 0.08

#创建order3低通道butterworth过滤器:
b, a = signal.butter(3, 0.05)
#将过滤器应用于xn。使用lfilter_zi选择过滤器的初始条件:
#zi = signal.lfilter_zi(b, a)
#z, _ = signal.lfilter(b, a, xn, zi=zi*xn[0])
#再次应用过滤器,以与filtfilt相同的顺序过滤结果:
#z2, _ = signal.lfilter(b, a, z, zi=zi*z[0])
#使用filtfilt应用过滤器:
y = signal.filtfilt(b, a, xn)
#绘制原始信号和各种过滤版本:
plt.figure
plt.plot(t, xn, 'b', alpha=0.75)
plt.plot(t, z, 'r--', t, z2, 'r', t, y, 'k')
plt.legend(('noisy signal', 'lfilter, once', 'lfilter, twice',
            'filtfilt'), loc='best')
plt.grid(True)
plt.show()

lfilter还是filtfilt的区别:https://dsp.stackexchange.com/questions/19084/applying-filter-in-scipy-signal-use-lfilter-or-filtfilt

  • filtfilt是零相位滤波,在滤波时不会移位信号。由于在所有频率下相位均为零,因此它也是线性相位。及时过滤需要您预测未来,因此不能在“在线”实际应用中使用,仅用于信号记录的离线处理。

  • lfilter是一种因果时间过滤,类似于现实生活中的电子过滤器。它不能是零相位。它可以是线性相位(对称FIR),但通常不是。通常它会在不同的频率上增加不同的延迟量。

一个例子和图像应该使它显而易见。虽然滤波器的频率响应幅度相同(左上角和右上角),但零相位低通与原始信号对齐,只是没有高频内容,而最小相位滤波以因果方式延迟信号:

from __future__ import division, print_function
import numpy as np
from numpy.random import randn
from numpy.fft import rfft
from scipy import signal
import matplotlib.pyplot as plt

b, a = signal.butter(4, 0.03, analog=False)

# Show that frequency response is the same
impulse = np.zeros(1000)
impulse[500] = 1

# Applies filter forward and backward in time
imp_ff = signal.filtfilt(b, a, impulse)

# Applies filter forward in time twice (for same frequency response)
imp_lf = signal.lfilter(b, a, signal.lfilter(b, a, impulse))

plt.subplot(2, 2, 1)
plt.semilogx(20*np.log10(np.abs(rfft(imp_lf))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('lfilter')

plt.subplot(2, 2, 2)
plt.semilogx(20*np.log10(np.abs(rfft(imp_ff))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('filtfilt')

sig = np.cumsum(randn(800))  # Brownian noise
sig_ff = signal.filtfilt(b, a, sig)
sig_lf = signal.lfilter(b, a, signal.lfilter(b, a, sig))
plt.subplot(2, 1, 2)
plt.plot(sig, color='silver', label='Original')
plt.plot(sig_ff, color='#3465a4', label='filtfilt')
plt.plot(sig_lf, color='#cc0000', label='lfilter')
plt.grid(True, which='both')
plt.legend(loc="best")

scipy.signal.filtfilt模块:https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.filtfilt.html#scipy.signal.filtfilt

scipy.signal.filtfiltbaxaxis = -1padtype ='odd'padlen = Nonemethod ='pad'irlen = None [source]

向数字滤波器前后应用信号。

此功能应用线性数字滤波器两次,一次向前,一次向后。组合滤波器的零相位和滤波器顺序是原始滤波器的两倍。

该功能提供了处理信号边缘的选项。

参数:

: (N,)array_like

滤波器的分子系数向量。

: (N,)array_like

滤波器的分母系数向量。如果a[0] 不是1,则ab都归一化a[0]

: array_like

要过滤的数据数组。

axis : int,可选

应用滤波器的x轴。默认值为-1。

padtype : str或None,可选

必须是'奇数','偶数','常数'或无。这决定了用于应用滤波器的填充信号的扩展类型。如果padtype为None,则不使用填充。默认值为“奇数”。

padlen : int或None,可选

在应用过滤器之前在轴的两端 延伸x的元素数。该值必须小于 。 意味着没有填充。默认值为。x.shape[axis] - 1padlen=03 * max(len(a), len(b))

方法 : str,可选

确定处理信号边缘的方法,“pad”或“gust”。当方法是“pad”时,信号被填充; 填充的类型由padtypepadlen决定,irlen 被忽略。当方法是“阵风”时,使用Gustafsson的方法,并忽略padtypepadlen

irlen : int或None,可选

方法是“阵风”时,irlen指定滤波器的脉冲响应的长度。如果irlen为None,则不会忽略脉冲响应的任何部分。对于长信号,指定 irlen可以显着提高滤波器的性能。

返回:

: ndarray

滤波后的输出与x的形状相同。

from scipy import signal
import matplotlib.pyplot as plt
#首先,我们创建一秒信号,它是两个纯正弦波的总和,频率为5 Hz和250 Hz,采样频率为2000 Hz。
t = np.linspace(0, 1.0, 2001)
xlow = np.sin(2 * np.pi * 5 * t)
xhigh = np.sin(2 * np.pi * 250 * t)
x = xlow + xhigh
#现在创建的0.125倍的奈奎斯特频率,或125赫兹的截止低通巴特沃斯滤波器,并将其应用到x与filtfilt。结果应该是近似的xlow,没有相移。
b, a = signal.butter(8, 0.125)
y = signal.filtfilt(b, a, x, padlen=150)
np.abs(y - xlow).max()
#我们得到了一个相当干净的结果,因为奇数扩展是精确的,并且在适度长的填充时,滤波器的瞬态已经在实际数据到达时消散。通常,边缘处的瞬态效应是不可避免的。

#以下示例演示了该选项method="gust"。

#首先,创建一个过滤器。

b, a = signal.ellip(4, 0.01, 120, 0.125)  # Filter to be applied.
np.random.seed(123456)
#sig是要过滤的随机输入信号
n = 60
sig = np.random.randn(n)**3 + 3*np.random.randn(n).cumsum()

fgust = signal.filtfilt(b, a, sig, method="gust")
fpad = signal.filtfilt(b, a, sig, padlen=50)
plt.plot(sig, 'k-', label='input')
plt.plot(fgust, 'b-', linewidth=4, label='gust')
plt.plot(fpad, 'c-', linewidth=1.5, label='pad')
plt.legend(loc='best')
plt.show()

#该irlen参数可以用来改善古斯塔夫松的方法的性能。

#估计滤波器的脉冲响应长度。
z, p, k = signal.tf2zpk(b, a)
eps = 1e-9
r = np.max(np.abs(p))
approx_impulse_len = int(np.ceil(np.log(eps) / np.log(r)))
approx_impulse_len
#使用和不使用irlen 参数将滤波器应用于更长的信号。y1和y2之间的差异很小。对于长信号,使用irlen可显着提高性能。
x = np.random.randn(5000)
y1 = signal.filtfilt(b, a, x, method='gust')
y2 = signal.filtfilt(b, a, x, method='gust', irlen=approx_impulse_len)
print(np.max(np.abs(y1 - y2)))

 

参考资料:

SciPy完整的教程:https://docs.scipy.org/doc/scipy/reference/index.html

numpy的使用:https://blog.csdn.net/cxmscb/article/details/54583415

SciPy上手: https://blog.csdn.net/q583501947/article/details/76735870

利用Python scipy.signal.filtfilt() 实现信号滤波:https://blog.csdn.net/weixin_37996604/article/details/82864680

python实现低通滤波器:https://blog.csdn.net/kkkxiong1/article/details/84941992

  https://blog.csdn.net/daiyinger/article/details/48289587

python实现高通滤波器:https://blog.csdn.net/thoughts_storms/article/details/32318921

python实现带通滤波器:https://blog.csdn.net/weixin_39739342/article/details/84948308

python实现数字滤波器FIR,IIR:https://blog.csdn.net/qq_21970857/article/details/46685923

数据分析scipy常用方法 :https://www.cnblogs.com/why957/p/9308916.html