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

python 希尔伯特变换_Python中HHT(希尔伯特-黄变换)以及其在EEG数据处理中的应用...

在脑电信号的处理过程中去除伪迹是很关键的一个步骤,常用的有ICA和小波等方法。不过这些方法大多是针对多通道脑电数据进行处理的,单通道的脑电数据如何去除伪迹呢?推荐一篇文章《单通道脑电信号眼电伪迹去除算法研究》,在文章中提到了一种WT-EEMD-ICA方法,该方法是小波-集合经验模态分解-独立成分分析的结合。具体内容感兴趣的可以精读下这篇文章,在对应的下载附件中有这篇文章。

上面说的和本篇的内容关系不大,我就是在看了文章后对里面提到的HHT方法感兴趣,就研究了一下。下面主要说的是HHT的实现以及如何准确计算瞬时频率。

推荐几个参考的博客:

相关代码:

# %matplotlib inline

import matplotlib.pyplot as plt

import numpy as np

from pyhht import EMD

from scipy.signal import hilbert

import tftb.processing

import mne

# 定义HHT的计算分析函数

def HHTAnalysis(eegRaw, fs):

# 进行EMD分解

decomposer = EMD(eegRaw)

# 获取EMD分解后的IMF成分

imfs = decomposer.decompose()

# 分解后的组分数

n_components = imfs.shape[0]

# 定义绘图,包括原始数据以及各组分数据

fig, axes = plt.subplots(n_components + 1, 2, figsize=(10, 7), sharex=True, sharey=False)

# 绘制原始数据

axes[0][0].plot(eegRaw)

# 原始数据的Hilbert变换

eegRawHT = hilbert(eegRaw)

# 绘制原始数据Hilbert变换的结果

axes[0][0].plot(abs(eegRawHT))

# 设置绘图标题

axes[0][0].set_title('Raw Data')

# 计算Hilbert变换后的瞬时频率

instf, timestamps = tftb.processing.inst_freq(eegRawHT)

# 绘制瞬时频率,这里乘以fs是正则化频率到真实频率的转换

axes[0][1].plot(timestamps, instf * fs)

# 计算瞬时频率的均值和中位数

axes[0][1].set_title('Freq_Mean{:.2f}----Freq_Median{:.2f}'.format(np.mean(instf * fs), np.median(instf * fs)))

# 计算并绘制各个组分

for iter in range(n_components):

# 绘制分解后的IMF组分

axes[iter + 1][0].plot(imfs[iter])

# 计算各组分的Hilbert变换

imfsHT = hilbert(imfs[iter])

# 绘制各组分的Hilber变换

axes[iter + 1][0].plot(abs(imfsHT))

# 设置图名

axes[iter + 1][0].set_title('IMF{}'.format(iter))

# 计算各组分Hilbert变换后的瞬时频率

instf, timestamps = tftb.processing.inst_freq(imfsHT)

# 绘制瞬时频率,这里乘以fs是正则化频率到真实频率的转换

axes[iter + 1][1].plot(timestamps, instf * fs)

# 计算瞬时频率的均值和中位数

axes[iter + 1][1].set_title('Freq_Mean{:.2f}----Freq_Median{:.2f}'.format(np.mean(instf * fs), np.median(instf * fs)))

plt.show()

# 定义HHT的滤波函数,提取部分EMD组分

def HHTFilter(eegRaw, componentsRetain):

# 进行EMD分解

decomposer = EMD(eegRaw)

# 获取EMD分解后的IMF成分

imfs = decomposer.decompose()

# 选取需要保留的EMD组分,并且将其合成信号

eegRetain = np.sum(imfs[componentsRetain], axis=0)

# 绘图

plt.figure(figsize=(10, 7))

# 绘制原始数据

plt.plot(eegRaw, label='RawData')

# 绘制保留组分合成的数据

plt.plot(eegRetain, label='HHTData')

# 绘制标题

plt.title('RawData-----HHTData')

# 绘制图例

plt.legend()

plt.show()

return eegRetain

if __name__ == '__main__':

####################示例数据分析##################################

# 生成0-1时间序列,共100个点

t = np.linspace(0, 1, 100)

# 生成频率为5Hz、10Hz、25Hz的正弦信号累加

modes = np.sin(2 * np.pi * 5 * t) + np.sin(2 * np.pi * 10 * t) + np.sin(2 * np.pi * 25 * t)

# 信号和时间累加,相当于添加噪声

eegRaw = modes + t

# fs为采样频率,用于正则化频率和真实频率的转换

fs = 100

# 进行HHT分析

HHTAnalysis(eegRaw, fs)

# 选取需要保留的信号进行合成,也就是相当于滤波

eegRetain = HHTFilter(eegRaw, [0, 1, 2, 3])

