news 2026/10/1 12:00:18

HHT时频图从解压到画对:EMD分解、Hilbert谱与调参避坑全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HHT时频图从解压到画对:EMD分解、Hilbert谱与调参避坑全流程

简介:希尔伯特-黄变换(HHT)时频图绘制的 MATLAB 代码示例包,面向信号处理研究者、机械故障诊断与生物医学信号分析人员,解决非线性、非平稳信号时频分布可视化的实现与调参问题。压缩包体积约 1KB,仅含 1 个 .m 脚本,重点演示了经验模态分解(EMD)、本征模态函数(IMF)提取、希尔伯特变换求瞬时频率与幅度,以及最终将结果拼接为时频分布图的完整流程。已有 441 人学习。脚本输出清晰呈现各步骤中间结果,便于理解横轴时间、纵轴频率与颜色强度对应的物理含义,并据此调整 EMD 分解参数或后处理策略,减少从零编码与排错的时间。资源体量虽小,但代码结构紧凑,适合作为入门 HHT 时频图绘制的参考模板,并可根据自身信号数据做进一步扩展。

1. 解压“HHT时频图的问题.rar”之前,先看懂这份资料包在解决什么问题

“HHT时频图”这个词在检索里经常拖着“.rar”出现。这通常意味着你拿到了别人整理好的资料包:里面有几张跑好的时频图、一份或Matlab或Python的脚本,运气好还附带说明。但真正复现的人大多卡在同一处:图能出,却不知道对不对——频率轴量程随手写的,色标范围是自动的,分解出的IMF数量多到离谱。这篇笔记把从rar解压到HHT时频图画对的完整路径拆开:先讲三个坐标轴各自怎么算出来,再给一套最小可运行代码,然后按优先级调参数,最后用一张合成信号图验收。适合要做故障诊断、脑电分析或结构振动的工程师和研究生,也适合那些打开资料包发现脚本根本跑不通的人。

2. 时频图三个坐标轴背后的计算:EMD、Hilbert谱和瞬时频率

2.1 从FFT和STFT翻到HHT:非平稳信号为什么需要瞬时频率

FFT的假设是信号在整段记录里平稳,算出来的是全局频率分量;短时傅里叶变换(STFT)用固定窗去分帧,时间分辨率和频率分辨率被窗长锁死——窗短了频率糊,窗长了时间糊。小波换了个思路,靠伸缩平移的基函数来适配,但基函数一旦选错,低频段就会变得很钝。HHT完全是数据驱动的:先对信号做经验模态分解(EMD),拆出若干本征模态函数(IMF),再对每个IMF做希尔伯特变换,得到每个时刻的瞬时幅值和瞬时频率。这里的关键词是“每个时刻”,所以HHT时频图不像STFT那样存在窗长和跳步,频率在任意采样点上都有定义,这对突变冲击、频率漂移这类非平稳成分尤其友好。

实战里我见过最多的误区,是把HHT和FFT直接对比。如果你只是想知道“信号里有哪几个固定频率”,FFT又快又稳,没必要动用HHT;一旦信号的频率成分会随时间改变,FFT只能给你一片模糊的宽带,而HHT能画出“一段亮带从15Hz慢慢爬向35Hz”这种可读性极强的轨迹。我一般这样向团队里的人解释:FFT告诉你“有能量集中在25Hz附近”,HHT告诉你“第2秒到第5秒之间频率从22Hz线性爬升到31Hz”。后者对故障时刻定位至关重要,这也是资料包里通常既有频谱图又有HHT时频图的原因。

2.2 EMD分解的筛选过程:IMF长什么样才算合格

EMD假设任何复杂信号都能分解成有限个本征模态函数加一个残差。IMF要满足两个条件:一是过零点数和极值点数相等或最多差一个;二是上下包络均值处处为零。第二个条件在实际计算中退化为一个阈值判断,因为严格为零意味着要无限次迭代。筛分过程是一层循环:找到信号所有极大值和极小值,用三次样条分别拟合出上包络和下包络,取均值线,然后用原信号减去均值线,得到剩余分量;对剩余分量重复上面流程,直到它满足IMF判据。第一次筛出的IMF是高频成分,之后依次降低频率逐层剥离,最后剩下一个单调或近似单调的残差。

筛分的停止条件绕不开两个参数:相邻两次筛分结果的能量变化(典型阈值0.2到0.3),以及筛分迭代次数上限。阈值太严会把噪声也筛进IMF,太松则IMF内部还藏着没拆开的频率分量。一个常见的翻车场面是:默认参数跑完,出现二十几个IMF,前两个IMF把大部分能量抢走,时频图像一个被揉皱的铝箔纸。这种情况先不要怀疑EMD有问题,大概率是停止条件太严或者信号里混入了明显趋势项。

