Matlab 中的低通滤波器/Python 用于去除运动噪声

Low-pass filter in Matlab / Python for removing movement noise

我正在随时间记录一个信号(皮肤电导),即我有一个时间序列。不幸的是,信号会受到运动的影响。在用户指南中,我现在阅读了以下内容:

A low pass filter should be applied to the data to remove high frequency noise which can be attributed to movement artifact and other noise components. A cutoff frequency of as low as 1 - 5 Hz can be used without affecting the data of interest due to the slowly varying nature of GSR responses.

如何在 Matlab 或 Python 中将具有截止频率的低通滤波器应用于我的时间序列?

在 Matlab 中,最简单的方法可能是使用 butter 命令(查找数字滤波器的系数),然后使用 filter 命令:https://www.mathworks.com/help/signal/ref/butter.html

butter(n, Wn) 将您要设计的滤波器的阶数(阶数越高,滤波器的行为越理想)和归一化频率 Wn 作为参数。通常,为了正确设计滤波器,您需要知道原始数据的采样频率 (Hz)。

由于您只需要去除基线低频噪声,因此请使用高通滤波器。

示例:

rawdata=rand(1000,1); %randomly generated data

fs=1000; %frequency at which your data was sampled, assuming 1000 Hz here

fc=5; %cut-off frequency (you mentioned 1-5 Hz in your question so I used 5)

Wn= fc/fs; % Normalized frequency

filt_order=8; % arbitrarily chose an 8th order filter

[b,a]=butter(filt_order,Wn, 'high'); 
% butter creates the coefficients of your digital filter
% the optional parameter 'high' specifies a high-pass filter

filtered_data=filter(b,a,rawdata);

设计过滤器可能是一个相当复杂的过程,没有人能给您正确的答案。过滤器设计是一种从经验中获得的技能,但在获得这种经验之前,对过滤器的基础知识有充分的了解是很重要的。您至少应该熟悉 FIRIIR 过滤器(优缺点),low/high/band-pass 过滤器是什么以及采样的基础知识.

在你的情况下,我假设你已经将时间序列存储在内存中的某个地方,所以你不需要在测量时过滤数据。在这种情况下,我会选择一个 FIR 滤波器,并使用 Matlab 的函数 filtfilt 在正向和反向方向上过滤数据,因此您的过滤信号将没有相位失真。这种类型的过滤只有在 post-processing 中才有可能,当数据已经收集时,因为这是 非因果 过滤,您知道数据点的值之前和之后,某个数据点。而如果您在记录时进行过滤,您将不知道未来的价值。

滤波器阶数截止频率通常是select迭代过程。要记住的一件事是,通过增加滤波器阶数,您可以提高滤波器的性能(更陡的滚降斜率),这会带来更高的计算要求。

下面是一个简短的示例,其中的信号由两个频率分别为 3 Hz 和 25 Hz 的正弦波组成。滤波的目的是设计一个低通滤波器来去除 25 Hz 的频率分量。我想展示两种不同滤波器的性能,一种是 45 阶,另一种是 70 阶。

% sampling frequency [Hz]
Fs = 1000;
% sampling period [s]
Ts = 1/Fs;

% time vector [s]
t = 0:Ts:3;

% Signal A frequency [Hz] and amplitude
amplitude_A = 5;
f_A = 3;
sig_A = amplitude_A.*sin(2*pi*f_A.*t);

% Signal A frequency [Hz] and amplitude
amplitude_B = 2;
f_B = 25;
sig_B = amplitude_B.*sin(2*pi*f_B.*t);

% sum of the two signals
X = sig_A + sig_B;
plot(t,X,'LineWidth',2);
hold on;
grid on;

% Low pass filter at ~15Hz
% normalized frequency wn
wn = 15/Fs;
b_1 = fir1(45,wn);
b_2 = fir1(70,wn);

% filtered signal
a = 1; % fir filter does not have poles (transfer function denominator = 1)
Y_1 = filtfilt(b_1,a,X);
plot(t,Y_1,'-r','LineWidth',2);
Y_2 = filtfilt(b_2,a,X);
plot(t,Y_2,'-k','LineWidth',2);
xlabel('Time (s)');
ylabel('Amplitude (V)');
legend('original signal','filtered order 45',...
    'filtered order 70');

这是输出:

从图中可以看出,低阶滤波器没有完全滤除高频分量,但两个滤波器都衰减了信号的幅度。可以通过调整截止频率和滤波器阶数来改善输出。这也是一个简单的过滤示例,如果两个分量的频率更接近,则获得好的结果将更具挑战性。

对于您的情况,我假设皮肤电导 (GSR) 的频率(低于 1 Hz)比运动引起的伪影低得多,因此运动是您想要消除的高频成分。我认为您应该仔细观察原始信号图并尝试识别运动引起的变化,然后过滤信号并检查运动分量是否减少,不断更改过滤器参数,直到您对结果满意为止。此外(如果需要)您应该考虑获取信号的频谱(执行 FFT),这可以帮助您 select 截止频率。如果推荐的截止频率在 1-5 赫兹之间,我会从这个开始,看看这个范围内的频率是否能做到。

几乎不可能一口气解释过滤 post,但为了让您入门,最好了解一些基础知识。请记住,在过滤器设计中通常没有完美的解决方案,因为每个过滤器都会以某种方式扭曲原始数据。