【语音识别】食物声音识别(三)音频数据特征提取

目录

 

01 特征提取背景

02 常见的音频特征提取

2.1 过零率

2.2 频谱质心

2.3 声谱衰减

2.4 色度频率

03 MFCC特征提取

3.1 短时傅里叶分析

3.1.1 分帧

3.1.2 对每帧信号进行DFT

04 梅尔频谱和梅尔倒谱

4.1 梅尔尺度

4.2 梅尔滤波器

4.3 梅尔倒谱

05 本次任务中的特征提取

参考资料


 

01 特征提取背景

在之前的Task2中,我们初步查看了数据集的信息,并通过音频的声波图和声谱图将声音可视化了。当我们拿到这些音频数据之后,接下来就需要进行特征提取(过滤掉背景噪音等不需要的信息)筛选出我们需要的信息了。

接下来我们将简要介绍以下特征,并详细学习MFCC特征提取知识:

  • 过零率 (Zero Crossing Rate)
  • 频谱质心 (Spectral Centroid)
  • 声谱衰减 (Spectral Roll-off)
  • 梅尔频率倒谱系数 (Mel-frequency cepstral coefficients ,MFCC)
  • 色度频率 (Chroma Frequencies)

 

02 常见的音频特征提取

导包

import numpy as np
import sklearn
import librosa
import librosa.display
import matplotlib.pyplot as plt

2.1 过零率

过零率(zero crossing rate)是一个信号符号变化的比率,即,在每帧中,语音信号从正变为负或从负变为正的次数。 这个特征已在语音识别和音乐信息检索领域得到广泛使用,通常对类似金属、摇滚等高冲击性的声音的具有更高的价值。

一般情况下,过零率越大,频率近似越高。

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()

 

可以看到该音频信号没有过零点,我们开源用librosa库进行验证,输出过零点个数:

# 计算过零率
zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))

15

 

2.2 频谱质心

谱质心(Spectral Centroid)是描述音色属性的重要物理参数之一,是频率成分的重心,是在一定频率范围内通过能量加权平均的频率,其单位是Hz。它是声音信号的频率分布和能量分布的重要信息。在主观感知领域,谱质心描述了声音的明亮度,具有阴暗、低沉品质的声音倾向有较多低频内容,谱质心相对较低,具有明亮、欢快品质的多数集中在高频,谱质心相对较高。该参数常用于对乐器声色的分析研究。

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.3 声谱衰减

它是对声音信号形状(波形图)的一种衡量,表示低于总频谱能量的指定百分比的频率。

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.4 色度频率

色度频率是音乐音频有趣且强大的表示,其中整个频谱被投影到12个区间,代表音乐八度音的12个不同的半音(或色度)

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')

 

03 MFCC特征提取

人的耳朵在接收信号的时候,不同的频率会引起耳蜗不同部位的震动。耳蜗就像一个频谱仪,自动在做特征提取并进行语音信号的处理。在语音识别领域中MFCC(Mel Frequency Cepstral Coefficents)特征提取是最常用的方法,也是本次音频分类任务中涉及到的特征提取方法。

具体来说,MFCC特征提取的步骤如下:

  • 对语音信号进行分帧处理
  • 用周期图(periodogram)法来进行功率谱(power spectrum)估计
  • 对功率谱用Mel滤波器组进行滤波,计算每个滤波器里的能量
  • 对每个滤波器的能量取log
  • 进行离散余弦变换(DCT)变换
  • 保留DCT的第2-13个系数,去掉其它

其中,前面两步是短时傅里叶变换,后面几步主要涉及梅尔频谱,接下来我们将分别学习这些知识。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.1 短时傅里叶分析

声音信号本是一维时域信号(声音信号随时间变化),我们可以通过傅里叶变换将其转换到频域上,但这样又失去了时域信息,无法看出频率分布随时间的变化。短时傅里叶(STFT)就是为了解决这个问题而发明的常用手段。

所谓的短时傅里叶变换,即把一段长信号分帧、加窗,再对每一帧做快速傅里叶变换(FFT),最后把每一帧的结果沿另一个维度堆叠起来,得到类似于一幅图的二维信号形式,也就是我们task2中得到的声谱图。

 

 

3.1.1 分帧

语音信号是不稳定的时变信号,但为了便于处理,我们假设在一个很短的时间内,如20-40ms内为一个稳定的系统,也就是1帧。但是我们不能简单平均分割语音,相邻的帧之间需要有一定的重合。我们通常以25ms为1帧,帧移为10ms,因此1秒的信号会有10帧。

3.1.2 对每帧信号进行DFT

我们可以使用离散傅里叶变换(DFT)把每一帧信号变换到时域,公式是:

其中s(n)表示时域信号;si(n)是第i帧的数据,其中n的范围是1-400;当我们介绍DFT的时候,Si(k)表示的是第i帧的第k个复系数;Pi(k)是第i帧的功率谱。h(n)是一个N点的窗函数(比如Hamming窗),K是DFT的长度。有了Si(k)我们就可以估计功率谱:

这样,我们就得到了周期图的功率谱估计,即声谱图。以之前task2的芦荟音频为例,它的横坐标是帧下标,纵坐标是不同频率或者叫能量,图中颜色越深(比如红色),对应频率的能量越大。

 

我们可以利用 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)

04 梅尔频谱和梅尔倒谱

声谱图往往是很大的一张图,且依旧包含了大量无用的信息,所以我们需要通过梅尔标度滤波器组(mel-scale filter banks)将其变为梅尔频谱。

4.1 梅尔尺度

