当前位置: 首页 > ds >正文

基于C语言实现的HRV分析方法 —— 与Kubios和MATLAB对比

基于C语言实现的HRV分析方法 —— 与Kubios和MATLAB对比

  • 背景
  • 实现流程
  • 预处理技术
  • 算法分析所需内存数量
  • 调用示例
  • 频域分析方法
    • RR间期插值
    • RR间期去趋势化
    • FFT变换库
    • FFT+Welch方法
    • AR方法
    • Lomb-Scargle方法
    • 三种方法适用场景
  • 时域和非线性分析
  • 结果对比
    • 与MATLAB对比
    • 与Kubios软件对比
      • 时域和非线性结果对比
      • 频域结果对比
  • 总结
  • 参考资料

本文简单记录了使用C语言实现HRV(心率变异性)的 频域、时域和非线性分析,并与 KubiosMATLAB软件结果进行了对比验证。

背景

本文是我帮一位朋友完成的一个小项目,主要目标是用C语言实现HRV的计算,将计算的结果返回以便进行疲劳、压力及抑郁等神经功能的分析。

HRV的分析内容包含时域、频域和非线性三个部分。本项目主要实现以下内容:

  1. RR间期预处理,RR间期预处理主要是将异常的RR间期进行处理,确保仅对窦性的心拍进行分析;
  2. HRV时域、频域和非线性结果计算。频域分析是三个分析的主要实现内容,分析方法包括FFT+Welch、AR和lomb-scargle三种。

在项目的实现中,所有内存均由外部传入,函数内部不进行动态分配,减少内存碎片,且便于调用者进行内存生命周期的控制,更安全。

实现流程

  1. 预处理。通过对RR间期进行预处理,将异常的间期,如过短/过长、房早及室早等进行剔除;
  2. 获取算法所需内存数量。通过接口传入预处理后的RR间期,以及频域分析方法,RR间期插值方法等获取需要的内存数量;
  3. HRV分析。调用者通过第二步获取的内存数量,申请一个内存块后,传入HRV分析接口进行三个HRV的分析,获取分析结果。

预处理技术

HRV是对窦性(NN)间期进行分析,所以在分析之前,需要对异常的间期进行处理。本算法中主要处理以下几种类型的异常间期:

  1. 长度无效间期。去除RR间期中,低于300ms和高于2000ms的间期;
  2. 房早/室早间期。通过提前+补偿的逻辑查找房早及室早间期,剔除这类型的间期;
  3. 异常间期。提出与整体RR间期比较时,出现间期差较大的异常间期。
/*** @brief Preprocess the RR intervals. Remove outliers and interpolate missing values.* * @param rr_in_ms      Pointer to the input RR intervals in milliseconds.* @param rr_len        Length of the RR intervals array. *                      The value should not be less than MIN_RR_NUM.* @param invalid_ratio Pointer to a float to store the invalid ratio. *                      The value should be between 0 and 1.*                      The percentage of invalid intervals to total intervals less than this ratio means*                      the preprocessing was successful. Otherwise, it failed. *                      The default value is 0.05 if it is NULL.* * @return int          1 on success.*                      0 on too many outliers and intervals invalid.*                      -1 on error.*/
int HRVPreprocess(int16_t *rr_in_ms, uint32_t rr_len, float *invalid_ratio);

其中参数invalid_ratio表示可容忍的异常心拍比率,若异常心拍太多,说明RR间期序列的非窦性心拍太多,HRV的分析结果已无意义。

算法分析所需内存数量

在算法的实现中,不进行内存的申请,所有的内存均需要调用者在外部申请好内存块后传入。调用者通过RR间期、频域分析方法、插值方法(如需要)及AR分析方法(如需要)进行内存数量的计算。

