关于ECG信号处理的MATLAB代码的逐行解读

作为即将要入门ECG信号处理的小小白,即使拿到大佬们的代码并且跑通也还是不懂每一句代码的含义及其背后的原理,这里借助chatgpt的解释把它备份到这里,一来是作为自己的笔记本用时方便查阅,二来帮助像我一样懵懂的萌新省去查阅繁杂资料的麻烦,本文旨在做笔记所以未刻意排版做美观处理,如有错误,欢迎指正
参考文章见:基于MATLAB实现ECG心电信号处理
ps:每句前面序号代表代码所在行数

  1. fp 是通带截止频率(通带结束点),表示在滤波器的通带中保留信号的频率范围
    fs 是阻带截止频率(阻带开始点),表示在滤波器的阻带中抑制信号的频率范围

  2. rp 是通带衰减,表示在通带中滤波器允许的最大衰减
    rs 是阻带衰减,表示在阻带中滤波器要达到的最小衰减

  3. 将角频率转换为弧度/秒。角频率(wp和ws)是频率的一个标准表示,以弧度为单位。这里使用了 2 * pi 的乘法因子

  4. buttord 函数用于计算巴特沃斯滤波器的最佳阶数(n)和截止频率(wn)。它的输入参数是通带角频率、阻带角频率、通带衰减和阻带衰减,以及滤波器类型(这里是 ‘s’ 表示模拟滤波器)。n 是计算得到的最佳滤波器阶数。wn 是对应于通带截止频率的模拟滤波器的截止频率

在MATLAB中,'butter’函数的设计参数中有一个参数用于指定滤波器的类型,即’s’表示模拟滤波器,而’d’表示数字滤波器。

  • 's' 表示使用模拟(analog)滤波器设计方法。模拟滤波器设计通常是在频率域中对连续时间系统进行设计,不考虑离散化和采样。设计完成后可以使用freqs等函数来查看模拟滤波器的频率响应。

  • 'd' 表示使用数字(digital)滤波器设计方法。数字滤波器设计考虑了离散化和采样的影响,通常更适用于数字信号处理应用。设计完成后可以使用freqz等函数来查看数字滤波器的频率响应。

在上面的代码中,'s' 用于模拟滤波器的设计,因此 butter 函数设计的是一个连续时间(模拟)滤波器。在设计完成后,如果你希望在数字系统中应用这个滤波器,你可能需要将其离散化(数字化)。这可以通过使用c2d函数进行。例如,在这个例子中,c2d函数将模拟滤波器的系数转换为数字滤波器的系数,其中fsamp是离散化时的采样频率。

[b, a] = butter(n, wn, 'low', 's');  % 模拟滤波器设计
[b_digital, a_digital] = c2d(b, a, fsamp);  % 离散化为数字滤波器
  1. 在MATLAB的Signal Processing Toolbox中,buttap 函数用于设计巴特沃斯模拟滤波器的极点-零点-增益表示法参数。巴特沃斯滤波器是一种特殊类型的滤波器,通常被设计为低通滤波器。
[z,P,k]=buttap(n);

buttap(n) 中,n 是滤波器的阶数,它决定了滤波器的复杂性和截止频率的控制。阶数越高,滤波器越复杂,截止频率的控制越尖锐。

巴特沃斯滤波器的特点之一是其极点分布。在 buttap 函数返回的极点-零点-增益表示法中,z 是滤波器的极点,P 是滤波器的零点,k 是增益。对于低通巴特沃斯滤波器,极点主要分布在左半平面,而零点主要分布在原点。这种特殊的极点分布使得低通巴特沃斯滤波器在通带内有一个相对平坦的频率响应。

因此,通过 buttap(n) 函数设计的极点-零点-增益表示法通常对应于低通滤波器。这并不是唯一的设计低通滤波器的方法,但在巴特沃斯滤波器中,它是一种常见的实现方式。

  1. 在这行代码中,zp2tf 函数用于将极点-零点-增益(ZPK)表示法转换为传递函数(TF)表示法。在这个特定的情境下,z 是极点,P 是零点,k 是增益。
[bp, ap] = zp2tf(z, P, k);
  • z 是模拟滤波器的极点。
  • P 是模拟滤波器的零点。
  • k 是增益。

bp 是传递函数的分子系数,ap 是传递函数的分母系数。

这里的 bpap 表示的是传递函数:

在这里插入图片描述

其中,( n ) 是滤波器的阶数。