网上流传的Matlab版HHT工具包多来自Rilling等人的EMD工具箱,它的默认阈值偏向保守;Python的emd库(PyPI上的EMD-signal包)默认参数更像“先跑通再微调”。如果你两份代码的结果不一样,先别急着评判谁对谁错,检查两边IMF数量是否一致,再检查停止条件。EMD分解从高频到低频逐级抽取,第一个IMF频率占比最高,数值上并不是固定频带,而是自适应划分。这个自适应是优点,但也导致它对采样率和端点极其敏感。

2.3 Hilbert谱的构建:从解析信号到时频图上的一个点

拿到合格的IMF之后,对它做Hilbert变换得到解析信号z(t)=a(t)e^{jθ(t)},其中a(t)是瞬时幅值,θ(t)是瞬时相位,瞬时频率ω(t)等于相位对时间的导数。把每个IMF在每个采样时刻的瞬时幅值和瞬时频率放到同一个平面上,就得到Hilbert谱。时频图上的一个点,坐标含义是:某时刻某个频率,颜色的深浅代表该时刻该频率的瞬时能量高低。把所有频率按时间累积,得到边际谱,可以把它理解为“全时段能量按频率的分布”,很多人画完时频图还会顺手补一张边际谱和FFT幅值谱对比,用来验证主频位置是否吻合。

这部分最容易困惑的是“瞬时频率”不是测量出来的,而是相位求导算出来的。相位一旦发生跳变,导数就会出现尖刺,画在图上就是一条垂直亮线或负频率线。所以从这个角度说,HHT时频图对IMF质量极度敏感,后续所有调参本质上都在为“让IMF更干净”服务。时频图上如果是恒定频率信号,比如10Hz正弦,看到的是一条水平亮线;如果是线性扫频信号,看到的是一条从低到高的倾斜亮带;如果是一台旋转机械的启停过程,亮带会呈现“开口的抛物线”样子。这三个基本图案可以作为后续一切调参的参照物。

3. 从.rar到第一张HHT时频图:环境判断与最小可运行代码

3.1 解压后先分清三类产物:.m文件、.py文件和数据信号

解压“HHT时频图的问题.rar”之后,别急着双击任何脚本。先看目录结构。常见三类内容:Matlab脚本(emd.m、hhspectrum.m这类老牌工具,来自网上流传的HHT工具箱)、Python脚本、以及数据文件(.mat或.csv)。判断依据是后缀:有大量.m就准备Matlab环境,装好信号处理工具箱;有.py就准备Python环境,安装numpy、scipy和emd库。数据文件要确认采样率和点数,这直接决定后面频率轴上下限。

如果资料包只有一个打不开的图或者一段残缺代码,也别慌,时频图本质是数据计算出来的,只要原始信号还在就能重建。我的习惯是先把数据文件读出来,查看长度和采样间隔,再用下面的Python流程做一套独立的HHT时频图,跟资料包里的成品图对比。这样就算原始脚本跑不起来,也能得到一张“你自己的图”,并且知道它和参考图差在哪里。

注意:解压后如果看到.bat、.exe或带Untitled后缀的可执行文件,先隔离处理,课程类rar里偶尔会混进广告加载程序,不要双击。

3.2 用emd库跑通最小HHT时频图:代码与参数拆解

下面的代码是一套最小可运行方案,我用EMD-signal这个库(导入名emd)演示。三层信号叠加成非平稳测试信号:一个恒定10Hz正弦,一个中心频率随时间线性爬升的扫频分量,以及一个缓慢漂移项。

import numpy as np import emd # 采样:10秒,4000点,等效采样率400Hz t = np.linspace(0, 10, 4000) x = 1.5 * np.sin(2 * np.pi * 10 * t) \ + np.sin(2 * np.pi * (18 + 0.6 * t) * t) \ + 0.3 * t # 1) EMD分解,返回数组形状为 [IMF数量, 点数] imf = emd.sift.sift(x) # 2) Hilbert变换求瞬时频率(IF)和瞬时幅值(IA) IF, IA, _ = emd.spectra.frequency_transform(imf, t, method='hilbert') # 3) 设定频率轴的量化范围:0~45Hz,300个间隔 freq_edges, _ = emd.spectra.define_hist_bins(0, 45, 300) # 4) 把瞬时频率和瞬时幅值统计到频率间隔里,得到Hilbert谱 freq_hist = emd.spectra.hilbert_spectrum(IF, IA, freq_edges) # 5) 画时频图,用inferno色标,暖色表示能量高 emd.plotting.plot_hilbert_spectrum(freq_hist, freq_edges, cmap='inferno')

逻辑说明:第1步的sift会把输入信号按频率从高到低拆成多个IMF,每个IMF都是同长度的一维数组;第2步对每个IMF做Hilbert变换,得到两条曲线,一条是瞬时频率,一条是瞬时幅值;第3步确定频率轴的边界,返回直方图edges;第4步把“每时刻、每个IMF”的瞬时能量投到对应频率格子,投完就是时频图的数据;第5步才是真正的绘图。整个流程里,除了信号本身,最需要调的就是第3步的频率范围和间隔数。

参数说明:np.linspace(0, 10, 4000)决定了采样率约400Hz,理论可分析频率上限200Hz,这里把频率轴上限定到45Hz是为了看图清晰,因为信号主要能量在10Hz和20到40Hz之间;define_hist_bins(0, 45, 300)三个参数分别是频率下限、上限和区间数,区间数就是纵轴的像素密度,300是视觉比较舒服的值,太低出颗粒感,太高出竖条纹;method='hilbert'是标准Hilbert变换,如果负频大量出现可以换'noda'。

3.3 拿到图后怎么读:横轴、纵轴和颜色的物理含义

HHT时频图读起来只有三个要素,但很多人栽在第一眼的“好看”上。整理成一张表:

坐标/颜色含义在测试信号里应该看到什么
横轴时间,单位秒与输入t完全一致,0到10秒
纵轴瞬时频率,单位Hz0到45Hz范围,有效成分集中在低频段
颜色瞬时幅值(可理解成瞬时能量)10Hz水平亮线一条,20~40Hz倾斜亮带一条
高亮背景块IMF边界/端点效应主要在图两端,正常现象

如果画出来的图在10Hz处是一条均匀的水平亮线,在20到40Hz之间有一条从左下到右上的倾斜亮带,说明EMD把两个频率分量分开了,Hilbert谱也正确还原了瞬时频率。如果倾斜亮带断成两截,说明这个扫频分量被拆成了两个IMF,发生了所谓的过分解。这是后面调参的主攻方向。

4. 把HHT时频图调到论文能用的状态:五个参数按优先级调

4.1 EMD筛分停止条件:先让IMF数量落在正常区间

时频图好不好看,八成取决于IMF质量。EMD的筛分停止条件决定分解出多少个IMF、每个IMF里还残留多少别的频率成分。在Python emd库里,sift的迭代上限和能量阈值影响最大。经验范围:对一个500到5000点的实测信号,IMF数量在7到11个之间通常正常;超过15个就要怀疑过分解;少于5个则可能欠分解。我习惯先把默认参数跑一遍看IMF数量,再决定要不要收紧。

如果IMF数量过多,把筛分迭代上限调低一些,让筛分更早收敛;如果IMF数量过少,说明信号里不同尺度的成分没被分开,试着调高迭代上限或先去掉趋势项。注意:不管怎么调,残差项应该近似单调,如果残差还在明显振荡,说明分解没走完。这个步骤做扎实,后面频率轴和色标才谈得上意义。

4.2 频率上限和分箱数:竖条纹和颗粒感都来自这里

很多人拿到代码直接define_hist_bins(0, fs//2, ...),把频率轴拉满到Nyquist,结果是大部分区域空白,有用的频率只在最底下一条细线。正确做法是先看边际谱或FFT,确定能量集中区间,再把频率上限设到该区间的1.2到1.5倍。比如能量集中在50Hz以下,就设(0, 60, 300)。

分箱数是另一个调参入口。箱数太少,瞬时频率会被量化成粗块,图看起来像马赛克;箱数太多,每个格子里能量稀疏,画出来是一根根竖条纹。200到500是常见的平滑区间。我一般先设300,如果条纹明显就降到250,如果太糊就加到400。还要注意分箱数变化不影响物理结果,只影响显示,真正决定频率细节的是采样率和信号本身。

4.3 色标锁定与画布设置:多图对比前必须做的事

时频图颜色代表瞬时幅值,而幅值上限由能量最大的那个点决定。如果每次画图都用自动色标,两张图的颜色深浅就没有可比性。同一批实验数据做对比前,先把所有数据拼在一起算一个全局最大值,然后用vmin和vmax把色标固定下来,这点在论文组图里尤其重要。

色标的选择也有讲究。常见jet色标会把高能量区域渲染成红色,但它的颜色顺序在低亮度区会造成视觉误导;inferno和magma这类顺序色标更适合能量谱。画布尺寸保持统一,dpi设置在150以上,否则暗色区域的渐变会糊掉。把上面的经验收敛成一张参数表:

参数常见默认建议起始值主要影响
筛分迭代上限库默认300~1000IMF数量与过分解
能量停止阈值库默认0.2~0.3IMF纯度
频率上限Nyquist能量集中区的1.2~1.5倍有效显示范围
分箱数库默认200~500颗粒感/竖条纹
色标范围自动手动锁死vmin/vmax多图可比性

5. HHT时频图复现避坑:从rar伪加密到模态混叠的五个排查点

5.1 解压提示要密码,先查是不是rar伪加密

现象:双击“HHT时频图的问题.rar”,WinRAR提示需要密码;输入空密码和常见口令都失败。这也是“rar伪加密”“rar忘记解压密码”这类检索词常年有流量的原因。

原因:这类课程资料包在二次传播中常被重新打包,发布者可能随手加了伪加密——在rar文件头里把加密标志位置为1,但实际数据没有加密,弹窗要密码只是表面现象。另一种情况是文件被损坏,解压工具误报了加密位。

解决:用16进制编辑器打开这个.rar,定位文件头标志(HEAD_FLAGS)区域,找值为0x04的加密标志位,把它改成0x00,保存后重新打开即可直接解压。更快的办法是直接用7-Zip解压,7-Zip在不少伪加密场景下不会理会这个标志位。改之前先备份原文件。真加密的rar这个方法无效,也别在密码恢复工具上花时间,直接找资料发布者要口令。

5.2 时频图两端大面积高亮:端点效应

现象:时频图在时间轴两端出现大面积高亮,或者瞬时频率在两端剧烈抖动,像被风吹起的纸角。

原因:EMD筛分时三次样条包络在信号两端没有极值约束,包络会漂移;Hilbert变换在截断处也有振铃。两个效应叠加,两端时频图基本不可信。

解决:通用三招。先在分解前对信号做镜像延拓或边界极值延拓,让包络有约束;分解后裁剪,把每个IMF两端各去掉5%的点再算Hilbert变换;画图时把时间轴范围也相应裁掉。我一般直接裁剪时间轴5%,简单稳定,缺点是会损失一点时间覆盖,对长记录无所谓。

5.3 相邻频率糊成一片:模态混叠

现象:时频图上两个频率成分之间的区域出现梳齿状亮纹,或者本来该是干净扫频线的区域出现不连续跳跃。

原因:EMD分解对间歇性高频成分敏感,比如一段信号里前段有冲击后段没有,这种时间尺度差异会让EMD把同一个物理分量拆到不同IMF里。

解决:按成本从低到高试三步。第一步带通滤波预处理,把研究频带外的能量先压下去;第二步用集合经验模态分解,对应emd库里的emd.sift.ensemble_sift,集成次数50到100次,加入白噪声辅助分解;第三步上CEEMDAN类方法抑制残差噪声。多数场景第一步就够,别一上来就集成200次,计算耗时会让人怀疑人生。

5.4 同一批数据画出来颜色不一样:色标范围没锁死

现象:同一组数据,换了一个时间段画图,颜色深浅完全不同,明明信号最大幅值没有变化。

原因:绘图函数默认按当前输入的数据自动计算色标范围,局部段的瞬时幅值上限和全局段不一致,导致同一能量强度在不同的图里呈现出不同颜色。

解决:要对比时,先对整个信号算一遍freq_hist,拿到全图最大值,再把这个最大值传给所有子图的vmax;或者统一用某个固定值比如0.8倍全局最大值。这个习惯花两行代码,能避免对比图色标不一致的问题。

5.5 时频图出现负频率线:先查IMF是否合格

现象:时频图上出现频率低于0Hz的亮线,或者在某条IMF曲线中间出现向下凹陷到负值的细线。

原因:瞬时频率是相位求导,IMF不满足Hilbert变换适用条件时,解析信号的相位会出现局部回流,导数就变负。强噪声和剧烈幅值调制都会诱发。

解决:先看对应IMF的包络是否光滑,包络震荡剧烈说明这个IMF不合格,返工EMD参数或者对该IMF做低通平滑;然后把method从hilbert换成noda(直接正交法),负频数量通常会减少;最后确认负频出现的位置是否对应信号的瞬态突变时刻,真实的相位翻转也可能产生负频,这种情况下不一定要抹掉它。

6. 用一张合成信号图验收HHT流程是否画对

6.1 验收信号与脚本:三个特征一眼看齐

拿真实信号调参数,缺点是没有标准答案。我习惯在做任何数据之前,先跑一个已知答案的合成信号,验证这套流程没有坏掉。下面这个组合足够验证三个关键特征:恒定频率、扫频、瞬态冲击。

import numpy as np import emd t = np.linspace(0, 5, 2500) x = np.sin(2 * np.pi * 10 * t) \ + np.sin(2 * np.pi * (15 + 6 * t) * t) x[:500] += 0.8 * np.sin(2 * np.pi * 80 * t[:500]) * np.exp(-4 * t[:500]) imf = emd.sift.sift(x) IF, IA, _ = emd.spectra.frequency_transform(imf, t, method='hilbert') freq_edges, _ = emd.spectra.define_hist_bins(0, 100, 400) freq_hist = emd.spectra.hilbert_spectrum(IF, IA, freq_edges) emd.plotting.plot_hilbert_spectrum(freq_hist, freq_edges, cmap='inferno')

验收三个点:第一,10Hz正弦应该在时频图上呈现一条水平亮线,位置不偏不倚;第二,扫频分量应该是一条从(0秒,15Hz)到(5秒,45Hz)的倾斜亮带,中间不断裂;第三,前500毫秒的80Hz冲击应该在左上角形成一块独立的亮斑。如果这三样都看得清楚,说明EMD分解、Hilbert变换和谱统计这条链路是通的。

6.2 验收通过后固定三件套:采样率、频率上限、色标

验收通过不代表可以随意乱调。回到真实数据时,我会把三样东西先固定下来:采样率不变、频率上限按实测信号能量区设置、色标vmax用全段最大值锁定。所有后续参数只在EMD停止条件上微调,这样每次出图之间只有分解质量这一个变量在变化,排查问题才容易。

这算是我这几年做时频图最深的体会:HHT不是拿来就跑的现成算法,它每一步都留了参数口子,图不对时先怀疑IMF,再怀疑谱统计,最后才怀疑绘图。合成信号验收看似多了一步,实际省下的是对着真实数据反复猜玄学问题的时间。希望这篇从rar到成图的流程帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 12:00:12

用智能体+Hugging Face构建可审计的AI考题生成流水线

这个标题乍一看像一则科技圈的悬疑新闻——“OpenAI的700个智能体入侵Hugging Face,只为做出一道考题,两个多月没人发现”。但稍加推敲就会发现:它根本不符合任何已知的技术事实、组织行为逻辑或平台运行机制。作为在AI基础设施、开源社区运营…

作者头像 李华
网站建设 2026/10/1 12:00:11

基于Spring Boot+Vue的宿舍水电费报修管理系统设计与实现

1. 项目整体设计与技术选型思路 1.1 核心需求解析:宿舍管理员到底想要什么 做这个系统之前,我特地去和几位高校后勤的老师聊过,发现大家的需求高度一致:宿舍水电费核算太麻烦、报修进度全靠微信群吼、月底对账更是让人头大。 传…

作者头像 李华
网站建设 2026/10/1 12:00:11

Linux运行Excel VBA宏:Wine、虚拟机、兼容层与Python重写

上周有个做运营报表的朋友甩给我一个 3MB 的.xlsm文件,里面塞了两千多行 VBA,干的事情是每天把三个部门的明细表跑一遍 SUMIFS、生成一张甘特图、再导出一份带格式的汇总表。问题是他整套工作流已经搬到 Linux 上了,服务器是国产 Linux 发行版…

作者头像 李华
网站建设 2026/10/1 11:59:49

ARM汇编CMP指令原理与实战:标志位、条件执行与跨架构避坑

1. CMP指令到底在ARM汇编里干啥?别再把它当成“比较就完事”的黑盒了你写ARM汇编时,是不是经常看到CMP R0, #5、CMP R1, R2这类指令,顺手就抄进代码里,然后靠BEQ、BNE跳转收尾?我刚入行那会儿也是——直到有次调试一个…

作者头像 李华
网站建设 2026/10/1 11:59:41

Univer在线表格实战:用命令拦截实现单元格只读与可编辑区域控制

1. 为什么选Univer做在线填报表格:场景与选型分析 1.1 一个很常见的需求:表格能看,但不能随便改 先说我手上这个项目。甲方要做一个报表平台,其中一个核心功能是:运营人员从后台选择一张报表模板,模板里已…

作者头像 李华
网站建设 2026/10/1 11:59:23

MATLAB高斯光束到平顶光束整形:GS算法与SLM相位分布计算

我一直觉得,光束整形是光学实验里“看起来简单、做起来全是细节”的典型课题。这篇东西聊的是用MATLAB实现高斯光束到平顶光束的转变,核心手段是GS算法和直接计算SLM相位分布这两条路。简单说,就是激光器出来的光斑强度是中间亮、边缘暗的高斯…

作者头像 李华