/*** @brief Get the size of the context for HRV analysis.* * @param rr_clean_in_ms  Pointer to the cleaned RR intervals in milliseconds.* @param rr_len          Length of the cleaned RR intervals array.* @param psd_method      Method used for PSD calculation.*                        Options:*                        - PSD_FFT: FFT with Welch method*                        - PSD_AR: Autoregressive method*                        - PSD_LS: Lomb-Scargle * @param interp_method   Method used for interpolation.*                        Options:*                        - INTERP_METHOD_LINEAR: Linear interpolation*                        - INTERP_METHOD_CUBIC: Cubic spline (default for PSD_FFT/PSD_AR if NULL)*                        The value is ignored if psd_method is PSD_LS and can be NULL in this case.* @param ar_method       Method used for autoregressive model.*                        Options:*                        - AR_YULE_WALKER: Yule-Walker method*                        - AR_BURG: Burg method (default for PSD_AR if NULL)*                        The value is ignored if psd_method is not PSD_AR and can be NULL in this case.* * @return size_t         Size of the context in bytes.*/
size_t HRVGetContextSize
(const int16_t *rr_clean_in_ms,uint32_t rr_len, PSD_METHOD psd_method,INTERP_METHOD *interp_method,PSD_AR_METHOD *ar_method
);

不同方法下内存所需数量

频域分析方法有FFT、AR和lomb-scargle三种方法,RR间期插值有线性和三次样条两种方法,AR分析有Yule-Walker和Burg两种方法。总体来说,由于不需要进行RR间期插值和FFT变换,lomb-scargle所需的内存数量最少。

调用示例

调用示例如下所示,包含以下步骤:

  • 函数HRVPreprocess()预处理;
  • 通过函数HRVGetContextSize()获取算法所需内存的字节数,并申请内存;
  • 调用HRVAnalysis()函数进行HRV分析;
  • 释放申请的内存。
	int16_t ms_arr[MAX_LEN] = {0};int count = load_rr_intervals("../matlab/rr.txt", ms_arr, 1000);if (HRVPreprocess(ms_arr, count, NULL) != 1) {fprintf(stderr, "HRVPreprocess failed\n");return;}PSD_METHOD psd_method = PSD_FFT;INTERP_METHOD interp_method = INTERP_METHOD_CUBIC;size_t context_size = HRVGetContextSize(ms_arr, count, psd_method, &interp_method, NULL);uint8_t *context = (uint8_t *)malloc(context_size);if (NULL == context){fprintf(stderr, "Failed to allocate memory for context\n");return;}FrequencyDomainFeatures fdf;TimeDomainFeatures tdf;PoincarePlotFeatures ppf;int ret = HRVAnalysis(ms_arr,count,context,context_size,psd_method,&interp_method,NULL,PSD_UNIT_SEC_SEC_HZ,&fdf,&tdf,&ppf);free(context);

频域分析方法

频域分析中,实现了FFT+Welch、AR和lomb-scargle三种,也是目前主流的HRV频域分析方法。

RR间期插值

在采用FFT+Welch或是AR的分析方法中,需要对RR间期进行插值,一般采用4Hz的重采样,这样得到的信号最高频率在2Hz,满足HRV分析的0~0.5Hz的要求。

插值方法中,算法实现了线性和三次样条两种插值方法。线性插值的优点是实现简单,缺点是不够平滑,可能会引入高频噪声,影响最后的分析结果;三次样条插值优点是曲线平滑,高频段更稳定,缺点是计算复杂度较高。如果条件允许,尽量选择三次样条插值方法,这也是Kubios默认的插值方法。

RR间期去趋势化

RR间期插值后,信号里存在低频趋势或是漂移,需要进行去趋势化。包含一次线性拟合、高阶多项式拟合等方法。本项目采用简单的减均值进行去趋势化。Kubios默认采用的是平滑先验(Smoothness Priors)正则化方法,由于内存问题,项目未实现该方法。

FFT变换库

项目采用开源的kissfft库,该库基于C语言编写,支持外部传入内存进行FFT变换计算。

FFT+Welch方法

FFT+Welch为最常用的HRV分析方法,是HRV中默认的分析方法。通过对信号进行叠加分段,每段分别做FFT后再进行平均,能有效减少随机噪声对谱估计的影响。得益于其快速、稳健及易实现的特点,FFT+Welch适用于大多数HRV的研究场景,尤其是短时间5分钟RR间期的分析。