在这个上下文中,z, P, 和 k 是通过 buttap 函数得到的巴特沃斯滤波器的极点-零点-增益表示法的参数。通过 zp2tf 将这些参数转换为传递函数形式,从而获得模拟滤波器的传递函数。

  1. 在这一行代码中,lp2lp 函数被用于将一个低通滤波器(Low Pass,LP)的传递函数转换为另一个低通滤波器。这是通过指定新的截止频率 wp 来实现的。
[bs, as] = lp2lp(bp, ap, wp);
  • bpap 是原始低通滤波器的传递函数分子和分母系数。
  • wp 是新的低通滤波器的截止频率。

bsas 是转换后的新低通滤波器的传递函数分子和分母系数。

在这里,通过 lp2lp 函数,原始低通滤波器的传递函数 (H_a(s)) 被转换为新低通滤波器的传递函数 (H_s(s))。这种转换通常是通过调整原始滤波器的频率响应来实现的,确保新的滤波器具有所需的截止频率 wp。这样做的目的是确保滤波器在新的截止频率下仍然具有适当的性能,以滤除肌电信号。例如,根据具体的应用需求,调整截止频率以适应不同的信号特性。

  1. 在这一行代码中,freqs 函数用于计算数字滤波器的频率响应。这个频率响应包括复数值,其中 hs 表示频率响应,ws 表示对应的频率。
[hs, ws] = freqs(bs, as);
  • bsas 是数字滤波器的传递函数的分子和分母系数。
  • hs 是数字滤波器在频率域上的响应。
  • ws 是对应于 hs 中每个频率点的频率。

hsws 的关系表示了数字滤波器在不同频率下的增益或衰减。

此步骤通常用于了解数字滤波器在频域中的性能,以便进一步分析其对输入信号的影响。可以通过绘制频率响应图来更直观地理解数字滤波器对信号的影响。

  1. 在这一行代码中,bilinear 函数用于对数字滤波器进行双线性变换。这个过程是将连续时间(模拟)滤波器的传递函数转换为离散时间(数字)滤波器的传递函数。
[bz, az] = bilinear(bs, as, Fs);
  • bsas 是连续时间数字滤波器的传递函数的分子和分母系数。
  • Fs 是数字滤波器的采样频率。
  • bzaz 是通过双线性变换得到的数字滤波器的传递函数的分子和分母系数。

通过这个步骤,模拟滤波器被离散化以适应数字信号的处理。这是因为在实际应用中,信号通常以数字形式进行采样和处理。使用双线性变换可以将连续时间滤波器转换为数字滤波器,以便对离散时间信号进行滤波。

  1. 在这段代码中,进行了离散傅立叶变换(FFT)以获取信号的频谱信息。以下是对代码的解释:
N = 512;                      % FFT的点数
n = 0:N-1;                    % 时间序列
mf = fft(M(:, 1), N);         % 进行频谱变换(傅里叶变换)
mag = abs(mf);                % 计算频谱的幅度
f = (0:length(mf)-1) * Fs / length(mf);  % 计算频率轴
  • N = 512 设置了FFT的点数,这决定了频谱分析的精度。
  • n = 0:N-1 创建了时间序列,用于表示信号的时间轴。
  • fft(M(:, 1), N) 对信号 M(:, 1) 进行离散傅立叶变换,得到频谱信息。结果存储在 mf 中。
  • abs(mf) 计算了频谱的幅度,即信号在频域中的强度。
  • f = (0:length(mf)-1) * Fs / length(mf) 计算了频率轴,其中 Fs 是采样频率。这个轴表示FFT输出中每个频率点对应的实际频率。

通过这段代码,你可以得到信号的频谱信息,并可以使用 magf 进行进一步的频谱分析和可视化。

  1. 在这段代码中,进行了心电信号的功率谱密度估计,并通过图形表示。以下是对代码的解释:
wn = M(:, 1);                 % 从信号中提取一列作为处理的信号
P = 10 * log10(abs(fft(wn).^2)/N);  % 计算信号的功率谱密度估计
f = (0:length(P)-1) / length(P);   % 计算频率轴

