尧图精选

LOFAR谱实战:从时频图到船舶目标分类的完整链路

🕒 发布时间:2026/9/16 2:07:46 📁 来源:尧图网络
做水声信号处理和船舶目标识别的时间久了基本都会撞上LOFAR谱这个名词。LOFAR全称Low Frequency Analysis and Recording低频分析记录谱名字听起来很学院派实际上就是把水听器收到的声信号做短时傅里叶变换画一张频率随时间变化的二维能量图。在MATLAB里这就是几行代码的事。但真正有意思的不是那张图本身而是图上那些横平竖直的亮线——线谱。这些线谱才是后续分类识别的关键“指纹”。本文我会把一个完整的处理链路从头到尾拆开讲先用MATLAB生成LOFAR谱然后对谱图做线谱增强接着从增强结果里提取特征最后把特征送去分类器完成目标分类识别。这套流程我实际用了很多次覆盖过仿真信号、湖试数据和海试数据。坦率说网上讲LOFAR谱定义的文章不少但讲“拿到一张不太干净的LOFAR谱之后具体怎么处理、怎么提取特征、怎么训练分类器”的要么藏在零碎的代码片段里要么只给个方向不给细节。这篇我把能直接抄作业的代码和踩坑记录一起放出来适合正在做水声信号处理、被动声呐目标识别、振动噪声分析或者课程大作业撞上类似题目的同学参考。1. 先搞清楚LOFAR谱一张图里的“低频指纹”1.1 什么是LOFAR谱又为什么能用于分类识别LOFAR谱本质上是一个时频分布。把一段信号切成若干带重叠的时间窗对每个窗做FFT再把所有窗的频谱按时间顺序拼接起来就得到一张二维图横轴是时间纵轴是频率颜色深浅代表该频点在该时刻的能量大小。这里说的“低频”其实是个相对概念在水声场景里通常关心几赫兹到几千赫兹的频段被动声呐处理的目标辐射噪声大量能量都落在这个范围内。为什么LOFAR谱能用于分类识别因为它把“频谱随时间的变化”这个信息完整展现出来了。不同的目标机械结构不同它们的噪声谱形态就不一样——有人是一串间隔均匀的谐波线有人是在连续谱上零星立着几根独立谱线有人则只有低频段有一个宽包。这些差异光看某一段频谱或者某一个功率谱均值很难稳定捕捉但在LOFAR谱上线谱的“空间位置”和“时间连续性”都会直接变成肉眼可见的模式差异。分类识别的第一步其实就是把这些模式差异变成可量化的特征。1.2 线谱从哪里来机械噪声中的谐波成分说清楚线谱的来源才能理解后面为什么做增强、提取什么特征。船上的发动机、辅机、螺旋桨、减速齿轮箱等旋转和往复部件在运转时会产生周期性的机械力激发水下声辐射。这种周期力对应的声信号在频域上表现为集中在若干离散频率上的窄带分量画在LOFAR谱上就是一条条水平亮线。线谱频率之间有很强的规律性。螺旋桨轴频、叶频轴频乘以叶片数和谐波组合是最常见的结构柴油机的点火频率也带有明显的基频和谐波。这些频率只要目标工况稳定就能持续数分钟甚至更久所以我做线谱追踪时经常把“时间连续性”和“频率间谐波关系”两个条件一起用作为剔除虚假线和确认目标身份的双重依据。这也决定了后面的特征提取面对的不是一个孤零零的峰值而是一组有结构关系的谱线集合。1.3 MATLAB里生成LOFAR谱的最简流程我不太喜欢一上来就甩几十行配置复杂的脚本。生成LOFAR谱核心就一个spectrogram调用。下面这段代码用的是仿真数据一阵宽带随机噪声作为背景叠加两组合有基频和谐波的线谱分量模拟两个不同目标。close all; clear; clc; fs 20000; % 采样率按实际采集设备设定 N fs * 60; % 60秒数据 t (0:N-1) / fs; % 宽带背景噪声 x 0.7 * randn(1, N); % 目标1基频23.5Hz及二、三次谐波 for ff [23.5, 47.0, 70.5] x x 0.5 * sin(2*pi*ff*t rand*2*pi); end % 目标2基频17.2Hz及二、三次谐波 for ff [17.2, 34.4, 51.6] x x 0.35 * sin(2*pi*ff*t rand*2*pi); end % 生成LOFAR谱 winLen 2048; hop winLen / 2; win hann(winLen, periodic); [S, F, T, P] spectrogram(x, win, hop, winLen, fs); % 绘制 figure; imagesc(T, F, 10*log10(P eps)); axis xy; xlabel(时间 (s)); ylabel(频率 (Hz)); title(仿真信号的LOFAR谱); colorbar; ylim([0 200]);窗长选择这里多说一句。窗口越长频谱频率分辨率越高但时间分辨率会变差。2048点配合20kHz采样率频率分辨率是fs / winLen约为9.8Hz往低看100Hz以内的线谱还能勉强分开但两根靠得很近的线谱比如23.5Hz和23.8Hz就完全糊在一起了。真要分辨得更细就得把窗长拉长到4096甚至8192点同时接受时间分辨率下降的代价。工程上我会先看目标线谱的最小间距是多少再倒推窗长而不是图省事直接用默认参数。重叠比例同样影响最终效果。我习惯用50%重叠也就是hop取winLen的一半这样计算量适中时间轴也够细腻。如果希望时间上更平滑可以加到75%重叠代价是计算耗时明显增加对离线分析无所谓但实时处理时要权衡。2. 线谱增强从“噪声里找线”到“把线变亮”2.1 为什么原始LOFAR谱不能直接用干扰源拆解仿真信号想得很美但实测数据远没有这么干净。拿拖曳阵、舷侧阵或者单水听器接到的信号来说主要干扰有这么几类一是海洋环境噪声风浪、降雨、生物活动都会产生宽频能量让整个LOFAR谱的底色忽明忽暗二是远处航船宽带噪声这类干扰在低频段可能压过目标的最强线谱而且是时变的三是目标自身信号的非平稳性目标加减速或转向时线谱频率会缓慢漂移不是教科书里那种笔直的横线。如果拿着这样的原始谱直接做特征提取你会发现峰值检出来的全是干扰。我在第一次处理一段湖试数据时就被环境噪声的起伏坑过——一个低频段的宽带包络强度变化能超过10dB把几条真实线谱全部淹没。后来才老老实实把“增强”环节放到特征提取之前这也是这套方法流程里“线谱增强”存在的意义抑制起伏背景把稳定、连续、有结构的窄带分量突出出来让后续算法聚焦在真正代表目标的成分上。2.2 预处理归一化、去均值和动态范围压缩增强之前先做三个预处理步骤。把功率谱统一转到对数域也就是dB单位。人眼和阈值算法对dB的变化都比线性幅度更敏感而且后续处理几乎都基于对数谱做更稳定。对每个频点沿时间方向减中值消除设备响应和信道起伏带来的缓变偏差。这一步相当于把整个谱图的“地板”抹平不然低频隆起很容易干扰后面的形态学操作。锁定分析频带。并不是整幅图都要处理几百赫兹以上多数情况下线谱稀疏且淹没程度高先把频带限定在关注范围能省掉大量误检。% 假设P是spectrogram输出的功率谱单位是线性幅度平方 Plog 10 * log10(P eps); % 转为dB Plog Plog - mean(Plog, 2); % 逐频率点去掉时间均值抑制缓变背景 fBand F 200; % 关注0~200Hz频带 Pband Plog(fBand, :); Fband F(fBand);这里的mean(Plog, 2)是对每个频点在所有时间帧上取平均。做完这一步整个LOFAR谱的背景会明显平整线谱保持原样后续增强算法的收敛速度会快很多。2.3 三种常用线谱增强方法对比我说“常用”是因为实测里这三类方法我都用过各有各的适用场景不存在哪个绝对最好。方法核心思想优点缺点适用场景频域中值滤波沿时间轴用中值替代原值时变的宽带成分被压平实现简单、运算快、稳定抑制宽带突变对频率缓慢漂移的长线谱改善有限目标匀速直航、线谱频率基本不变时形态学顶帽变换用结构元素提取谱图中凸起的亮目标扣除背景对起伏背景抑制强能保留局部细节结构元素尺寸需要调选不好会破坏弱线谱背景起伏明显、线谱强度不一的海试数据自适应线谱增强器用自适应滤波器从时域信号里直接跟踪窄带分量能跟踪频率漂移输出时域窄带分量参数敏感多线谱时通道间可能互相干扰目标变速变向、线谱漂移明显的场景下面逐一展开。2.3.1 频域中值滤波最简单却最稳中值滤波的思路特别直白对一个频率点取它前后若干帧的值排个序取中间值作为该时刻的估计。宽带噪声能量随时间起伏剧烈但排序后取中值天然会把极端值剔除掉所以中值结果近似反映“该频点的背景水平”。原始谱减掉这个背景线谱就凸显了。MATLAB里我用循环逐频点处理代码简洁而且内存占用小winLenMed 21; % 中值窗长单位是帧数 Pmed zeros(size(Pband)); for k 1:size(Pband, 1) Pmed(k, :) medfilt1(Pband(k, :), winLenMed); end % 原始谱减背景得到增强后的线谱部分 Penh1 Pband - Pmed;窗长的选择要留意窗太短背景估计不稳健窗太长会把真实线谱的慢变趋势当成背景减掉。仿真里线谱频率不变时21帧的中值窗很稳实测海试数据我会放到31~51帧因为环境背景的起伏周期更长需要更大的窗口才能把背景和中值对齐。注意medfilt1是Signal Processing Toolbox里的函数没装这个工具箱的话用movmedian也能实现同样效果。2.3.2 形态学顶帽变换处理起伏背景的利器如果中值滤波做完背景还是起伏就要上形态学了。形态学顶帽变换的基本操作是先用一个结构元素对图像做开运算先腐蚀后膨胀估计出背景再用原图减掉这个背景估计剩下的就是比邻近区域更亮的“凸起”部分。在LOFAR谱上结构元素的形状就决定了你期望提取的线谱“长什么样”——一条水平亮线所以结构元素用水平线形最合理。% 先对中值滤波后的谱再做一次顶帽变换 se strel(line, 15, 0); % 水平方向15个像素的结构元素 Ptophat imtophat(Pmed, se); % 可以根据顶帽结果和原始谱联合判定候选线谱 candidateMask (Ptophat - Pmed) 3; % 阈值需要根据数据统计调整注意imtophat处理的是二维图像矩阵行是频率列是时间。strel(line, 15, 0)在矩阵里就是沿列方向的一段水平线对应时间方向正好和线谱的“时间连续性”匹配。如果某个场合线谱有明显斜率例如目标大幅度变速结构元素的长度要缩短或者加一点角度倾斜否则它会把斜线谱当成背景抹掉。这个细节我后来处理变速目标时反复调过。同时要确认Image Processing Toolbox已经安装否则imtophat和strel这两个函数会直接报错。2.3.3 自适应线谱增强器ALE追踪非平稳单频分量中值滤波和形态学处理都是基于已经算好的谱图属于“事后增强”。ALE则是在时域做自适应滤波直接用原始信号跟踪窄带分量。ALE基本结构是把信号延迟若干样本当作参考输入用LMS更新的自适应滤波器逼近一个“窄带预测器”输出就是被增强的窄带信号。下面是一个简化的ALE循环实现适合作为理解和调试的起点delay 16; % 延迟量通常设为几个到十几个样本 order 64; % 滤波器阶数 mu 0.001; % 步长越小越稳收敛越慢 w zeros(order, 1); x_ale zeros(size(x)); for n order delay 1 : length(x) xn x(n-delay : -1 : n-delay-order1); y w * xn; % 自适应滤波输出 e x(n) - y; % 误差信号 w w 2 * mu * e * xn; % LMS系数更新 x_ale(n) y; endALE的延迟量值得专门说。延迟若太小参考输入和期望信号的相关性还很高自适应滤波器会把宽频成分也预测出来延迟若太大窄带分量本身的相关性也被削弱增强效果变差。实际使用时要对着输出频谱调几次取一个“宽带噪声已经基本不相关、窄带分量依然高度相关”的折中值。ALE对单根强线谱的追踪能力很强但多线谱场景下各路窄带分量互相干扰建议先带通滤波分成几个子带再做ALE否则结果很难控制。2.4 增强效果怎么评估增强做得好不好不能只靠眼睛看“图更干净了”还得量化。我会用三个指标一是线谱所在频点的信噪比改善量公式上可以取增强前后线谱幅度与邻近底噪均值的差一般要求提升3~6dB才认为增强有效二是线谱时间连续性即一个候选频率在多少比例的帧里被检到真实线谱通常能在60%以上帧持续出现虚假点往往断断续续三是新增虚假线谱数量增强算法如果引入大量虚假峰反而会恶化特征提取这个我在调试形态学结构元素尺寸时深有体会——结构元素太短背景压不干净虚假峰丛生结构元素太长弱线谱又被抹掉。这里给一条个人经验增强算法的参数最好不要针对单条数据反复调到完美而是固定一套参数后跑一批数据看统计表现。否则模型很容易“过拟合”到某一段信号上换一段数据就崩。3. 特征提取把“增强后的谱图”变成“分类器能用的向量”3.1 特征设计的前后逻辑先想清楚分类依据很多同学拿到谱图就直接铺特征其实第一步应该想清楚你凭什么判它是A船而不是B船答案往往是线谱的“位置”“数量”“关系”。我习惯于从分类需求倒推特征比如要区分大船小船就要抓住低频强线谱和基频范围要区分不同螺旋桨类型就要关注谐波组的间隔关系。特征设计一定要跟最终的分类问题绑定而不是把能算的都算一遍。这套思路落实到工程上就是先做一轮特征初选跑一次分类器再看混淆矩阵。如果两个类别总是互相认错就去对比它们的LOFAR增强谱找出人眼能区分但当前特征没表达出来的差异再针对性补特征。这种“特征-错误-改特征”的迭代比一次性堆几百维特征再指望PCA更可控。3.2 线谱级特征频率、强度、稳定度线谱级特征基于单根线谱本身最常用的有三个线谱频率值即峰值所在频率。不同目标轴频、叶频差异明显这是最直接的特征。线谱强度用峰值幅度相对背景底噪的差值注意要使用增强前的原始谱估值否则特征会因增强处理失真。线谱稳定度候选频点在全部时间帧中出现的比例反映线谱的持续性好坏。这三个特征组合在一起已经能区分很多工况差异。比如两个目标的基频接近但一个线谱强度高且稳定另一个强度弱且时断时续分类器就能用稳定度特征把它们分开。我建议提取的时候把这些值按“最强线谱”“次强线谱”排序整理而不是按频率从小到大排这样特征向量的顺序在不同样本间更一致分类器学起来更容易。3.3 谐波结构特征基频与谐波簇线谱很少孤立存在多数目标会有一串等间隔谐波。基频估计常见方法是对候选频率集合做整数倍匹配对每个候选频率f统计在2f、3f、4f附近存在其他候选峰的个数匹配数量最多的f就是最可能的基频匹配出来的整串频率就是一个谐波簇。% 在stableFreqs候选频率里找基频统计每个频率整数倍上的峰值数 score zeros(size(stableFreqs)); for k 1:numel(stableFreqs) f0 stableFreqs(k); for h 2:5 if any(abs(stableFreqs - h*f0) 1.5) score(k) score(k) 1; end end end [~, bestIdx] max(score); bestBase stableFreqs(bestIdx);得到基频和谱结构之后可以衍生一组特征基频值、谐波个数、谐波间隔的一致性比如各谐波频率相对基频的整数倍偏移标准差。相比单根线谱特征这类结构化特征对工况变化的鲁棒性更好也是分类器最喜欢用的区分维度。实际测试里加入谐波关系特征后KNN分类准确率能提高不少原因是它把几十个孤立频率点变成了一个有组织的“指纹”。3.4 用MATLAB把特征工程落地特征提取的核心操作是寻峰和统计我直接用findpeaks处理增强后的每一帧再做时域聚合。% 从增强谱Penh1和频率轴Fband中提取候选线谱频率 thresh 3; % 峰值高度阈值需要根据增强后数据分布调整 allFreq []; allAmp []; for col 1:size(Penh1, 2) [pks, locs] findpeaks(Penh1(:, col), Fband, ... MinPeakHeight, thresh, MinPeakDistance, 5); allFreq [allFreq; locs(:)]; allAmp [allAmp; pks(:)]; end % 统计频率出现次数得到稳定线谱 freqRound round(allFreq * 10) / 10; % 量化到0.1Hz网格 [G, freqID] findgroups(freqRound); cnt splitapply(numel, freqRound, G); stableIdx cnt 0.4 * size(Penh1, 2); % 在超过40%的帧中出现 stableFreqs freqID(stableIdx); stableCnt cnt(stableIdx);这里量化到0.1Hz是怕频率估计精度不够导致同一根线谱被统计成多个频率。如果谱图频率分辨率粗也可以放宽到0.5Hz的网格具体看你的FFT分辨率。聚合完之后stableFreqs就是候选线谱频率后面的谐波分析就可以在这个集合上做了。findpeaks同样依赖Signal Processing Toolbox单位注意是频率值Hz不是FFT下标。3.5 特征归一化与维度评估特征向量拼好后不能直接丢给分类器。频率特征和幅度特征量纲不同幅度特征范围差异很大需要先做z-score标准化减去均值除以标准差。我不建议直接调zscore函数糊弄过去因为标准化参数必须严格从训练集计算然后套用到测试集否则会有数据泄漏。mu_feat mean(featuresTrain, 1); sd_feat std(featuresTrain, 0, 1); featuresTrainStd (featuresTrain - mu_feat) ./ sd_feat; featuresTestStd (featuresTest - mu_feat) ./ sd_feat;顺便提醒一句如果做了PCA降维别用全部数据统一fit要用训练集fit后再transform测试集否则同样会引入数据泄漏测试结果看起来很好一上真实场景就露馅。这是很多初学者容易踩的坑。特征维度上我的原则是先用分类准确率和特征重要度筛选一遍保留区分度高的十几维特征而不是一次性塞几十维进去。4. 分类识别全流程一个可以直接套用的MATLAB示例4.1 整体流程设计与数据组织有了增强和特征提取的方法分类识别链路其实很清晰原始信号→LOFAR谱→线谱增强→特征提取→特征标准化→分类器训练/预测。我一般把每个目标的信号切成长度为几十秒的片段每段生成一个特征向量一个目标攒几十个样本。数据组织上用两个变量features是N×M的特征矩阵labels是N×1的分类标签用整数1、2、3标识不同目标类别。这样后面调用任何分类器API都不需要再折腾。实际工程里数据切片的长度要和线谱稳定性匹配。切片太短比如5秒有些低频线谱还没积累到足够帧稳定度特征就失真切片太长比如5分钟数据样本数太少且目标工况可能发生变化。我常用的方案是每段30秒配合2秒一帧的LOFAR窗口每段能产生15帧左右统计稳定度时已经有点意义。如果信号长就用滑窗截取多段窗口重叠控制在50%左右。4.2 特征向量传统分类器KNN/SVM的完整示例下面这段代码给出了从特征矩阵到分类评估的最短路径。KNN作为基线分类器不需要训练阶段调太多参数很适合先看特征有没有区分度。% features: N个样本×M维特征labels: N×1类别标签 rng(2024); cv cvpartition(labels, HoldOut, 0.3); trainIdx training(cv); testIdx test(cv); mdl fitcknn(features(trainIdx, :), labels(trainIdx), ... NumNeighbors, 5, Standardize, true); pred predict(mdl, features(testIdx, :)); acc sum(pred labels(testIdx)) / numel(pred); fprintf(KNN分类准确率: %.2f%%\n, acc * 100); % 混淆矩阵看哪些类别容易混淆 confMat confusionmat(labels(testIdx), pred); disp(confMat);如果KNN准确率已经很高说明特征空间里不同类别本身分得开工程交付就够用了如果准确率平平再换成SVM或者随机森林试试。SVM用fitcecoc做多分类随机森林用TreeBagger两者在中小样本场景下都比KNN更稳代价是超参数要调。调参时有个小技巧先用默认参数跑一遍拿到基线准确率再对最敏感的一两个参数做网格搜索不要一上来就贝叶斯优化否则容易把时间花在随机波动上。4.3 数据不足时的处理与简单数据增强被动声呐目标识别的老大难是样本少。实测目标不可能像公共数据集那样给你几百上千个样本往往一个目标只有几十分钟录音。我的做法是先切片段每20~30秒一段60分钟数据能切100个以上的样本数量已经够传统分类器用了。还不够的话再做三种数据增强加不同强度的随机噪声、对整段信号做几赫兹的频移模拟目标速度差异、截取不同起始位置的时间片段。这三种操作都保持了线谱的基本结构扩展出来的样本能明显提升分类器泛化能力同时也不至于造出违背物理规律的假数据。频移操作特别适合模拟不同航速下的目标。对原始信号乘以一个复指数频域上所有分量整体平移几赫兹线谱的谐波关系保持不变但基频值变了。加多少频移量可以参考目标速度变化引起的多普勒范围一般几赫兹到十几赫兹。加噪声则要控制幅度最好不要超过原信号能量的30%否则增强后的LOFAR虚假峰太多反而干扰训练。4.4 扩展到深度学习的思路特征工程做扎实之后如果想进一步用深度学习思路也很顺把增强后的LOFAR谱保存成灰度图或伪彩图用CNN直接学习时频图上的模式。MATLAB的Deep Learning Toolbox提供了imageInputLayer和卷积层、全连接层代码写得快。但深度方案对数据量要求高小样本场景建议用预训练网络做迁移学习而不是从零训练。迁移学习的具体做法是把预训练网络比如GoogLeNet、ResNet的全连接层替换成适应目标数量的新层然后用少量LOFAR图微调。LOFAR图虽然和自然图像差异很大但预训练网络底层学到的边缘、纹理检测器对时频图也有用。输入图像建议用3通道伪彩图把增强谱用不同colormap映射成RGB比单通道灰度图更容易体现细节。深度模型的输入是二维谱图输出是类别标签中间不假设任何人工特征但也意味着可解释性差出了问题很难定位是增强环节、训练环节还是数据标注的问题——这点在做工程交付时要想清楚再选路线。5. 常见问题与排查技巧实录5.1 问题速查表现象可能原因排查方向LOFAR谱上全是一条条细竖线FFT点数设置过小导致频率分辨率太低增大窗长到4096或8192点低频段整片亮、线谱看不清海洋环境低频背景强先做频带限制再增强线谱在时间上断断续续目标变速导致频率漂移用ALE或缩短中值窗口先跟踪再聚合增强后出现大量虚假谱线形态学结构元素尺寸不当加长结构元素或提高峰值阈值分类准确率高但现场回放效果差特征标准化时数据泄漏检查是否用全量数据fit过标准化器不同目标的特征在空间中混叠谐波结构特征缺失增加谐波匹配特征改用SVM/随机森林增强处理时间太长实时性差中值滤波和形态学处理循环多先降采样到2kHz只保留低频段再处理5.2 几条压箱底的工程经验第一线谱增强参数不要只在仿真数据上调。仿真信号干净、平稳参数随便选都好看但真实海试数据总有一堆“意外的脏”最好留一两条真实数据做参数校准哪怕只有几条也能暴露很多问题。第二特征数量宁少勿多。我见过有人一口气提了四五十维特征分类准确率反而比只用十几维时低。原因很简单小样本高维度会引入大量噪声维度分类器学到的是训练集上的特判。先做特征重要性分析保留区分度最高的那些维度比无脑堆特征有效得多。第三分析频带尽量贴合声学常识。低频线谱是分类识别的主战场不是频率越高越好高频率段宽带噪声大、线谱衰减快提取到的特征常常不具代表性。我通常把分析频带上限设在几百赫兹再往上除非有明确的齿轮啮合谐波需求否则不加。第四分类之前一定要看混淆矩阵。只看总准确率会掩盖问题比如A类全对、B类几乎全分到A类。混淆矩阵能告诉你哪些类别在声学特征上真的相似进而回头调整特征设计这个闭环迭代才是工程里真正花时间的部分。说实话LOFAR谱加线谱增强加特征提取这套组合放在今天不算新但它依然是很多被动声呐识别系统里最稳的地基。我个人做下来最大的体会是千万别急着上深度学习先把线谱增强和特征提取做扎实浅层分类器能解决的问题就不要让全连接层替你扛。后续如果要继续扩展可以考虑把DEMON谱调制谱和LOFAR谱联合起来一个看线谱结构一个看螺旋桨轴频调制互补性很强也可以在这套特征基础上引入多帧时序建模比如用LSTM建模线谱频率随时间的漂移轨迹。这些方向都是在现有流程上自然的延伸希望这篇讲透的方法能让你少走点弯路。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →