Task3 食物声音识别之音频数据特征提取
1 特征提取背景
在Task2中,我们已经了解了我们需要识别的音频的样本数据的声学特征,采用ipython的库和librosa库播放并可视化了音频在幅度和声谱上的图形化特性。那么下一步就是要对这些音频文件进行处理,去掉噪声干扰,保留可以代表音频类别信息的特征。
那么该提取哪些特征呢?这还要回到Task2里分析的音频的物理特性1:
- 能量特征,主要是幅度代表的波形包络
- 时域特征,主要是相位特性所代表的物理解释,例如起音阶段,过零率,自相关
- 频域特征,
2 常见音频提取
2.1 加载库
在Task1中已经介绍过下述库的基本用途
import numpy as np
import sklearn
import librosa
import librosa.display
import matplotlib.pyplot as plt
2.2 过零率
过零率可以计算出信号符号变化的比率,短时平均过零率可以用于语音信号请浊音的判断。如果过零率高,语音信号就是清音,如果过零率低,语音信号就是浊音。但有的音,位于浊音和清音的重叠区域,这时,只根据短时平均过零率就不可能来明确地判别清、浊音。
x, sr = librosa.load('/train_sample/aloe/24EJ22XBZ5.wav')
#绘制声波信号
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)
# 放大
n0 = 9000
n1 = 9100
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.grid()
输出的结果如下,可以发现有明显的过零趋势,我们再来计算一下过零的次数
对于zero_crossings函数,寻找过零点参数为:y:信号值,pad:类似与卷积的pad,为0是valid zero-crossing.
具体的librosa核心参数作用及输入输出定义可以参考http://librosa.github.io/librosa/core.html,翻译可以参考:https://www.xiaopingtou.cn/article-84344.html
# 计算过零率
zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))
得到15次的过零值。
2.3 频谱质心
频谱质心指示声音的“质心”位于何处,并按照声音的频率的加权平均值来加以计算。频谱中心的值越小,表明越多的频谱能量集中在低频范围内,如:voice与music相比,通常spectral centroid较低。
spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]
print(spectral_centroids.shape)
# (2647,)
# 计算时间变量
frames = range(len(spectral_centroids))
t = librosa.frames_to_time(frames)
# 归一化频谱质心
def normalize(x, axis=0):
return sklearn.preprocessing.minmax_scale(x, axis=axis)
#沿波形绘制频谱质心
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_centroids), color='r')
输出结果可以看出频谱质心呈现类似周期的变化,在随时间的低频和高频明显。
2.4 声谱衰减
它是对声音信号形状(波形图)的一种衡量,表示低于总频谱能量的指定百分比的频率。
spectral_rolloff = librosa.feature.spectral_rolloff(x+0.01, sr=sr)[0]
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_rolloff), color='b')
2.5 色度频率
色度频率是音乐音频有趣且强大的表示,其中整个频谱被投影到12个区间,代表音乐八度音的12个不同的半音(或色度)。色度向量(chroma vector )(*)(FMP,p.123)是一个通常包含12个元素特征的向量,表示信号中每个音级{C, C#, D, D#, E, …, B}中的能量。
hop_length = 512
chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)
plt.figure(figsize=(15, 5))
librosa.display.specshow(chromagram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='coolwarm')
chroma的特征示意如下
代码运行后对当前使用的音频的频率表示如下。颜色越红表示频率在此时间点上的能量越大。
3 MFCC 特征提取
人的耳朵在接收信号的时候,不同的频率会引起耳蜗不同部位的震动。耳蜗就像一个频谱仪,自动在做特征提取并进行语音信号的处理。在语音识别领域中MFCC(Mel Frequency Cepstral Coefficents)特征提取是最常用的方法,也是本次音频分类任务中涉及到的特征提取方法。
具体来说,MFCC特征提取的步骤如下:
- 对语音信号进行分帧处理
- 用周期图(periodogram)法来进行功率谱(power spectrum)估计
- 对功率谱用Mel滤波器组进行滤波,计算每个滤波器里的能量
- 对每个滤波器的能量取log 进行离散余弦变换(DCT)变换
- 保留DCT的第2-13个系数,去掉其它
其中,前面两步是短时傅里叶变换,后面几步主要涉及梅尔频谱,接下来我们将分别学习这些知识。
3.1 短时傅立叶分析
短时傅里叶分析的可以参考:https://www.jianshu.com/p/7e160442830f,https://www.cnblogs.com/klchang/p/9280509.html这里就不再赘述。
我们可以利用 librosa库做短时傅立叶变换(STFT),通过STFT能够返回一个复数矩阵,使得:
- 复数的实部:np.abs(D(f,t))为频率的振幅
- 复数的虚部:np.angle(D(f,t))为频率的相位
# STFT
y, sr = librosa.load('./train_sample/aloe/24EJ22XBZ5.wav')
S =librosa.stft(y, n_fft=2048, hop_length=None, win_length=None, window='hann', center=True, pad_mode='reflect')
'''
• y:音频时间序列
• n_fft:FFT窗口大小,n_fft=hop_length+overlapping
• hop_length:帧移,如果未指定,则默认win_length / 4
• win_length:每一帧音频都由window()加窗。窗长win_length,然后用零填充以匹配n_fft
默认win_length=n_fft。
• window:字符串,元组,数字,函数 shape =(n_fft, )
窗口(字符串,元组或数字)
窗函数,例如scipy.signal.hanning
长度为n_fft的向量或数组
• center:bool
如果为True,则填充信号y,以使帧 D [:, t]以y [t * hop_length]为中心
如果为False,则D [:, t]从y [t * hop_length]开始
• dtype:D的复数值类型。默认值为64-bit complex复数
• pad_mode:如果center = True,则在信号的边缘使用填充模式
默认情况下,STFT使用reflection padding
'''
S = np.abs(S)
print(y.shape)
print(S.shape)
输出结果如下:
(71661,)
(1025, 140)
4 梅尔频谱和梅尔倒谱
4.1 梅尔频谱
声谱图往往是很大的一张图,为了得到合适大小的声音特征,往往把它通过梅尔标度滤波器组(mel-scale filter banks),变换为梅尔频谱。这是由于人耳对低频音调的感知较灵敏,在高频时人耳是很迟钝的,梅尔标度滤波器组启发于此。由于这个限定也就导致了梅尔频谱在处理非人声的时候丢掉了高频信息,影响了准确性。可以理解为人声定制。
详细的可以参考:
https://www.cnblogs.com/xingzheai/p/14263389.html
https://blog.csdn.net/zouxy09/article/details/9156785/
4.2 梅尔倒谱
倒谱(cepstrum)就是一种信号的傅里叶变换经对数运算后再进行傅里叶反变换得到的谱。它的计算过程如下:
而梅尔频率倒谱系数(Mel Frequency Cepstrum Coefficient, MFCC)考虑到了人类的听觉特征,先将线性频谱映射到基于听觉感知的Mel非线性频谱中,然后转换到倒谱(取对数,做DCT变换)上。
#梅尔频率倒谱系数 MFCC
mfccs = librosa.feature.mfcc(x, sr)
print (mfccs.shape)
# (20, 151)
#Displaying the MFCCs:
librosa.display.specshow(mfccs, sr=sr, x_axis='time')
# mfcc 特征缩放
mfccs = sklearn.preprocessing.scale(mfccs, axis=1)
print(mfccs.mean(axis=1))
print(mfccs.var(axis=1))
librosa.display.specshow(mfccs, sr=sr, x_axis='time')
-
参考音频特征提取方法和工具汇总https://www.cnblogs.com/xingzheai/p/14263389.html ↩︎