######################真实数据分析#################################

# 加载fif格式的数据

epochs = mne.read_epochs(r'F:\BaiduNetdiskDownload\BCICompetition\BCICIV_2a_gdf\Train\Fif\A02T_epo.fif')

# 获取采样频率

sfreq = epochs.info['sfreq']

# 想要分析的数据

eegData = epochs.get_data()[0][0]

HHTAnalysis(eegData, sfreq)

HHTFilter(eegData, [0, 1, 2, 3, 4, 5, 6, 7, 8])

一、EMD分解

HHT变换首先要做的是EMD也就是经验模态分解,原始信号就是分解后信号的累加和。开始的时候也是有些疑问的,后面尝试了下,发现真的是这样的啊,这可比小波、ICA这种分解好理解的多了,简单一句话就是将信号分解为不同的成分。

原始信号和分解后合成信号的对比:分解后再合成和原始信号基本保持一致。

开始我还以为计算错了,去掉了IMF0,再看,确实有效果:

二、瞬时频率

查了些资料,还是没搞明白瞬时频率到底是什么意思,在这个场景中我的理解是,其目的就是为了计算EMD分解后信号的频率。不过在一些需要时频分析的场景中应该更加有用吧。

先看一下5Hz+10Hz+25Hz+t信号的情况:EMD分解了4个组分IMF0+IMF1+IMF2+IMF3,IMF0\IMF1\IMF2其对应瞬时频率的中位数为25.24、10.18、5.01,和生成信号的频率相对应,还是比较准确的,取中位数主要是为了去掉边界的影响。

这里有一点需要注意:tftb.processing.inst_freq计算的瞬时频率是正则化后的,如果想要得到真实频率需要进行换算。Matlab中的单位频率指的是奈圭斯特频率(采样频率的一半),在Python中试验了下这里应该是采样频率,而非其一半。

三、应用到真实数据中

HHT这种方法有一个好处,需要确定的参数比较少。和STFT相比不用设置窗长,和WP相比不用设置基函数。选取了一段竞赛数据处理看着还像那么回事,这次就处理到这,后面有机会再进行后续的相关工作吧。

原文链接:https://blog.csdn.net/zhoudapeng01/article/details/108448218

相关文章:

  • 广义表head tail 运算_数据结构习题解答:多维数组和广义表 | 选择题
  • python求中位数的怎么编写_python计算分位数方法
  • 在anaconda安装python命令_Anaconda入门:安装及包与环境的管理(conda命令)
  • python创建提示用户输入查询条件_pythone-2:用户登录并根据条件查询
  • crontab类型的任务python_Linux 上使用 crontab 设置定时任务及运行 Python 代码不执行的解决方案...
  • python epoll多路复用技术_python 网络编程 IO多路复用之epoll
  • python的数字运算_Python中数字的相关运算:数学运算及函数运算
  • python的开发环境有哪些特点_Python集成开发环境有哪些
  • 导出数据表 跳过autoincrease_aTimeLogger按周导出的数据报表
  • python基础网易_python零基础入门命令方式汇总大全,快速恶补你的Python基础
  • python tableview刚开始没有数据很丑_一个TableView(并没有)循环刷新的现象与正确的做法...
  • python mro c3_python的MRO和C3算法
  • word光标一直闪动_Word制作办公室会议签到表,详细步骤,新手也能自己做
  • pythonsys教程_python sys模块
  • nacos启动不能发现服务_您的服务器是否经常不能正常启动,但是还不能停用?...
  • 分享的文章《人生如棋》
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • centos安装java运行环境jdk+tomcat
  • css系列之关于字体的事
  • Invalidate和postInvalidate的区别
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • JDK9: 集成 Jshell 和 Maven 项目.
  • jquery ajax学习笔记
  • Laravel 菜鸟晋级之路
  • mysql 5.6 原生Online DDL解析
  • orm2 中文文档 3.1 模型属性
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • SpringCloud集成分布式事务LCN (一)
  • tab.js分享及浏览器兼容性问题汇总
  • 爱情 北京女病人
  • 前端学习笔记之观察者模式
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 问题之ssh中Host key verification failed的解决
  • 译自由幺半群
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​渐进式Web应用PWA的未来
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #DBA杂记1
  • (09)Hive——CTE 公共表达式
  • (1)SpringCloud 整合Python
  • (4) PIVOT 和 UPIVOT 的使用
  • (6)STL算法之转换
  • (C#)获取字符编码的类
  • (搬运以学习)flask 上下文的实现
  • (编译到47%失败)to be deleted
  • (接口自动化)Python3操作MySQL数据库
  • (十五)使用Nexus创建Maven私服
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (四) 虚拟摄像头vivi体验
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (一)为什么要选择C++
  • (转)linux 命令大全
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据