梅尔尺度(Mel Scale)是建立从人类的听觉感知的频率——Pitch到声音实际频率直接的映射。频率的单位是赫兹(Hz),人耳能听到的频率范围是20-20000Hz,但人耳对Hz这种标度单位并不是线性感知关系,例如,若把音调频率从1000Hz提高到2000Hz,我们的耳朵只能觉察到频率似乎提高了一些而不是一倍。但是通过把频率转换成美尔尺度,我们的特征就能够更好的匹配人类的听觉感知效果。从频率到梅尔频率的转换公式如下:

我们可以观察一下转换后的映射图,可以发现人耳对于低频声音的分辨率要高于高频的声音,因为赫兹到梅尔是log的关系,所以当频率较小时,mel随Hz变化较快;当频率很大时,mel的上升很缓慢,曲线的斜率很小。这说明了人耳对低频音调的感知较灵敏,在高频时人耳是很迟钝的,梅尔标度滤波器组启发于此。

 

4.2 梅尔滤波器

为了模拟人耳对声音的感知,人们发明的梅尔滤波器组。一组大约20-40(通常26)个三角滤波器组,它会对上一步得到的周期图的功率谱估计进行滤波。而且区间的频率越高,滤波器就越宽(但是如果把它变换到美尔尺度则是一样宽的)。为了计算方便,我们通常把26个滤波器用一个矩阵来表示,这个矩阵有26行,列数就是傅里叶变换的点数。

计算过程如下图所示,最后我们会保留这26个滤波器的能量。图(a)是26个滤波器;图(b)是滤波后的信号;图(c)是其中的第8个滤波器,它只让某一频率范围的信号通过;图(d)通过它的信号的能量;图(e)是第20个滤波器;图(f)是通过它的信号的能量。

4.3 梅尔倒谱

在梅尔频谱上做倒谱分析(取对数log,做离散余弦变换(DCT)变换)就得到了梅尔倒谱。

对上面得到的26个点的信号进行DCT,得到26个倒谱系数(Cepstral Coefficents),最后我们保留2-13这12个数字,这12个数字就叫MFCC特征。对功率谱再做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')
(20, 140)

 

这里mfcc计算了超过151帧的20个MFCC。我们还可以进行特征缩放,使得每个系数维度具有零均值和单位方差:

 

# 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')

 

[-5.1089697e-09  1.2772424e-09  1.3623919e-08 -1.0217939e-08
 -8.5149493e-10 -5.0238199e-08 -3.6188534e-09  4.2574747e-10
  7.4505806e-09  7.6634548e-09 -2.5544848e-09  4.2574747e-10
 -2.5544848e-09 -4.0446011e-09  3.8317271e-08  8.9406971e-09
 -3.1931060e-09  2.9802323e-09 -2.3416111e-09  3.6188534e-09]
[0.9999999  1.0000002  0.99999976 0.99999976 1.0000001  0.9999997
 0.9999996  0.99999976 0.99999976 1.0000002  1.0000004  0.9999997
 1.         1.0000004  1.0000002  1.0000002  1.         0.9999997
 1.0000004  1.        ]

 

05 本次任务中的特征提取

 

feature = []
label = []
# 建立类别标签,不同类别对应不同的数字。
label_dict = {'aloe': 0, 'burger': 1, 'cabbage': 2,'candied_fruits':3, 'carrots': 4, 'chips':5,
                  'chocolate': 6, 'drinks': 7, 'fries': 8, 'grapes': 9, 'gummies': 10, 'ice-cream':11,
                  'jelly': 12, 'noodles': 13, 'pickles': 14, 'pizza': 15, 'ribs': 16, 'salmon':17,
                  'soup': 18, 'wings': 19}
label_dict_inv = {v:k for k,v in label_dict.items()}

建立提取音频特征的函数

from tqdm import tqdm
def extract_features(parent_dir, sub_dirs, max_file=10, file_ext="*.wav"):
    c = 0
    label, feature = [], []
    for sub_dir in sub_dirs:
        for fn in tqdm(glob.glob(os.path.join(parent_dir, sub_dir, file_ext))[:max_file]): # 遍历数据集的所有文件
            
           # segment_log_specgrams, segment_labels = [], []
            #sound_clip,sr = librosa.load(fn)
            #print(fn)
            label_name = fn.split('/')[-2]
            label.extend([label_dict[label_name]])
            X, sample_rate = librosa.load(fn,res_type='kaiser_fast')
            mels = np.mean(librosa.feature.melspectrogram(y=X,sr=sample_rate).T,axis=0) # 计算梅尔频谱(mel spectrogram),并把它作为特征
            feature.extend([mels])
            
    return [feature, label]

 

# 自己更改目录
parent_dir = './train_sample/'
save_dir = "./"
folds = sub_dirs = np.array(['aloe','burger','cabbage','candied_fruits',
                             'carrots','chips','chocolate','drinks','fries',
                            'grapes','gummies','ice-cream','jelly','noodles','pickles',
                            'pizza','ribs','salmon','soup','wings'])

# 获取特征feature以及类别的label
temp = extract_features(parent_dir,sub_dirs,max_file=100)
temp = np.array(temp)
data = temp.transpose()

 

# 获取特征
X = np.vstack(data[:, 0])

# 获取标签
Y = np.array(data[:, 1])
print('X的特征尺寸是:',X.shape)
print('Y的特征尺寸是:',Y.shape)
X的特征尺寸是: (1000, 128)
Y的特征尺寸是: (1000,)
# 在Keras库中:to_categorical就是将类别向量转换为二进制(只有0和1)的矩阵类型表示
Y = to_categorical(Y)

 

# 最终数据
print(X.shape)
print(Y.shape)

 

(1000, 128)
(1000, 20)

参考资料

1. STFT和声谱图

2. MFCC特征提取教程

3. librosa处理音频信号

 

 

 

 

 

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值