1. 信号包络检测从“听”到“看”的桥梁在信号处理的世界里我们常常需要从纷繁复杂的波形中提取出最核心、最本质的信息。想象一下你正在听一首交响乐乐器的声音忽高忽低强弱变化构成了音乐的韵律。这个“强弱变化”的轮廓就是声音信号的“包络”。它剥离了高频的细节振荡留下了信号整体幅度随时间变化的趋势。这就是信号包络检测的核心任务——将一个快速振荡的信号转换成一个平滑的、能反映其能量或幅度变化的曲线。这个概念听起来抽象但它的应用无处不在。在通信领域调幅AM广播就是最经典的例子高频的载波信号承载着低频的语音信息而接收端正是通过包络检测将语音信息从载波中“解调”出来我们才能听到广播内容。在生物医学工程中心电图ECG或脑电图EEG信号的分析常常需要提取其包络来观察心率变异性或脑电节律的强度变化。在机械故障诊断中轴承振动信号的高频冲击成分其包络谱能清晰地揭示故障特征频率。甚至在我们日常的音频处理、语音识别中包络信息对于理解语音的韵律和情感也至关重要。因此掌握信号包络检测不仅仅是学会几个算法更是获得了一把钥匙能帮你打开一扇门去理解隐藏在振荡信号背后的物理过程、信息内容或系统状态。无论你是通信工程师、算法研究员还是嵌入式开发者这都是一项基础且强大的技能。接下来我将从一个实践者的角度带你深入理解包络检测的几种核心方法、它们的适用场景以及在实际工程中那些容易踩坑的细节。2. 包络检测的本质为什么我们需要它在深入技术细节之前我们必须先回答一个根本问题为什么要把一个好好的信号变成它的包络直接分析原始信号不行吗答案是在很多场景下直接分析既低效又抓不住重点。2.1 信息维度的降维与聚焦一个实值的振荡信号其信息包含在两个维度瞬时幅度和瞬时频率或相位。对于许多应用我们关心的核心是“强度”或“能量”如何随时间演变而不是每个振荡周期的细微相位差异。包络检测本质上是一种信息筛选和聚焦的过程。它滤除了高频的载波或振荡细节保留了低频的幅度调制信息。这就好比看一幅油画退后几步看整体明暗和轮廓包络比凑近了数每一笔颜料原始信号更能把握画作的情绪和主题。以轴承故障诊断为例。一个健康的轴承其振动信号是平稳的、类似噪声的。一旦出现局部损伤如点蚀、剥落滚动体滚过损伤点时会产生周期性的冲击。这个冲击激发了轴承结构的高频固有振动表现为一系列衰减振荡的波包。原始信号看起来是一团杂乱的高频振荡但如果我们提取其包络就会得到一条清晰的、周期性出现的脉冲序列。这个脉冲序列的周期就直接对应着故障的特征频率如轴承外圈故障频率、内圈故障频率等。没有包络检测这个关键的故障特征几乎淹没在噪声中。2.2 解调从载波中取出信息这是包络检测最经典的应用。在调幅AM系统中有用信号如声音被调制到一个高频载波上形成幅度随信号变化的已调波。接收端要还原原始声音就必须进行“解调”而最简单的解调方式就是包络检波。一个二极管和一个RC低通滤波器就能构成一个物理的包络检测器它输出的就是调制信号的近似。在更复杂的通信系统如QAM或雷达系统中包络检测或更广义的解调同样是核心步骤用于恢复基带信号。2.3 简化后续处理包络信号相比原始信号频率成分更低数据更平滑。这为后续处理带来了巨大便利降低采样率要求根据奈奎斯特采样定理对包络信号进行采样的频率可以远低于对原始高频信号的采样要求节省存储和计算资源。便于特征提取对于模式识别、异常检测等任务从平滑的包络曲线中提取均值、方差、峰值等统计特征比从振荡信号中提取更稳定、更有区分度。可视化与解释包络曲线更符合人类的直观认知便于工程师或研究人员观察信号的整体趋势、事件发生时刻和强度。理解了“为什么”我们才能更好地选择“怎么做”。不同的应用场景对包络的“保真度”、“实时性”和“抗噪性”要求不同这就引出了多种不同的实现方法。3. 经典方法拆解从模拟电路到数字算法包络检测的方法论演进伴随着从模拟时代到数字时代的变迁。理解这些方法的原理和局限是灵活运用的前提。3.1 希尔伯特变换法理论上的“标准答案”在信号处理理论中对于一个实信号x(t)要得到其解析信号z(t)最优雅的方式就是使用希尔伯特变换。解析信号是一个复信号其虚部是实部的希尔伯特变换。z(t) x(t) j * H{x(t)}其中H{·}表示希尔伯特变换。这个解析信号的模绝对值就被定义为该实信号的包络envelope(t) |z(t)| sqrt( x(t)^2 H{x(t)}^2 )为什么它能工作希尔伯特变换可以理解为是一个将所有频率分量的相位推迟90度的滤波器。对于一个单频信号A*cos(ωtφ)其希尔伯特变换是A*sin(ωtφ)。那么解析信号就是A*cos(ωtφ) j*A*sin(ωtφ) A*exp(j*(ωtφ))其模长恒为A完美地提取了幅度A。对于多分量或调制信号它提供了一种在全局意义上构造“瞬时幅度”的数学框架。实操要点与坑点边界效应数字实现希尔伯特变换通常使用FFT快速傅里叶变换。在频域将负频率置零正频率加倍再逆变换回时域即可得到解析信号。但FFT默认信号是周期性的对有限长信号进行操作时在数据块的起始和结束处会产生严重的畸变这就是边界效应。处理实际数据时必须考虑如何缓解例如对数据加窗、重叠分段处理或者简单地舍弃头尾受影响的数据段。计算开销虽然FFT很高效但对于需要实时、逐点处理的应用如嵌入式系统完整的FFT运算可能开销过大。对非平稳信号的解释对于频率快速变化的信号“瞬时包络”的物理意义可能变得模糊需要谨慎理解结果。注意希尔伯特变换法得到的包络对于单分量信号即瞬时频率有明确意义的信号效果最好。对于多分量信号如多个正弦波叠加它给出的是整体信号的幅度可能无法分离出单个分量的包络。3.2 检波二极管与低通滤波硬件工程师的直觉这是最古老、最直观的方法直接源于模拟电路。其核心就两步整流让信号通过一个二极管或运算放大器构成的精密整流电路只保留正半周或负半周或全波整流将交流振荡转换为单向的脉冲。低通滤波用一个RC低通滤波器平滑这些脉冲滤除残留的高频载波成分输出平滑的包络曲线。为什么它能工作整流步骤去掉了信号的负半部分或将其翻转为正使得信号的局部平均值与其包络成正比。低通滤波器则充当了“求局部平均”的角色其截止频率必须远低于载波频率但高于包络调制信号的最高频率以在平滑振荡和保留变化趋势之间取得平衡。实操要点与坑点二极管压降实际二极管有正向导通压降硅管约0.7V。对于小信号这会引入严重失真甚至无法导通。解决方案是使用运放搭建“精密整流电路”也称为绝对值电路利用运放的高增益来消除二极管压降的影响。RC时间常数τ的选择这是该方法成败的关键。τ R * C。τ太小滤波器截止频率高平滑效果差输出包络波动大残留大量载波纹波。τ太大滤波器截止频率低平滑效果好但会无法跟上包络的快速下降沿导致输出波形“跟不上”输入的变化产生失真。在AM解调中过大的τ会导致声音低沉、含糊不清。经验法则τ 应满足1/(f_modulation_max) τ 1/(f_carrier)。通常需要根据实际信号频率通过仿真或实验确定。数字域的仿效在数字信号处理DSP中我们可以用软件完美模拟这一过程先对信号取绝对值或平方再经过一个数字低通滤波器如FIR或IIR。这种方法在数字领域非常稳健且易于控制。3.3 平方律检波与均值/峰值检测这是一类更简单的算法常用于强度估计或能量检测。平方律检波envelope(t) ≈ sqrt( mean( x(t)^2 ) )。这里对信号平方后在一个短时窗口内求平均即求均方值再开方得到均方根RMS值。这个RMS值可以看作是该时间段内信号能量的度量也是一种对包络的近似尤其适用于噪声背景下的信号强度估计。峰值检测跟踪信号在一个周期或一个时间窗内的峰值。在数字域可以通过寻找局部最大值来实现。这种方法对脉冲类信号的包络提取很有效但对噪声敏感且峰值位置会有延迟。选择策略如果你的应用关心信号的平均功率如音频响度RMS方法是合适的。如果关心信号的瞬时冲击强度如振动冲击峰值检测可能更直接。而希尔伯特变换和低通滤波法则提供了更通用的“瞬时幅度”估计。4. 数字实现实战以振动信号分析为例理论说得再多不如一行代码。让我们以一个具体的场景——旋转机械振动信号分析——来串联上述方法并看看在Python或MATLAB环境中如何实现以及会遇到哪些实际问题。假设我们通过加速度传感器采集到一段轴承振动信号vib_signal采样频率fs 10000 Hz。我们怀疑信号中可能存在由故障引起的周期性冲击。4.1 数据观察与预处理首先永远是观察原始数据。import numpy as np import matplotlib.pyplot as plt from scipy import signal, fftpack # 假设我们已经有了 vib_signal 和 fs # 1. 绘制时域波形 t np.arange(len(vib_signal)) / fs plt.figure(figsize(12, 4)) plt.subplot(1,2,1) plt.plot(t, vib_signal) plt.xlabel(Time (s)) plt.ylabel(Amplitude) plt.title(Raw Vibration Signal) plt.grid(True) # 2. 绘制频域谱FFT看主要频率成分 N len(vib_signal) freqs fftpack.fftfreq(N, 1/fs) fft_vals np.abs(fftpack.fft(vib_signal))[:N//2] freqs freqs[:N//2] plt.subplot(1,2,2) plt.plot(freqs, fft_vals) plt.xlabel(Frequency (Hz)) plt.ylabel(Magnitude) plt.title(Frequency Spectrum) plt.grid(True) plt.xlim(0, 2000) # 假设我们关心2000Hz以下成分 plt.tight_layout() plt.show()通过频谱图我们可能会发现一个或多个高频的共振带例如2000Hz附近有一个峰这很可能是冲击激发起的结构固有频率。我们的目标就是提取这个共振频带内信号的包络。4.2 方法一希尔伯特变换法实现def envelope_hilbert(sig): 使用希尔伯特变换计算信号包络 analytic_signal signal.hilbert(sig) # 得到解析信号 amplitude_envelope np.abs(analytic_signal) # 取模得到包络 return amplitude_envelope # 直接应用 env_hilbert envelope_hilbert(vib_signal) # 绘制对比 plt.figure(figsize(10, 6)) plt.plot(t, vib_signal, alpha0.5, labelRaw Signal, colorgray) plt.plot(t, env_hilbert, labelEnvelope (Hilbert), colorred, linewidth1.5) plt.xlabel(Time (s)) plt.ylabel(Amplitude) plt.title(Envelope Extraction using Hilbert Transform) plt.legend() plt.grid(True) plt.show()可能的问题如果原始信号包含直流偏移或低频趋势希尔伯特变换得到的包络也会包含这些成分这可能会干扰我们对高频冲击包络的观察。因此通常需要先对信号进行带通滤波聚焦到感兴趣的共振频带。4.3 方法二带通滤波后求包络更实用的流程这才是工程上的标准做法先滤波再提取包络。# 步骤1设计带通滤波器聚焦共振频带例如 1800-2200 Hz lowcut 1800.0 highcut 2200.0 nyquist 0.5 * fs low lowcut / nyquist high highcut / nyquist # 使用巴特沃斯滤波器阶数不宜过高以避免相位失真 b, a signal.butter(N4, Wn[low, high], btypeband) vib_filtered signal.filtfilt(b, a, vib_signal) # 使用filtfilt实现零相位滤波 # 步骤2对滤波后的信号进行包络提取这里用希尔伯特法 env_filtered envelope_hilbert(vib_filtered) # 步骤3对包络信号进行低通滤波进一步平滑可选取决于包络的波动程度 # 包络信号的最高频率通常远低于原载波频率设为几百Hz可能就够了 env_lowpass_order 2 env_cutoff 500.0 # Hz env_cutoff_norm env_cutoff / nyquist b_env, a_env signal.butter(env_lowpass_order, env_cutoff_norm, btypelow) env_smooth signal.filtfilt(b_env, a_env, env_filtered) # 绘制结果 plt.figure(figsize(12, 8)) plt.subplot(3,1,1) plt.plot(t, vib_signal, alpha0.7, labelRaw) plt.plot(t, vib_filtered, labelBand-pass Filtered (1800-2200Hz), linewidth1.2) plt.legend() plt.title(Step 1: Band-pass Filtering) plt.grid(True) plt.subplot(3,1,2) plt.plot(t, vib_filtered, alpha0.5, colorgray, labelFiltered Signal) plt.plot(t, env_filtered, labelEnvelope (Hilbert on Filtered), colororange, linewidth1.5) plt.legend() plt.title(Step 2: Envelope Extraction) plt.grid(True) plt.subplot(3,1,3) plt.plot(t, env_smooth, labelSmoothed Envelope, colorgreen, linewidth2) plt.legend() plt.xlabel(Time (s)) plt.title(Step 3: Low-pass Smoothing (Final Envelope)) plt.grid(True) plt.tight_layout() plt.show()现在我们得到的env_smooth就是一个清晰的、反映了原始信号在1800-2200Hz频带内能量变化的包络曲线。如果存在周期性冲击你应该能在这条曲线上看到周期性的脉冲。4.4 方法三数字仿真的检波-低通滤波法我们也可以用纯粹的“整流低通滤波”思路在数字域实现。def envelope_lpf(sig, fs, fc_envelope): 通过绝对值整流低通滤波求包络 sig: 输入信号最好已经过带通滤波 fs: 采样率 fc_envelope: 低通滤波器的截止频率应大于包络变化频率远小于信号中心频率 # 1. 全波整流取绝对值 rectified np.abs(sig) # 2. 低通滤波 nyquist 0.5 * fs norm_cutoff fc_envelope / nyquist # 使用阶数稍高的滤波器以获得更好的平滑效果 b, a signal.butter(N6, Wnnorm_cutoff, btypelow) envelope signal.filtfilt(b, a, rectified) # 使用零相位滤波 return envelope # 使用带通滤波后的信号 fc_env 500 # 低通截止频率根据包络变化快慢调整 env_lpf envelope_lpf(vib_filtered, fs, fc_env) # 对比两种方法的结果 plt.figure(figsize(10, 6)) plt.plot(t, env_smooth, labelHilbert Smoothing, linewidth2) plt.plot(t, env_lpf, labelAbs LPF, linestyle--, linewidth2) plt.xlabel(Time (s)) plt.ylabel(Amplitude) plt.title(Comparison of Two Envelope Detection Methods) plt.legend() plt.grid(True) plt.show()你会发现对于这个例子两种方法的结果可能非常接近。AbsLPF方法在计算上更简单在实时嵌入式系统中可能更有优势。而希尔伯特变换在理论上更严谨对于非常复杂的调制信号可能更准确。5. 进阶话题包络谱分析与工程诊断提取出包络并不是终点而是更深入分析的起点。在故障诊断领域包络谱Envelope Spectrum是终极武器。5.1 什么是包络谱包络谱就是对上面得到的包络信号env_smooth(t)再做一次傅里叶变换FFT将其从时域转换到频域。它的物理意义非常明确它显示了包络信号中周期性成分的频率。回到我们的轴承故障例子。如果轴承外圈有一个损伤点那么滚动体每经过这个损伤点一次就会产生一次冲击。这个冲击的周期是固定的比如对应转速的100Hz。这个周期性的冲击调制了传感器固有频率比如2000Hz的振动表现为一系列周期性的衰减振荡波包。我们提取的包络信号理论上就应该是一个以100Hz为重复频率的脉冲序列由于传递路径等影响可能不是理想脉冲。对这个包络信号做FFT就会在100Hz及其倍频谐波处出现明显的谱峰。这个100Hz就是故障特征频率。5.2 如何计算与解读包络谱# 继续使用前面得到的 env_smooth env env_smooth # 或 env_lpf # 计算包络谱 N_env len(env) # 通常会对包络信号进行重采样以降低数据量和突出低频特征 # 因为包络频率很低我们可以用很低的采样率 resample_factor int(fs / 1000) # 例如降到1000Hz采样 if resample_factor 1: env_resampled signal.resample(env, N_env // resample_factor) fs_env fs / resample_factor else: env_resampled env fs_env fs # 计算FFT N_fft len(env_resampled) freqs_env fftpack.fftfreq(N_fft, 1/fs_env)[:N_fft//2] fft_env np.abs(fftpack.fft(env_resampled))[:N_fft//2] # 绘制包络谱 plt.figure(figsize(10, 6)) plt.plot(freqs_env, fft_env) plt.xlabel(Frequency (Hz)) plt.ylabel(Magnitude) plt.title(Envelope Spectrum) plt.grid(True) plt.xlim(0, 500) # 重点关注低频段例如0-500Hz # 假设我们知道故障特征频率是100Hz可以在图上画竖线标注 fault_freq 100.0 plt.axvline(xfault_freq, colorr, linestyle--, alpha0.7, labelfExpected Fault Freq: {fault_freq}Hz) plt.legend() plt.show()如果图中在100Hz、200Hz、300Hz等处出现了明显的谱峰尤其是这些谱峰超出了背景噪声水平那么这就是轴承存在外圈故障的强有力证据。相比直接对原始振动信号做FFT频谱包络谱能极大地抑制与故障无关的随机振动和噪声让微弱的周期性故障特征凸显出来。5.3 参数选择的艺术滤波器与截止频率整个包络分析流程的性能极度依赖于几个关键参数的选择带通滤波器的通带范围必须准确覆盖被故障冲击激发起的“共振频带”。这个频带不是故障频率本身而是传感器或结构本身的固有频率。通常需要通过频谱分析或经验来确定。选得太宽会引入过多噪声选得太窄可能会漏掉部分冲击能量。低通滤波器的截止频率在最后平滑包络时或在AbsLPF方法中这个截止频率fc_envelope至关重要。它必须高于你关心的最高包络变化频率例如故障特征频率的几倍谐波同时远低于带通滤波的中心频率以确保能滤除载波残留。一个常用的起点是fc_envelope 3 ~ 5 * (最高关心的故障频率)。希尔伯特变换的边界处理如果使用分段处理需要处理好段与段之间的重叠以避免边界效应引入的虚假波动。没有放之四海而皆准的参数。最好的方法是基于物理知识设备转速、轴承参数计算故障频率、结构固有频率估算确定大致范围然后通过实际数据反复调试和验证。可以尝试不同的参数组合观察包络谱中故障频率处的峰值是否变得清晰、尖锐。6. 不同场景下的方法选型与避坑指南掌握了核心方法后面对具体项目该如何选择以下是一些经验性的建议和常见陷阱。6.1 通信信号解调场景AM广播、简单的无线数据传输。首选方法绝对值/平方律检波 低通滤波。这是最经典、计算最简单的方法在模拟和数字域都容易实现。对于数字域abs() FIR LPF是标准操作。关键参数低通滤波器的截止频率必须略大于调制信号如音频的最高频率例如4kHz远小于载波频率如1MHz。避坑过载失真确保接收信号幅度在ADC或放大器的线性范围内。载波泄漏如果载波没有被完全抑制会叠加在解调信号上产生高频噪声。确保滤波器的阻带衰减足够。群延迟如果使用IIR滤波器需注意其非线性相位特性可能造成语音失真。对于语音应用通常推荐使用线性相位的FIR滤波器。6.2 振动/声学故障诊断场景旋转机械轴承、齿轮箱状态监测。首选方法带通滤波 希尔伯特变换/绝对值检波 低通滤波。这是行业标准流程通常称为“高频共振解调技术”。关键参数带通中心频率选择系统的一个高信噪比共振频带。这个频带通常不是故障频率而是冲击激起的结构共振频率。包络分析低通截止频率设为预期最高故障频率考虑谐波的3-5倍。避坑选错共振带最大的谱峰不一定是最好的选择有时需要避开工频及其谐波干扰选择一个“干净”的共振带。可以尝试多个频带看哪个产生的包络谱故障特征最明显。忽略转频谐波在包络谱中不仅要找故障特征频率还要注意其谐波以及故障频率与转频的边带这些信息有助于区分故障类型内圈、外圈、滚动体。数据长度不足为了在包络谱中获得清晰的谱线需要足够长的数据以保证频率分辨率。分辨率Δf fs / N。要分辨两个接近的频率需要足够大的N。6.3 生物医学信号处理场景心电图R波检测、肌电信号强度分析、脑电节律提取。方法选择ECG R波检测通常先对信号进行带通滤波如5-15Hz以突出QRS波然后使用希尔伯特变换或求导/平方的方法来生成一个能凸显R波尖峰的特征波形再寻找其包络的峰值。EMG/EEG幅值常使用RMS值平方、平均、开方在一个滑动窗口内计算作为肌肉活动强度或脑电节律强度的度量。这本质上是一种短时包络。避坑基线漂移生理信号常有严重的基线漂移如ECG必须在包络检测前进行高通滤波或去趋势处理否则会严重影响包络形状。窗口长度对于滑动RMS窗口长度是关键。太短则包络波动剧烈太长则无法跟踪快速变化。通常需要根据信号的生理特性如肌肉收缩时长来选择。6.4 音频与音乐信息检索场景计算音频响度、节拍跟踪、音高轮廓提取。首选方法低通滤波的绝对值信号。在音频领域这通常被称为“幅度包络 follower”。为了实时性常使用一阶IIR低通滤波器。# 一个简单的实时包络跟踪器单极点低通滤波器 alpha 0.01 # 平滑系数介于0和1之间越小越平滑 envelope np.zeros_like(audio_signal) envelope[0] abs(audio_signal[0]) for i in range(1, len(audio_signal)): envelope[i] (1 - alpha) * envelope[i-1] alpha * abs(audio_signal[i])避坑攻击与释放时间上述简单IIR滤波器对信号上升Attack和下降Release的响应是对称的。在专业音频压缩器或门限效果器中会使用具有独立攻击和释放时间的包络跟踪器以产生更自然的音响效果。实现时可能需要两个不同的时间常数。过冲与欠冲平滑系数alpha的选择需要权衡响应速度和平滑度。对于节拍跟踪需要较快的响应对于响度计量则需要更平滑。7. 从仿真到实战一个完整的轴承故障诊断代码框架最后我将分享一个相对完整的、可用于实验或原型开发的Python代码框架。它集成了数据加载、预处理、多种包络提取方法、包络谱计算和简单可视化诊断的功能。import numpy as np import matplotlib.pyplot as plt from scipy import signal, fftpack import warnings warnings.filterwarnings(ignore) class VibrationEnvelopeAnalyzer: 一个用于振动信号包络分析的简易类。 def __init__(self, signal_data, fs): 初始化分析器。 Args: signal_data: 一维振动信号数组。 fs: 采样频率 (Hz)。 self.raw_signal np.array(signal_data).flatten() self.fs fs self.time np.arange(len(self.raw_signal)) / fs self.envelope None self.envelope_spectrum None self.freq_env None def bandpass_filter(self, lowcut, highcut, order4): 对原始信号进行零相位带通滤波。 Args: lowcut: 通带下限频率 (Hz)。 highcut: 通带上限频率 (Hz)。 order: 滤波器阶数。 Returns: 滤波后的信号。 nyquist 0.5 * self.fs low lowcut / nyquist high highcut / nyquist if low 0 or high 1: raise ValueError(截止频率必须在0和奈奎斯特频率之间。) b, a signal.butter(Norder, Wn[low, high], btypeband) filtered_signal signal.filtfilt(b, a, self.raw_signal) return filtered_signal def extract_envelope_hilbert(self, signal_in): 使用希尔伯特变换提取包络。 analytic signal.hilbert(signal_in) return np.abs(analytic) def extract_envelope_abs_lpf(self, signal_in, fc_envelope): 使用绝对值低通滤波提取包络。 rectified np.abs(signal_in) nyquist 0.5 * self.fs norm_cutoff fc_envelope / nyquist b, a signal.butter(N6, Wnnorm_cutoff, btypelow) envelope signal.filtfilt(b, a, rectified) return envelope def compute_envelope_spectrum(self, envelope_signal, resample_to_hzNone): 计算包络信号的频谱。 Args: envelope_signal: 包络信号。 resample_to_hz: 可选将包络信号重采样到此频率以降低数据量。 Returns: freq: 频率轴 (Hz)。 spec: 包络谱幅度。 if resample_to_hz and resample_to_hz self.fs: num_samples int(len(envelope_signal) * resample_to_hz / self.fs) envelope_resampled signal.resample(envelope_signal, num_samples) fs_current resample_to_hz else: envelope_resampled envelope_signal fs_current self.fs N len(envelope_resampled) freq fftpack.fftfreq(N, 1/fs_current)[:N//2] spec np.abs(fftpack.fft(envelope_resampled))[:N//2] return freq, spec def analyze(self, bp_lowcut, bp_highcut, env_methodhilbert, env_cutoff_hz500, resample_env_to1000): 执行完整的分析流程。 Args: bp_lowcut, bp_highcut: 带通滤波器截止频率。 env_method: hilbert 或 abs_lpf。 env_cutoff_hz: 仅当env_methodabs_lpf时使用低通截止频率。 resample_env_to: 计算包络谱前的重采样频率。 print(f开始分析: 带通 [{bp_lowcut}-{bp_highcut}]Hz, 包络方法 [{env_method}]) # 1. 带通滤波 self.filtered_signal self.bandpass_filter(bp_lowcut, bp_highcut) # 2. 提取包络 if env_method.lower() hilbert: env_raw self.extract_envelope_hilbert(self.filtered_signal) elif env_method.lower() abs_lpf: env_raw self.extract_envelope_abs_lpf(self.filtered_signal, env_cutoff_hz) else: raise ValueError(env_method 必须是 hilbert 或 abs_lpf) # 3. 对包络进行低通平滑可选但对hilbert结果通常有益 smooth_cutoff min(env_cutoff_hz, bp_highcut/10) # 一个保守的平滑截止频率 nyquist 0.5 * self.fs norm_smooth smooth_cutoff / nyquist b, a signal.butter(2, norm_smooth, btypelow) self.envelope signal.filtfilt(b, a, env_raw) # 4. 计算包络谱 self.freq_env, self.envelope_spectrum self.compute_envelope_spectrum( self.envelope, resample_to_hzresample_env_to ) print(分析完成。) def plot_results(self, fault_freqsNone, xlim_env_spec(0, 500)): 绘制原始信号、滤波信号、包络和包络谱。 if self.envelope is None: print(请先运行 analyze() 方法。) return fig, axes plt.subplots(4, 1, figsize(12, 10)) # 图1: 原始信号 axes[0].plot(self.time, self.raw_signal, colorgray, alpha0.7) axes[0].set_title(1. Raw Vibration Signal) axes[0].set_xlabel(Time (s)) axes[0].set_ylabel(Amplitude) axes[0].grid(True) # 图2: 带通滤波后信号 axes[1].plot(self.time, self.filtered_signal, colorblue, linewidth0.8) axes[1].set_title(2. Band-pass Filtered Signal) axes[1].set_xlabel(Time (s)) axes[1].set_ylabel(Amplitude) axes[1].grid(True) # 图3: 包络信号 axes[2].plot(self.time, self.envelope, colorred, linewidth1.5) axes[2].set_title(3. Extracted Envelope) axes[2].set_xlabel(Time (s)) axes[2].set_ylabel(Envelope) axes[2].grid(True) # 图4: 包络谱 axes[3].plot(self.freq_env, self.envelope_spectrum, colorgreen) axes[3].set_title(4. Envelope Spectrum) axes[3].set_xlabel(Frequency (Hz)) axes[3].set_ylabel(Magnitude) axes[3].grid(True) axes[3].set_xlim(xlim_env_spec) if fault_freqs: for ff in fault_freqs: axes[3].axvline(xff, colororange, linestyle--, alpha0.7, labelfFault Freq: {ff}Hz) axes[3].legend() plt.tight_layout() plt.show() # 使用示例 # 1. 准备或加载你的数据 (这里用模拟数据示例) fs_demo 10000 t_demo np.arange(0, 2, 1/fs_demo) # 2秒数据 # 模拟一个故障冲击信号载波共振频率 调制的脉冲序列故障频率 carrier_freq 2000 fault_freq 100 # 冲击序列每0.01秒一个 impulse_train (np.mod(t_demo, 1/fault_freq) 0.0005).astype(float) # 调制到载波上并加噪声 vib_demo impulse_train * np.sin(2*np.pi*carrier_freq*t_demo) * np.exp(-500*np.mod(t_demo, 1/fault_freq)) vib_demo 0.1 * np.random.randn(len(t_demo)) # 加入高斯噪声 # 2. 创建分析器并执行分析 analyzer VibrationEnvelopeAnalyzer(vib_demo, fs_demo) # 关键参数带通围绕共振频率包络截止频率设为故障频率的几倍 analyzer.analyze(bp_lowcut1800, bp_highcut2200, env_methodhilbert, env_cutoff_hz400, resample_env_to1000) # 3. 绘图并标注预期的故障频率 analyzer.plot_results(fault_freqs[fault_freq, 2*fault_freq, 3*fault_freq], xlim_env_spec(0, 500))这个框架提供了一个起点。在实际项目中你需要根据数据特点调整带通频率、滤波阶数、包络平滑参数等。诊断时在包络谱图中寻找与理论故障频率及其谐波对应的谱峰。这个方法的价值在于它能将肉眼难以从时域波形中识别的周期性冲击转化为频域中清晰可辨的谱线极大地提升了故障诊断的可靠性和早期预警能力。