figure
plot(f, P);                   % 绘制功率谱密度曲线
grid
xlabel('归一化频率');
ylabel('功率(dB)');
title('心电信号的功率谱');
  • wn = M(:, 1) 从原始信号中提取一列,作为需要处理的信号。
  • fft(wn) 对提取的信号进行傅里叶变换,得到频域表示。
  • abs(fft(wn).^2)/N 计算频域表示的幅度的平方,并除以FFT的点数,得到功率谱密度估计。
  • 10 * log10(...) 将功率转换为分贝(dB)单位,以便更容易观察。
  • f = (0:length(P)-1) / length(P) 计算频率轴。
  • plot(f, P) 绘制功率谱密度曲线。
  • grid 添加网格线以提高可视化效果。
  • xlabel('归一化频率')ylabel('功率(dB)') 添加轴标签。
  • title('心电信号的功率谱') 添加图形标题。

通过这段代码,你可以可视化心电信号的功率谱密度估计,以更好地了解信号在频域上的特性。

  1. 这行代码计算了信号 wn 的功率谱密度估计:
P = 10 * log10(abs(fft(wn).^2)/N);
  • fft(wn):对信号 wn 进行离散傅里叶变换,得到频域表示。这里使用 fft 函数。

  • abs(fft(wn).^2):计算频域表示的幅度的平方。这是为了获取功率谱的估计,因为功率是幅度的平方。

  • /N:将结果除以FFT的点数,这是为了得到归一化的功率谱密度。

  • 10 * log10(...):将结果取对数并乘以10,以转换为分贝(dB)单位。这样做是为了更方便地表示信号的强度。

综合起来,这行代码计算了信号在频域中每个频率分量的功率谱密度估计,并将结果以分贝为单位表示。功率谱密度估计用于了解信号在频域中不同频率上的功率分布,提供了一种分析信号频谱特性的方法。

  1. 这段代码设计了一个带陷滤波器,其目的是抑制特定频率,即50 Hz的工频。以下是对代码的逐行解释:
Me = 100;               % 滤波器阶数
L = 100;                % 窗口长度
beta = 100;             % 衰减系数
Fs = 1500;              % 采样频率
wc1 = 49/Fs*pi;         % 高通滤波器截止频率,对应51Hz
wc2 = 51/Fs*pi;         % 低通滤波器截止频率,对应49Hz
h = ideal_lp(0.132*pi, Me) - ideal_lp(wc1, Me) + ideal_lp(wc2, Me); % 陷波器冲激响应
w = kaiser(L, beta);
y = h .* rot90(w);      % 50Hz陷波器冲激响应序列
m2 = filter(y, 1, m);
  • Me 是滤波器的阶数,决定了滤波器的复杂度。
  • L 是窗口长度,用于设计Kaiser窗口。
  • beta 是Kaiser窗口的衰减系数,控制窗口的形状。
  • Fs 是采样频率。
  • wc1wc2 是高通滤波器和低通滤波器的截止频率,分别对应于51 Hz和49 Hz。这两个截止频率一起定义了带陷滤波器的通带范围,排除了50 Hz的工频。wc1 和 wc2 并不直接对应于高通或低通滤波器的截止频率,而是用于引入零点的频率。这两个零点的存在是为了在设计的带陷滤波器中形成两个抑制带,使其在50 Hz的电力线频率附近产生一个“带阻”效果。
  • ideal_lp 函数是一个理想低通滤波器的生成函数。在这里,它被用于生成一个理想的带陷滤波器的冲激响应。
  • kaiser 函数生成一个Kaiser窗口,用于加权滤波器的冲激响应。
  • rot90(w) 将Kaiser窗口旋转,以使其与滤波器的冲激响应对齐。
  • h .* rot90(w) 是带陷滤波器的冲激响应,通过Kaiser窗口进行加权。
  • filter(y, 1, m) 使用带陷滤波器对输入信号 m 进行滤波。这将抑制50 Hz的工频成分,而保留其他频率的信号成分。
  1. 这段代码使用了 MATLAB 中的椭圆滤波器设计函数 ellipordellip,并应用该椭圆滤波器对信号 m2 进行滤波。

让我为你逐步解释每一行:

  1. Wp=1.4*2/Fs;:设置通带截止频率,1.4*2 是希望保留的信号频率,Fs 是采样频率。这个值是以弧度/秒为单位的。

  2. Ws=0.6*2/Fs;:设置阻带截止频率,0.6*2 是希望抑制的频率。同样,这个值是以弧度/秒为单位的。

  3. devel=0.005;:设置通带纹波。通带纹波是指在通带内允许的最大波动。

  4. Rp=20*log10((1+devel)/(1-devel));:根据通带纹波计算通带纹波系数 Rp,并将其转换为分贝。

  5. Rs=20;:设置阻带衰减,以分贝为单位。

  6. [N Wn]=ellipord(Wp,Ws,Rp,Rs,'s');:使用 ellipord 函数计算椭圆滤波器的阶次 N 和截止频率 Wn

  7. [b a]=ellip(N,Rp,Rs,Wn,'high');:使用 ellip 函数设计椭圆滤波器的系数 b(分子系数)和 a(分母系数)。

  8. [hw,w]=freqz(b,a,512);:计算椭圆滤波器的频率响应。

  9. result = filter(b,a,m2);:使用设计好的椭圆滤波器对信号 m2 进行滤波。

这段代码的目的是设计一个高通椭圆滤波器,以滤除低频成分。椭圆滤波器是一种优秀的滤波器,它可以在给定通带纹波和阻带衰减的条件下实现最小阶次。在这里,设计的滤波器是高通的,以保留高于 Wp(1.4 Hz)的频率成分。

生成ECG信号的方法有很多种,下面提供一种基于Matlab的方法: 1. 生成心电图基线信号 使用Matlab中的randn函数生成随机噪声信号,并通过滤波器对信号进行平滑处理,得到心电图的基线信号。 ```matlab fs = 1000; % 采样率 t = 0:1/fs:1; % 时间轴 baseline = 0.1*randn(size(t)); % 随机噪声信号 [b,a] = butter(2,10/(fs/2),'low'); % 低通滤波器 baseline = filtfilt(b,a,baseline); % 平滑处理 ``` 2. 生成QRS波群信号 使用Matlab中的ecgpuwave函数生成QRS波群信号,该函数可以自动检测QRS波群的位置,并输出QRS波群的峰值、起始时间和终止时间等信息。 ```matlab ecg = ecgsyn(fs,6,0.2,0.1,0.1,0.01,0.01); % 生成ECG信号 [qrs_amp_raw,qrs_i_raw,delay,ecg_filtered] = ecgpuwave(ecg,fs,0); % 检测QRS波群 qrs_amp_raw = qrs_amp_raw(qrs_i_raw>fs); % 去掉前面的哪些QRS波群 qrs_i_raw = qrs_i_raw(qrs_i_raw>fs); % 去掉前面的哪些QRS波群 ``` 3. 生成ST段和T波信号 使用Matlab中的randn函数生成ST段和T波信号的随机噪声信号,并通过滤波器对信号进行平滑处理,得到ST段和T波信号。 ```matlab st = 0.05*randn(size(t)); % ST段随机噪声信号 [b,a] = butter(2,[0.5 5]/(fs/2)); % 带通滤波器 st = filtfilt(b,a,st); % 平滑处理 t_amp = 0.2*randn(size(qrs_amp_raw)); % T波振幅随机噪声信号 [b,a] = butter(2,[1 40]/(fs/2)); % 带通滤波器 t_amp = filtfilt(b,a,t_amp); % 平滑处理 ``` 4. 生成完整的ECG信号 将生成的心电图基线信号、QRS波群信号、ST段信号和T波信号叠加在一起,即可得到完整的ECG信号。 ```matlab ecg_new = baseline; for i = 1:length(qrs_i_raw) qrs_amp = qrs_amp_raw(i); qrs_i = qrs_i_raw(i); st_i = qrs_i + round(0.06*fs); % ST段开始时间 t_i = qrs_i + round(0.4*fs); % T波开始时间 % ST段信号叠加 ecg_new(st_i:t_i) = baseline(st_i:t_i) + st(st_i:t_i); % T波信号叠加 t_amp_i = t_amp(i); t_dur = round(0.2*fs); % T波持续时间 t_slope = t_amp_i/t_dur; % T波斜率 ecg_new(t_i:t_i+t_dur) = baseline(t_i:t_i+t_dur) + t_amp_i - t_slope*(0:t_dur); % QRS波群信号叠加 qrs_dur = round(0.06*fs); % QRS波群持续时间 qrs_slope = qrs_amp/qrs_dur; % QRS波群斜率 ecg_new(qrs_i:qrs_i+qrs_dur) = baseline(qrs_i:qrs_i+qrs_dur) + qrs_amp - qrs_slope*(0:qrs_dur); end plot(t,ecg_new); % 绘制ECG信号 xlabel('时间/s'); ylabel('电压/mV'); title('ECG信号'); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值