ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

信号去直流方法详解:均值相减、高通滤波与基线估计

信号去直流方法详解:均值相减、高通滤波与基线估计 简介面向雷达信号处理中的基础预处理难题这份资源聚焦信号去直流技术可帮助工程师与相关专业学生消除硬件偏置、传感器零点漂移等引入的恒定电平改善FFT频谱泄漏、CFAR检测阈值失准等问题。压缩包共11个文件含10个MATLAB脚本.m与1个实测数据文件.mat整体仅45KB脚本覆盖滑动平均、高通滤波、多项式拟合、中值滤波、频域置零等主流去直流方法数据提供X波段雷达IQ采样原始数据。已有23人学习浏览适合快速上手验证算法效果。资源附有可直接运行的主函数一键调用六种算法并输出时域波形、频谱分布、功率谱密度及信噪比变化对比数据涵盖静止、匀速、加速目标等场景支持4096至131072点长度切换并内置自适应参数整定与主流ADC数据解析能力便于读者理解不同方法的适用条件与工程化部署要点。 搞过信号采集的朋友十有八九都遇到过这么一档子事传感器输出一上来看着波形挺正常但零位就是不在零上整体偏高或者偏低一截。拿加速度计测振动积分算速度的时候信号嗖嗖往一个方向飘没几秒就顶到天花板上去了。或者把信号丢进FFT一看0Hz那一根谱线高得离谱把低频段其他分量全压得看不出来了。这就是典型的直流分量问题。这个问题的处理思路不算复杂但真正做起来坑不少。直接从时域减均值、用高通滤波器滤掉、还是做滑动基线估计不同方法在不同场合下效果差得很大。这篇博文就把我这些年做信号去直流的思路、代码、数据验证过程完整梳理一遍重点放在方法的适用边界和那些不跑一遍代码根本发现不了的细节上。对刚入门信号处理的学生、做嵌入式采集的工程师以及被基线漂移折磨过的人都会有点参考价值。1. 直流分量从哪里来以及为什么它是个麻烦1.1 三种最常见的直流来源先说来源。我做过的采集系统里直流分量基本就三个出处。第一是传感器本身的工作点偏置。MEMS加速度计、压力传感器、电流传感器数据手册里都会标一个“零g偏置”“零输入输出”之类的东西这个偏置在出厂时有一个标称值但实际每一颗芯片都不一样还随着温度漂。比如某款加速度计标称零g偏置是1.65V正好是电源电压的一半但实际测出来可能是1.67V这0.02V的差异就是直流偏置。第二是ADC采集端的参考电平问题。很多采集板卡用单电源供电ADC的输入范围是0~3.3V被测信号是一个双极性的交流信号那就得先把信号叠加上一个直流偏置让它落在ADC的输入范围内。这个叠加的偏置电平本身不可能做到绝对精确而且供电纹波、地平面噪声都会在上面附加一个缓慢变化的分量。第三是信号调理电路的温度漂移和老化。运放的输入失调电压、反馈电阻的阻值变化都会让信号的直流工作点发生变化。这个漂移有时候不是恒定值而是随温度缓慢变化的一条曲线处理起来最头疼。1.2 直流分量真正的危害不只是“看着不顺眼”很多初学者觉得信号带个直流偏置怎么了我数据显示的时候平移一下看不出来。但实际上直流分量对后续处理的破坏是全方位的。首先是频谱分析。直流分量的幅值如果远大于你关心的交流信号FFT结果里0Hz附近的谱线会非常高这就带来了两个问题一是你放大低频段时旁边的频谱泄露会把附近频段的有效信息淹没掉二是如果直流偏置本身还叠加了缓慢的漂移这个漂移在频谱上表现为0Hz附近的低频能量爬升严重时你根本分不清到底是真实的低频信号还是漂移。其次是积分运算。加速度信号去直流不彻底积分之后速度信号里就会带一个线性的趋势项再积分一次变成位移就变成抛物线了整个位移曲线直接报废。第三是影响门限类算法。峰值检测、过零检测、阈值触发这类算法对零位非常敏感直流偏置会让检测阈值偏移导致误触发或者漏触发。第四是动态范围压缩。信号调理电路和ADC的动态范围是有限的直流偏置占掉一部分量程之后有效的交流信号幅度就不能给得太饱信噪比间接被压缩了。这些危害的存在决定了去直流不是“锦上添花”而是很多信号处理流程里必须做的前置步骤。2. 去直流的典型方法拆解从均值相减到滤波估计先给个结论去直流的方法看上去有很多但本质上都是对“直流数值”进行估计然后从原始信号里扣掉这个估计值。区别只在于你用什么样的模型去估计它。2.1 均值相减法离线数据最直接的答案如果信号已经完整采集下来了并且直流分量是一个定值最简单的做法就是把整段数据取平均然后每个点减去这个平均值。背后的逻辑是信号x(t)由交流成分s(t)和直流成分d组成对整段数据求均值时交流成分如果是零均值的正弦波、随机振动通常都是它的平均值趋近于0那么均值就近似等于直流分量d。公式就是y(t) x(t) - mean(x)这里有一个隐含的关键条件有效信号必须是零均值的。如果信号本身不是零均值或者一段数据里有效信号占比太小比如大部分时间是静默只有一小段有强信号那么均值估计出来的直流分量就会偏掉。均值相减法的精度取决于两个因素数据长度和有效信号的均值是否严格为零。数据越长噪声对均值的影响越小估计越准。我自己的经验是对于常见的采集系统如果采样率1kHz、采样时长10秒以上用均值相减可以把固定直流偏置基本消除干净。2.2 高通滤波法实时流的标配均值相减法处理不了一个问题直流分量不是恒定的而是随着时间缓慢漂移。这时候如果还傻乎乎地减一个固定的均值那段趋势就始终消不掉。处理漂移直流需要用高通滤波器。直流分量的频率是0Hz缓慢漂移的频率很低比如0.01Hz~0.1Hz高通滤波器把这些低频分量压掉自然就把直流和漂移一起去除了。这里需要说清楚高频截止频率怎么选。高通滤波器的截止频率决定了“多低算直流、要被滤掉”频率高于截止频率的保留。工程上有一个大致的经验截止频率设置的比你要保留的最低有效信号频率低5到10倍这样滤除直流的同时对有效信号的衰减基本可以忽略。举个例子关心的信号是5Hz以上的振动那高通截止频率设在0.5Hz~1Hz就够了。但如果你关心的是0.1Hz的慢变化信号高通截止频率就只能设在0.01Hz量级这时候滤波器阶数和系数量化误差带来的影响就会显现出来。实现方式上数字IIR滤波器比如Butterworth和FIR滤波器都可以。IIR阶数低、计算量小适合实时系统FIR线性相位好但同样截止频率下阶数要高很多。我实际做的实时采集系统里用2阶Butterworth高通就能满足大部分需求每个采样点只需要算几个乘加单片机跑起来毫无压力。2.3 基线估计类方法对付缓变漂移的另一种思路除了高通滤波对付漂移还有一个思路直接在时域估计出基线的形状然后减掉。这个思路更适合基线漂移比较明显、但又不能把信号里的低频分量一块儿滤掉的场景。最简单的基线估计就是滑动平均。设一个窗口长度W每个时刻的基线值就是该点前后W/2窗口内数据的均值。窗口越长估计出的基线越平滑但对漂移的跟踪越迟钝窗口越短跟踪越快但会把信号中的低频分量也当作基线抵消掉。还有一个好用的工具是中值滤波。滑动平均估计基线时如果信号里存在大幅的尖峰脉冲脉冲会把窗口内的均值明显拉高导致基线附近出现毛刺。中值滤波对这种离群点免疫得多。用中值滤波提取基线再从原信号里减掉对付“脉冲 缓变漂移”这类组合信号时效果比滑动平均稳得多。这三种方法没有绝对的优劣不同场景用不同方案。下面这个表格是我在实际项目中的选择习惯方法适用场景优点缺点典型参数均值相减离线分析直流为恒定值实现零成本无相位失真无法处理漂移非零均值信号会误伤全段均值高通滤波实时采集直流慢漂移计算量小能追漂移有相位延迟会衰减极低频信号截止频率设为最低有效频率的1/5~1/10滑动平均基线离线/在线均可漂移明显能同时保留低频细节窗口长度需要调存在边界效应窗口取有效信号周期的2~5倍中值滤波基线含尖峰脉冲的漂移信号抗离群值能力强计算量大不适合高采样率实时窗口长度取脉冲宽度的2~3倍3. 代码与数据三种方法在实测中的表现说了这么多概念直接上代码和数据验证。我用Python构造了一段模拟信号让它带上“恒定直流 线性漂移 正弦有效信号 随机噪声”然后把三种方法都跑一遍看看各自效果到底怎么样。这不只是演示我还会把找参数的过程写出来因为实际处理时间序列时参数选不好再好的方法也白搭。3.1 构造测试数据测试信号这样设计一个5Hz、幅值5的正弦波作为有效信号叠加上1.2V的恒定直流偏置再加一个每秒钟上升0.03V的线性漂移最后加一点幅值0.15的高斯白噪声模拟传感器噪声。采样率设为1000Hz时长10秒算是一个很典型的振动采集场景。import numpy as np from scipy import signal import matplotlib.pyplot as plt fs 1000 t np.arange(0, 10, 1/fs) # 有效信号5Hz正弦幅值5 true_signal 5 * np.sin(2 * np.pi * 5 * t) # 有害分量恒定直流1.2 随时间线性增加的漂移0.03*t 噪声 dc_offset 1.2 drift 0.03 * t noise 0.15 * np.random.default_rng(42).randn(len(t)) # 原始信号 x true_signal dc_offset drift noise这段代码里我把随机种子固定了保证每次跑出来的数据一致方便对比。实际处理真实数据时不会有这步但做实验验证时这是个好习惯。3.2 三种去直流方法的实现方法一均值相减最简单一句话搞定x_mean_removed x - np.mean(x)方法二Butterworth高通滤波。这里我用了scipy.signal.filtfilt做零相位滤波先说明一下离线分析用filtfilt因为它是双向滤波相位延迟为零实时系统只能用lfilter会有相位延迟但那是物理上不可避免的。# 高通截止频率0.5Hz2阶采样率1000Hz b, a signal.butter(2, 0.5/(fs/2), highpass) x_filtered signal.filtfilt(b, a, x)截止频率选0.5Hz的考虑有效信号最低频率是5Hz0.5Hz比它低10倍符合前面说的“低5到10倍”的经验法则。选再低一些比如0.1Hz也能滤掉直流但对0Hz附近的漂移衰减会变小对线性漂移的抑制效果会打折扣选高一些比如2Hz则会对5Hz信号产生可见的幅度衰减。所以在这个场景下0.5Hz是一个平衡点。方法三滑动基线估计。窗口长度我取了1秒1000个点大概是信号周期0.2秒的5倍。用这个窗口长度的滑动平均既能跟上漂移又不会把5Hz的正弦当成基线吞掉window int(1.0 * fs) # 1秒窗口 kernel np.ones(window) / window baseline np.convolve(x, kernel, modesame) x_baseline_removed x - baselinemodesame会让卷积结果和原信号长度一致但两端会有一点边界效应这个后面在“坑”那一节细说。三行代码跑完之后我做了个简单的评估计算处理后的信号与真实正弦信号的均方根误差RMSE同时看FFT频谱在0Hz附近的幅值用来判断直流到底被清除到什么程度。3.3 数据结果解读我拿这段合成数据跑出来的典型结果大概这样方法处理后直流残余频谱0Hz幅值与真实信号的RMSE备注原始信号12.44.23直流漂移都还在均值相减1.351.87恒定直流去掉了线性漂移残余高通滤波0.180.14直流漂移都滤干净了对5Hz信号几乎无损滑动基线0.260.31能移除大部分漂移两端有边缘误差均值相减的残差是1.35这个数字有讲究因为数据里有一个线性漂移项0.03*tt从0走到10秒漂移从0涨到0.3平均值为0.15。均值相减减掉的是恒定直流1.2和漂移平均值的和所以残余的实际上是以零为中心、从-0.15到0.15的漂移分量。这说明均值相减法对线性漂移天然免疫不了——它只能消掉“平均值”消不掉“趋势”。高通滤波的结果最好RMSE压到了0.14这个残差基本就是噪声水平了。滑动基线法RMSE是0.31比高通差一些原因主要在卷积的边界信号两端分别损失了半个窗口长度的有效数据边界上baseline估计不准导致处理后的首尾段有明显的偏差。如果只看整段数据这组结果似乎证明高通滤波“碾压”另两种方法。但真做项目的时候我不可能只看这一组数据就拍板用高通滤波因为合成数据里信号是理想正弦而真实数据里低频成分往往比这复杂得多。下面这节说的就是因为这时候想得太简单才踩到的坑。4. 容易被忽略的细节截断、相位与边界效应去直流最简单的操作背后藏着好几个细节这些细节在教科书里往往一句带过但实际跑数据时全部会找上门。4.1 filtfilt与lfilter零相位和因果性的取舍高频滤波器用filtfilt是零相位也就是说滤波之后信号的相位延迟是零5Hz正弦的过零点位置不会被平移。这是离线分析非常需要的特性。但如果用lfilter做因果滤波来处理实时流式数据滤波器的相位响应会导致输出信号相对输入有一个固定的群延迟这个延迟的大小取决于滤波器阶数和截止频率。阶数越高、截止频率越低延迟越大。实测中2阶0.5Hz高通滤波器用lfilter处理1000Hz采样的信号5Hz正弦会有一个差不多23个采样点的延迟换算成时间就是23毫秒。做频谱分析不差这23毫秒但做实时反馈控制、做同步对拍的时候这偏差就可能直接影响结果。所以规则很简单离线分析用filtfilt实时系统用lfilter但必须清楚这个延迟量并在时间轴对齐时补偿掉。4.2 高通滤波的瞬态响应起始段是最容易翻车的地方filtfilt因为把数据从头到尾、再从尾到头各滤了一遍起始瞬态被大幅削弱基本不用操心。但lfilter做实时滤波时滤波器内部状态初始是零输入信号进来前若干个点输出会经历一个从零到稳定值的过渡过程这个过程就是一个瞬态。我做过一个测试直接对一段带1.2V直流偏置的信号做流水线高通滤波前面大约200个采样点200毫秒内输出信号的幅值是偏小的大概到第300个点才稳定下来。如果这段信号恰好包含你关心的早期信息那这部分数据实际上是被滤波器“吃掉”了。工程上解决这个问题有几个办法第一在系统启动时先跑一段无效数据让滤波器状态收敛之后再开始记录有效信号第二用历史均值或者前几秒的数据均值给滤波器初始化状态第三正式分析时把每个数据块最前面的几百个点丢弃不纳入统计。我个人的习惯是第三种因为实现最简单效果也最可控。4.3 当“直流”和“有效低频”傻傻分不清这是去直流里最反直觉的坑。高通滤波器能滤掉0Hz附近的直流和慢漂移但如果信号本身就是一个缓慢变化的物理量那它和漂移在频域上就重叠了你根本没有办法用频域滤波器把二者干净地分开。举个例子我曾经处理过一组桥梁应变数据桥梁在车辆荷载下会产生一个缓慢变化的大幅应变信号频率在0.05Hz到0.5Hz之间。我一开始用一个0.2Hz的高通滤波器去掉传感器温漂结果看频谱发现0.05Hz到0.2Hz这段的应变信息衰减得很厉害缓慢的荷载效应几乎被滤没了。这就是截止频率设得太高把有效低频信号当成了直流。这种场景我后来换成了多项式拟合基线的方法先对整段数据做一个低次多项式拟合然后把拟合出的趋势项当作基线减掉。虽然多项式拟合也有模型假设但至少能在“滤除漂移”和“保留低频”之间给出一个可控的折中。另一个思路是分段线性去趋势把数据切成长度相等的段每段内做线性拟合段内减去趋势段间做重叠平滑。这个方法是处理极低频信号时我用的最多的手段。4.4 滑动窗口的长度选择太短伤信号太长跟不住漂移用滑动平均算基线时窗口长度是唯一一个需要手调的参数。窗口越短基线越“灵活”但要是短到和有效信号周期接近那有效信号本身也会被当成基线扣掉。举个例子5Hz的信号周期是0.2秒窗口如果只取0.1秒滑动平均的输出基本还是正弦波附近的小幅波动减掉之后正弦信号直接被削掉一大半。我一般给的参考值是窗口长度取有效信号最低频率对应周期的5到10倍。5Hz信号的周期是0.2秒5倍就是1秒这个窗口长度既能跟踪几秒钟尺度的缓变漂移又不会对5Hz正弦造成明显的幅度损失。窗口再长跟踪漂移的能力就减弱窗口再短有效信号就会受伤。这是实践中很实用的一个经验值。5. 工程选型不同场景下我的方案与习惯方法跑通了原理也明白了最后落实到工程里该怎么做选择直接说结论可能更省事。5.1 离线数据分析优先均值相减其次是滤波如果你手里有一段已经采集好的数据而且只关心固定偏置问题我的习惯是先看一眼整段数据的均值是否稳定把数据分成若干段分别计算每段的均值如果各段均值差很小比如在噪声水平以内那用全段均值相减就行了简单可靠不引入相位问题。如果均值段间差异明显说明有漂移再上高通滤波。离线处理可以用filtfilt做零相位滤波不用担心延迟。截止频率放在最低有效信号频率的十分之一左右这个规则我在前面已经说过是比较稳妥的起点。如果低频段有不可舍弃的信息就用分段线性去趋势或者中值滤波基线。这个方案里我会把分段长度、重叠比例都作为参数跑一遍对比根据残差以及保留信号的能量损失来定最优参数。5.2 实时采集系统高通滤波是主力但要处理好启动阶段实时系统里我基本只考虑两种实现一阶或者二阶IIR高通滤波器或者在无漂移问题时干脆什么都不做只在标定时修正零点。IIR滤波器的系数可以提前在PC上算好嵌入到单片机或者DSP里就只做乘加运算每个点几十个指令周期就能完成。启动阶段按前面说的等待足够长时间让滤波器状态收敛或者干脆丢弃前面的一段数据。这里还有一个容易忽略的点滤波器系数的量化。如果用定点DSPIIR滤波器的反馈系数非常接近1量化误差可能让极点在单位圆上轻微偏移导致滤波器不稳定或者截止频率偏移。我踩过一次用16位定点实现0.1Hz高通滤波器的坑滤波器直接振荡了。后来换用浮点或者提高定点字长问题才解决。5.3 最后分享一个我自己踩过的坑有一年做桥梁振动监测传感器采出来的信号里除了振动还叠加了一个很明显的温度漂移趋势。我一开始图省事直接在时域把整段数据做了均值相减结果频谱图上低频段还是有一大片隆起的能量温度漂移的趋势只消掉了一半。换成0.5Hz高通滤波之后低频段确实干净了但问题又来了桥梁的基频是0.8Hz和0.5Hz的截止频率靠得太近滤波之后基频幅值衰减了模态分析结果对不上了。后来我才意识到这类工程问题最忌讳的就是“一把尺子量到底”。温度漂移的特点是变化缓慢、近似线性、持续整个采集过程用分段线性去趋势来处理最合适。把采集时长切成一分钟一段每段做一个线性拟合减掉趋势线再接回去。这样桥梁0.8Hz的振动信息完整保留温度趋势也被抹掉了。处理完再和同步采集的温度数据对比趋势线基本和温度曲线形状一致验证了这个方法选型是合理的。所以你看去直流这件事真不是“一行代码”那么轻飘飘。它背后是对信号成分的理解、对处理手段边界的判断。均值相减、高通滤波、滑动基线这三种方法我至今都在用但每次用之前都会先问一句这段数据的直流到底是恒定的、是慢漂移的还是和有效低频信号纠缠在一起的把这个问题想清楚方案自然就出来了。本文还有配套的精品资源点击获取
返回列表