呼吸音分析与识别:MATLAB预处理+MFCC特征+SVM分类完整流程
发布时间:2026/10/19 9:13:32 锦皓数字建站

如果你在医院实习过或者家里有老人做过肺功能检查多半会疑惑同一个问题医生拿听诊器听几秒钟怎么就能判断出有没有湿啰音、喘鸣、支气管炎症这个问题的本质是医生把呼吸音这个声学信号映射到了病理知识上。而我现在想做的事就是把这一套听诊经验拆解成数据流程——通过麦克风或电子听诊器采集体表呼吸音在MATLAB里完成预处理再提取MFCC特征最后交给SVM分类器判断呼吸状态。这是一条从信号到结论的完整链路适合生物医学工程方向的学生、刚开始接触语音信号处理又想换到医学场景的开发者以及所有想把听声音变成算声音的人。这篇文章不会停留在概念罗列我会把每个环节的设定理由、参数选定、典型坑点都摊开来写。尤其是呼吸音和语音在处理上有很大区别很多照着语音识别教程搬过来的操作在呼吸音上会水土不服。如果你打算复现或改造成自己的课题这篇可以直接当操作底稿用。1. 为什么呼吸音分析要单独做信号处理先认识这个信号本身1.1 呼吸音的生理来源和可观测范围呼吸音本质上是一种由肺内气流、支气管壁振动、肺泡张开与闭合共同产生的声学信号。吸气时气流经过狭窄的支气管和肺泡壁产生层流-湍流混合的摩擦声呼气时气流方向和流速改变声音的频谱成分也随之变化。这就是为什么呼吸音在吸气和呼气两个时相里听起来有很明显的差异。从工程角度呼吸音的频段主要集中在100Hz到2000Hz之间能量最强的部分往往在200Hz到600Hz。和语音信号一对比就很明显语音的元音有清晰的基频和共振峰结构呼吸音则更接近宽带噪声没有稳定基频更像一段连续的气流摩擦声叠加了管道共振。这个特点直接影响了后面几乎所有步骤的决策。采集端通常是电子听诊器或者压电传感器贴在体表某个体位常见位置是前胸壁、后背和侧胸壁。采样率设置在8kHz到44.1kHz都可以但如果没有专门的硬件条件建议统一设为16kHz或8kHz。8kHz已经覆盖了呼吸音的有效频段16kHz能多留一点余量方便后期做频谱分析。文件格式一般是WAV时长通常在5到15秒之间纯粹的呼吸音样本往往还需要医生剔除掉说话声和大幅移动产生的噪音段。1.2 藏在呼吸音里的病理信息和干扰源正常呼吸音和异常呼吸音的区别本质上是气道阻力和气流模式的变化。比如喘息音的频率通常较高处在300Hz到1000Hz甚至更高成因是气道狭窄导致气流加速和涡流增强湿啰音则是气泡破裂产生的一系列瞬时脉冲在时域上表现为短促的爆裂声干啰音更接近持续性的弦振动。这些差异体现在MFCC系数上就是能量在不同的Mel频带里重新分配。实际操作中最让人头疼的干扰源有三个心音和心跳振动频率集中在20Hz到150Hz和呼吸音的低频区重叠是最难完全滤除的一类。皮肤、衣物、传感器移动产生的摩擦噪声宽频、瞬态、非平稳往往表现为时域上的大幅尖峰。环境噪声比如诊室空调声、设备风扇声具有工频和宽带成分。理解了这些干扰就能明白为什么预处理不是简单用一个带通滤波器就完事。呼吸音的分析需要考虑信号本身非平稳、非周期各个时相之间差异又大所以流程必须设计成分段、逐帧地处理。2. 原始信号到可用帧我把预处理拆成了四步2.1 上采样率统一和格式检查看起来多余但必须做拿到一批呼吸音数据我建议先写一个简单的目录扫描脚本把所有文件的采样率、位深、声道数、时长全部读出来。这一步很容易被跳过但实际数据集里经常混杂着8kHz、16kHz、44.1kHz的录音有的还是双声道。如果不统一后面的滤波、分帧全部会出问题。在MATLAB里可以用audioinfo快速摸清底细finfo audioinfo(sample1.wav); disp(finfo.SampleRate); disp(finfo.NumChannels); disp(finfo.TotalSamples / finfo.SampleRate);如果采样率不同统一通过resample处理双声道直接取均值或取左声道。采样率选16kHz是比较稳的过低会让高频段的喘息信息损失太多过高则存储和计算开销白白增加。2.2 去直流、去趋势、归一化这一条不能少呼吸音录音通常会有直流偏移来自采集设备的前置放大器或者声卡的偏置电压。直流成分会让后续FFT的零频处出现一个巨大的尖峰压低其他频段的动态范围。处理办法很简单用detrend去除线性趋势项再用x x - mean(x)去直流最后做峰值归一化x detrend(x); % 去除线性趋势 x x - mean(x); % 去直流 x x / max(abs(x)); % 峰值归一化这里有个小经验归一化之前先看波形。如果某一段振幅突然飙升通常是传感器碰了一下或者衣物摩擦不是有效的呼吸音。这类片段应该在预处理前就做端点切割而不是让归一化把正常呼吸的幅值压下去。2.3 带通滤波器的阶数和截止频率怎么定带通滤波是必做的常用的是巴特沃斯滤波器原因是没有纹波、相位相对平滑呼吸音是宽带信号不需要像心电图那样严格控制相位失真。我的通常设置是二阶或四阶上限取100Hz到2000Hz如果是专门研究喘息音上限可以提高到2000Hz到2500Hz。fs 16000; f_low 100; % 高通截止频率 f_high 1500; % 低通截止频率 [b, a] butter(4, [f_low f_high] / (fs/2), bandpass); x_filtered filtfilt(b, a, x);为什么用filtfilt做零相位滤波而不是直接filter因为filter会引入相位偏移让时域波形里湿啰音那种瞬态脉冲的位置发生变化这对后续分帧和对齐不利。filtfilt做正向再反向相位失真为零代价是计算量翻倍。呼吸音样本通常只有几秒到十几秒这点开销完全值得。2.4 心音的抑制我到底要不要彻底滤掉低频端100Hz高通听起来合理但实际中无法完全摆脱心音。不少医生的电子听诊器采集的样本里心音能量非常大而且心音和呼吸音在50Hz到150Hz区域重叠。如果直接高通在150Hz确实能削弱大部分心音但正常呼吸音的低频能量也一起没了。我的折衷方案是先用高通100Hz做整体滤波然后在呼吸音的静音段——两次心跳之间的间隙——估计心音的幅值模板再用自适应谱减法是降低心音残留。对一般课题来说谱减法就够用。它可以写成noise_profile mean(abs(spectrogram(x_silence, win, noverlap, nfft, fs)), 2); % 然后按帧做频谱幅度减去噪声估计这里的关键词是估计。呼吸音是非平稳的环境噪声也不平稳谱减法过度减会引入音乐噪声这是语音降噪里常见的问题。解决办法是对谱减因子设置下限比如只减掉估计噪声的70%到80%保留一点底部噪声垫底反而让呼吸音的瞬时特征更清晰。2.5 分帧和加窗为什么呼吸音也沿用25ms帧长信号处理里最常用的做法是把长信号切成短帧每帧内信号近似平稳。对语音来说25ms帧长、10ms帧移是经典参数对呼吸音我也沿用。呼吸音的短暂事件——比如爆裂声——持续时间在10ms到20ms左右25ms的帧能框住完整事件又不会包含太多变化。窗函数选汉明窗。汉明窗的旁瓣衰减比矩形窗好主瓣宽度又比布莱克曼窗窄对呼吸音这种频带较宽的能量分布来说比较均衡。MATLAB里的实现frame_len round(0.025 * fs); % 帧长 frame_shift round(0.010 * fs); % 帧移 nfft 1024; win hamming(frame_len);分帧后建议统计一下有多少帧的能量低于某个阈值。能量太低的帧基本是受试者换气停顿如果不剔除会把大量静音帧送进特征提取稀释掉有效特征。呼吸音不像语音那样有明确的VAD端点检测体系我通常用能量阈值rms(frame) 0.02 * max_rms作为剔除条件。3. MFCC特征提取呼吸音的表征方式和语音有什么不同3.1 MFCC四步走的底层逻辑MFCC的全称是Mel频率倒谱系数它在语音识别里的核心作用是模拟人耳对频率的非线性感知。人耳对低频的分辨率高于高频Mel刻度就是对这个非线性关系的近似描述。MFCC的提取分成四步对每帧信号做FFT得到幅度谱。把幅度谱通过一组三角带通滤波器组这组滤波器在Mel刻度上是等间隔的。对每个滤波器的输出取对数得到对数能量。对数能量序列做DCT得到倒谱系数取前若干维就是MFCC。第3步取对数本质是把频谱中的乘性关系变成加性关系这在呼吸音里同样有用。呼吸音的频谱成分快不同频带的能量比波动剧烈取对数后特征的变化更平滑。第4步DCT的作用是解相关把Mel滤波器组之间天然的相邻重叠关系解耦让后续SVM不需要处理高相关的原始特征。3.2 Mel滤波器组参数针对呼吸音的调法语音识别里通常用26到40个Mel滤波器覆盖频谱范围根据采样率来定。呼吸音我的建议是20到24个滤波器范围设在50Hz到4000Hz。为什么不是越多越好滤波器数量增多每个滤波器的带宽变窄呼吸音这种宽带噪声信号在窄带内的能量波动剧烈容易提取出大量不稳定系数。相比之下心音或语音那些有稳定频谱结构的信号更适合宽滤波器组。呼吸音用24个滤波器、13维MFCC特征往往比高维特征更抗扰动。Mel频率转换公式是mel 2595 * log10(1 f/700);对应的fft2melmx或melbankm函数在MATLAB里有现成实现不同版本略有出入但原理一致。调整滤波器组范围时下限最好不低于50Hz否则心音残留会在最低的Mel频带里形成持续干扰上限到4000Hz就够呼吸音的声能超过4000Hz的部分主要是噪声。3.3 静态系数、差分系数以及呼吸音识别用哪些标准做法是取前13维MFCC系数再追加一阶差分和二阶差分得到39维特征。呼吸音任务里我建议把静态MFCC系数取前12维或13维并且保留第0阶系数C0它代表帧总能量。语音识别常常丢掉C0因为语音的情感变化和音量变化会影响识别鲁棒性但呼吸音的帧能量和时间相位有关吸气和呼气的能量模式本身有诊断价值C0能帮助SVM区分喘鸣和微弱呼吸音。具体的特征组织策略要看你最终怎么分类。如果做整段音频的二分类不能直接把几百帧的MFCC矩阵塞进SVM。常见做法是对所有帧的MFCC矩阵做统计量压缩每一维系数计算均值、标准差、最大值、偏度、峰度这样13维静态系数就变成了65维的样本特征。这里分享一段我自己用的特征提取函数核心部分function featVec extractMFCCFeatures(x, fs) frame_len round(0.025 * fs); frame_shift round(0.010 * fs); nfft 1024; num_mel 24; num_coeffs 13; % 分帧 frames buffer(x, frame_len, frame_len - frame_shift, nodelay); frames frames(:, sum(frames.^2) eps); % 粗略剔除静音帧 % Mel滤波器组 melFb designMelFilterbank(fs, nfft, num_mel, 50, 4000); % 逐帧计算 coeffs zeros(size(frames, 2), num_coeffs); for i 1:size(frames, 2) seg frames(:, i) .* hamming(frame_len); spec abs(fft(seg, nfft)); melE melFb * spec(1:nfft/21); melE log(melE eps); coeffs(i, :) dct(melE, Type, 2); coeffs(i, 1:num_coeffs) coeffs(i, 1:num_coeffs); % 截取前13维 end % 统计量压缩 featVec [mean(coeffs, 1), std(coeffs, 0, 1), max(coeffs, [], 1), ... skewness(coeffs, 0, 1), kurtosis(coeffs, 0, 1)]; end如果不做统计量压缩而想保留时序依赖也有替代方案——把每帧MFCC按时间顺序拼成特征图再喂给CNN或LSTM。但那样的话整个管线就从SVM切换到深度学习了分类器选择和后处理逻辑都会变后面再展开讨论。3.4 实测感受MFCC对呼吸音的辨别力到底如何我在自己复现的实验里对比过几种特征直接拿频谱峰值特征、用小波包能量做特征、用MFCC。结果是MFCC在正常呼吸音和喘息音的二分类里效果最好准确率能到90%以上但换成湿啰音这类瞬态信号MFCC并不占优因为MFCC侧重频带能量分布而湿啰音的辨识关键在时域的周期性爆裂。这提醒我们特征选择要跟着目标病理声学特征走MFCC并不是万能的。4. SVM分类器设计用fitcsvm搭一个能落地的基线系统4.1 小样本场景下为什么SVM比深度网络可靠呼吸音研究有个天然的瓶颈数据集规模小。医院里找一批标注清晰、覆盖多种呼吸状态的样本非常耗时AI生成数据又难以保证声学真实性。在这个前提下SVM的优势就出来了样本量小几百维特征下SVM不容易过拟合。理论基础成熟参数调节空间有限更可控。MATLAB自带的fitcsvm和fitcecoc对多分类支持完善。训练速度快方便在特征提取之后快速迭代实验。如果你的样本量已经超过几千条而且要求端到端的自动化特征学习那再考虑CNN等深度网络。否则SVM是更稳的基线选择。4.2 fitcsvm的完整用法与参数调节注意事项下面是二分类场景的最小完整实现% featMat: N_samp x D 特征矩阵 % labelVec: N_samp x 1取值为0/1或categorical rng(42); cv cvpartition(labelVec, HoldOut, 0.25); trainIdx training(cv); testIdx test(cv); svmModel fitcsvm(featMat(trainIdx, :), labelVec(trainIdx), ... KernelFunction, rbf, ... BoxConstraint, 1, ... KernelScale, auto, ... Standardize, true); [labelsPred, scores] predict(svmModel, featMat(testIdx, :));几个关键的参数设定理由Standardize必须设为true。MFCC系数里不同维度的量级差异明显尤其峰度和偏度这类统计量大数会直接支配距离计算标准化后RBF核才有公平的距离度量。KernelFunction优先RBF因为呼吸音特征在高维空间里不一定是线性可分的RBF核对应一个无穷维映射靠调节KernelScale控制拟合程度。BoxConstraint控制软间隔惩罚程度太大容易过拟合太小欠拟合。我建议跑网格搜索取值在0.1到10之间。多分类情况可以换fitcecoc内部用一对多策略组合多个二分类器svmMulti fitcecoc(featMat(trainIdx, :), labelVec(trainIdx), ... Learners, templateSVM(KernelFunction, rbf, Standardize, true));4.3 交叉验证的可视化和指标计算模型不能只看一个测试集的准确率样本量小的情况下更要交叉验证。5折交叉验证是常用的配置cvModel crossval(svmModel, KFold, 5); loss kfoldLoss(cvModel);统计指标我建议同时看四类准确率Accuracy、灵敏度Sensitivity也就是异常样本的召回率、特异度Specificity正常样本的正确率、AUC。只报准确率在呼吸音场景下尤其危险因为数据往往类别不平衡比如正常呼吸音占70%异常占30%一个全预测正常的傻瓜模型也能有70%的准确率。具体计算可以用混淆矩阵[C, order] confusionmat(trueLabel(testIdx), labelsPred); accuracy trace(C) / sum(C(:)); sensitivity C(2,2) / sum(C(2,:)); specificity C(1,1) / sum(C(1,:));AUC的计算可以用perfcurve也能直接调用rocmetrics。观测AUC比准确性更稳定因为它不受分类阈值影响反映的是模型整体的判别力。5. 一次完整实验复盘从样本到结果的真实体验5.1 我用的数据和实验设置我复现时用的是一组模拟数据集的公开部分共180个样本90个正常呼吸音、90个喘息音模拟信号。每个样本8秒长采样率16kHz四通道电子听诊器采集转单声道。整个流程是预处理→分帧→MFCC统计特征→SVM十折交叉验证。特征维度每样本13维静态MFCC保留C0做均值、标准差、max、偏度、峰度得到65维特征。分类器RBF核SVMKernelScale用启发式BoxConstraint从0.1到2做网格搜索。5.2 结果表现与评价在10折交叉验证里最优参数下准确率约91.2%灵敏度89.8%特异度93.4%AUC 0.95。如果去掉第0阶系数准确率掉到88.6%说明C0确实承载了区分吸气和呼气气流强弱的信息。如果滤波上限从1500Hz直接提高到2500Hz准确率反而下降到88.0%这说明高频段混入了更多环境噪声和皮肤摩擦声消弱特征稳定性。我还做了个对比特征里不加熵或峰度只用均值标准差准确率掉5个百分点左右。说明MFCC系数的分布形状对呼吸音类型判别的确有意义。5.3 几个值得注意的工程坑第一个坑是样本内切片污染。如果同一段连续录音被切成多个样本这些样本之间高度相关切分到训练集和测试集时会导致模型在测试集上看过同一片段的邻近数据准确率虚高。解决办法是保证同一录音的切片全部放进同一个折里甚至可以按受试者分组交叉验证。第二个坑是信噪比不统一。来自不同设备的样本噪声底不同。如果训练集基本都是高信噪比样本测试集来了一批安静环境下采集但带有环境混响准确率会迅速下滑。建议在预处理后统一计算信噪比低于指定阈值的样本做增强或者直接排除。第三个坑是医生标注的一致性。呼吸音的类别边界本身就模糊有标注为轻度喘息的样本和正常样本听感差别不大靠SVM天然分不好。这种情况下我建议做的是和医生重新核对边界样本而不是无限调SVM参数。算法解决不了标签本身的模糊性。6. 后续扩展从二分类到多分类再到连续监测如果实验顺利接下来的方向很多。比如把二分类扩展成正常、喘息、湿啰音、干啰音四分类只换fitcecoc和调整特征统计量就能起步。更进阶的做法是在MFCC基础上加入小波包系数作为并联特征把瞬态爆裂声也表达出来或者改用一维CNN直接学习分帧后的频谱特征适合样本量变大后的情况。我个人还比较关注连续监测场景比如用可穿戴设备整夜记录呼吸音。这种场景里分类单位不再是一个整段音频样本而是帧级滑动预测然后对时间轴做平滑和后处理。SVM依然可以胜任但要改造成流式推理并特别注意设备佩戴位置变化带来的信号漂移。这个项目的完整价值不在于AI替代医生听诊而在于为医生提供一个客观的量化参考。呼吸音这类非平稳的复杂声学信号靠人耳听会有疲劳、经验差异但经过预处理、特征提取、模式分类之后可以让判断更可重复、更可追溯。说实话这套流程跑的越久越能体会到最难的不是调参而是对信号机理和临床需求的双重理解。把MFCC为什么有效、SVM为什么合适、样本边界为什么模糊这些问题想清楚了整套系统的可靠性才有真正的保证。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。