AR方法

AR分析方法通过估计AR系数进行功率谱的计算。本项目采用Yule-Walker和Burg两种方法实现AR系数的计算,采用固定值为16的阶次。

Yule-Walker基于自相关函数的估计,具有实现简单,计算效率高等特点,但易受噪声的影响,可能出现谱泄露的情况,适用于信号较长且稳定,数据中噪声不大的情况。

Burg基于最小前向预测误差和后向预测误差,迭代估计AR系数。具有模型稳定,谱分辨率更高的特点,因而更适合短数据(如2分钟HRV片段),或是用于需要更平滑、分辨率更高的谱估计,是目前kubios软件中AR方法默认采用的分析方法。但由于采用前后向预测误差,所需的内存也更大。

Lomb-Scargle方法

lomb-scargle是一种专门针对非均匀采样数据的谱估计方法,与FFT和AR方法的最大区别是它不需要先对RR间期进行插值,直接用原始的非等间隔RR间期进行计算,从而避免了插值带来的伪信号,特别适合不规则RR间期数据或是有RR间期缺失的情况。

由于不涉及RR间期插值及FFT变换,仅对正弦和余弦基函数做加权拟合,lomb-scargle所需的内存是最少的。

三种方法适用场景

FFT+Welch为标准HRV分析,在时间长度大于等于5分钟时,应优先考虑该方法。

AR方法适用于时间较短的记录,如2~5分钟的情况。

Lomb-Scargle适用于RR间期不规则或RR间期有缺失,或是不希望插值对结果产生影响的情况。

时域和非线性分析

时域和非线性的分析较为简单,参数根据相应的公式进行计算即可。

结果对比

对MIT-BIH心律失常数据库的100号数据,取前5分钟的RR间期分析,然后与MATLAB和Kubios软件进行对比,检验结果是否准确。

与MATLAB对比

MATLAB对比主要是验证频域的分析结果,采用与MATLAB自带函数的结果进行对比的方法。FFT+Welch与pwelch、AR的Yule-Walker与pyulear、AR的Burg与pburg和Lomb-Scargle与plomb分别对比。

频域功率谱与MATLAB的对比结果

通过上图对比结果,算法频域分析的功率谱与MATLAB自带函数分析的结果基本相同。

与Kubios软件对比

Kubios是一款专业的HRV分析软件,由东芬兰大学的研究团队开发。它在临床研究、运动科学、生理学、心理学等领域被广泛使用,是HRV分析领域的权威工具之一。软件有收费版Kubios HRV Scientific和免费版Kubios HRV Scientific Lite,本项目采用免费的Lite版本进行验证。

Kubios对比主要验证时域、频域和非线性的分析结果。由于Kubios的数据预处理方法不同,在Kubios中的输入为经过预处理完成的RR间期,且软件中去趋势化的选项中选择“None”,Kubios会默认使用去均值。且由于使用的Kubios是免费的版本,频域分析中仅能对比FFT和AR的结果,无法对比Lomb-Scargle的结果。

时域和非线性结果对比

项目中,时域计算的参数与Kubios相同的有:Mean RR、SDNN、Mean HR、STD HR、Min HR、Max HR、RMSSD、NN50和pNN50;非线性相同的参数有:SD1、SD2和SD2/SD1。Kubios结果以及对比结果如下:

Kubios的HRV分析时域和非线性结果

算法与Kubios的HRV时域和非线性结果对比

由上图对比可知,本项目算法在时域和非线性结果与Kubios的结果基本相同,在非线性的SD2参数上略有不同。但根据Kubios自己的计算公式(https://www.kubios.com/blog/hrv-analysis-methods/),SD2的计算结果应与算法的结果一致才对,由于差距不大,此处暂不处理。

频域结果对比

频域主要计算几个频段的能量,Kubios结果及对比结果如下:

Kubios的HRV分析频域结果

算法与Kubios的HRV频域结果对比

算法与Kubios的PSD结果对比

由上图对比可知,FFT+Welch的结果与Kubios基本相同,由于Kubios的VLF频域范围是0到0.04Hz,标准的VLF范围为0.003到0.04Hz,项目采用标准VLF范围,所以在VLF部分的差别相对较大。对于AR的结果同理,除了VLF的差别较大外,其他参数的差别控制在6%以内。

总结

本项目基于C语言实现了HRV的分析,算法通过接收传入的RR间期序列,预处理去除不符合要求的RR间期后,进行HRV时域、频域和非线性的分析,最后将分析结果返回给调用者。

算法在进行频域相关参数计算时,调用者可选择功率谱计算所需的方法:FFT+Welch、AR(可选Yule-Walker和Burg两种)和Lomb-Scargle,在FFT和AR方法上,可以选择RR间期的插值方式:线性插值和三次样条插值,功率谱单位可选:ms*ms/Hz和s*s/Hz。

算法分析结果通过与MATLAB和Kubios软件的结果进行对比,显示结果基本一致,证明算法准确性较高。

参考资料

  1. Malik, M. (1996). Heart rate variability: Standards of measurement, physiological interpretation, and clinical use: Task force of the European Society of Cardiology and the North American Society for Pacing and Electrophysiology. Annals of Noninvasive Electrocardiology, 1(2), 151-181.
  2. https://github.com/mborgerding/kissfft
  3. MathWorks, Inc. pwelch (Power Spectral Density using Welch method). https://www.mathworks.com/help/signal/ref/pwelch.html
  4. MathWorks, Inc. pyulear (Power Spectral Density using Yule-Walker AR method). https://www.mathworks.com/help/signal/ref/pyulear.html
  5. MathWorks, Inc. pburg (Power Spectral Density using Burg method). https://www.mathworks.com/help/signal/ref/pburg.html
  6. MathWorks, Inc. plomb (Lomb–Scargle Power Spectrum). https://www.mathworks.com/help/signal/ref/plomb.html
  7. Kubios Oy. Kubios HRV Software. https://www.kubios.com/
http://www.xdnf.cn/news/18287.html

相关文章:

  • Django 请求生命周期
  • 2025北京世界机器人大会 ​要点总结
  • 检索增强生成(RAG) 缓存增强生成(CAG) 生成中检索(RICHES) 知识库增强语言模型(KBLAM)
  • PPT生成视频的AI大模型应用技巧
  • 第4.3节:awk正则表达式详解-特殊字符
  • apisix负载均衡测试
  • Webrtc在项目中承担的角色
  • 决策树-信息增益(第二十三节课内容总结)
  • 第2章:进阶篇——第2节:索引
  • 从决策树基础到熵与信息增益
  • PYTHON让繁琐的工作自动化-函数
  • 【DL学习笔记】交叉熵损失函数详解
  • 人工智能包括哪些方面内容?
  • minio安装和配置
  • 大数据时代时序数据库选型指南:深度解析与 Apache IoTDB 实践
  • 国产!全志T113-i 双核Cortex-A7@1.2GHz 工业开发板—ARM + DSP、RISC-V核间通信开发案例
  • MiniMax Agent 上线 Market Place ,AI一键复制克隆网站
  • 如何解决IDEA/Datagrip无法连接数据库的问题:解决方法为添加参数-Djava.net.preferIPv4Stack=true
  • MySQL的锁:
  • Image and Video Tokenization with Binary Spherical Quantization 论文阅读
  • 【网络运维】Playbook项目实战:基于 Ansible Playbook 一键部署 LNMP 架构服务器
  • WPF---数据模版
  • 突破成长瓶颈:产品运营能力体系化提升技巧
  • CentOS 7更换国内镜像源
  • Golang context
  • 广州曼顿智能断路器:让用电更聪明,生活更安心!
  • 【案例分享】AI使用分享|如何运用 GPT完成小任务并提升效率 —— Prompt 与案例整理
  • P2404 自然数的拆分问题(典型的dfs)
  • 【运维进阶】实施任务控制
  • 【计算机网络面试】键入网址到网页显示期间,发生了什么?