基于MATLAB和Python实现MFCC特征参数提取


Posted in Python onAugust 13, 2019

1、MFCC概述

在语音识别(Speech Recognition)和话者识别(Speaker Recognition)方面,最常用到的语音特征就是梅尔倒谱系数(Mel-scale FrequencyCepstral Coefficients,简称MFCC)。根据人耳听觉机理的研究发现,人耳对不同频率的声波有不同的听觉敏感度。从200Hz到5000Hz的语音信号对语音的清晰度影响较大。两个响度不等的声音作用于人耳时,则响度较高的频率成分的存在会影响到对响度较低的频率成分的感受,使其变得不易察觉,这种现象称为掩蔽效应。由于频率较低的声音在内耳蜗基底膜上行波传递的距离大于频率较高的声音,故一般来说,低音容易掩蔽高音,而高音掩蔽低音较困难。在低频处的声音掩蔽的临界带宽较高频要小。所以,人们从低频到高频这一段频带内按临界带宽的大小由密到疏安排一组带通滤波器,对输入信号进行滤波。将每个带通滤波器输出的信号能量作为信号的基本特征,对此特征经过进一步处理后就可以作为语音的输入特征。由于这种特征不依赖于信号的性质,对输入信号不做任何的假设和限制,又利用了听觉模型的研究成果。因此,这种参数比基于声道模型的LPCC相比具有更好的鲁邦性,更符合人耳的听觉特性,而且当信噪比降低时仍然具有较好的识别性能。

梅尔倒谱系数是在Mel标度频率域提取出来的倒谱参数,Mel标度描述了人耳频率的非线性特性,它与频率的关系可用下式近似表示:

基于MATLAB和Python实现MFCC特征参数提取

式中f为频率,单位为Hz。下图为Mel频率与线性频率的关系:

基于MATLAB和Python实现MFCC特征参数提取

2、 MFCC特征参数提取过程详解

基于MATLAB和Python实现MFCC特征参数提取

(1)预处理

预处理包括预加重、分帧、加窗函数。

预加重:预加重的目的是提升高频部分,使信号的频谱变得平坦,保持在低频到高频的整个频带中,能用同样的信噪比求频谱。同时,也是为了消除发生过程中声带和嘴唇的效应,来补偿语音信号受到发音系统所抑制的高频部分,也为了突出高频的共振峰。预加重处理其实是将语音信号通过一个高通滤波器:

基于MATLAB和Python实现MFCC特征参数提取

分帧:先将N个采样点集合成一个观测单位,称为帧。通常情况下N的值为256或512,涵盖的时间约为20~30ms左右。为了避免相邻两帧的变化过大,因此会让两相邻帧之间有一段重叠区域,此重叠区域包含了M个取样点,通常M的值约为N的1/2或1/3。通常语音识别所采用语音信号的采样频率为8KHz或16KHz,以8KHz来说,若帧长度为256个采样点,则对应的时间长度是256/8000×1000=32ms。

加窗:将每一帧乘以汉明窗,以增加帧左端和右端的连续性。假设分帧后的信号为S(n), n=0,1…,N-1, N为帧的大小,那么乘上汉明窗

基于MATLAB和Python实现MFCC特征参数提取

后 ,W(n)形式如下:

基于MATLAB和Python实现MFCC特征参数提取

(2)FFT

由于信号在时域上的变换通常很难看出信号的特性,所以通常将它转换为频域上的能量分布来观察,不同的能量分布,就能代表不同语音的特性。所以在乘上汉明窗后,每帧还必须再经过快速傅里叶变换以得到在频谱上的能量分布。对分帧加窗后的各帧信号进行快速傅里叶变换得到各帧的频谱。

(3)谱线能量

对语音信号的频谱取模平方得到语音信号的谱线能量。

(4)计算通过Mel滤波器的能量

将能量谱通过一组Mel尺度的三角形滤波器组,定义一个有M个滤波器的滤波器组(滤波器的个数和临界带的个数相近),采用的滤波器为三角滤波器,中心频率为f(m) 。M通常取22-26。各f(m)之间的间隔随着m值的减小而缩小,随着m值的增大而增宽,如图所示:

基于MATLAB和Python实现MFCC特征参数提取 

三角滤波器的频率响应定义为:

基于MATLAB和Python实现MFCC特征参数提取

对频谱进行平滑化,并消除谐波的作用,突显原先语音的共振峰。(因此一段语音的音调或音高,是不会呈现在MFCC 参数内,换句话说,以MFCC 为特征的语音辨识系统,并不会受到输入语音的音调不同而有所影响)此外,还可以降低运算量。

计算每个滤波器组输出的对数能量为 :

基于MATLAB和Python实现MFCC特征参数提取

(5)计算DCT倒谱

经离散余弦变换(DCT)得到MFCC系数 :

基于MATLAB和Python实现MFCC特征参数提取

将上述的对数能量带入离散余弦变换,求出L阶的Mel参数。L阶指MFCC系数阶数,通常取12-16。这里M是三角滤波器个数。

3、MATLAB实现方法

注:在提取MFCC参数之前需要加载并使用VOICEBOX工具包

Df=5;
fs=8000; 
N=fs/Df;
t=0:1./fs:(N-1)./fs;
x=sin(2*pi*200*t);  
bank=melbankm(24,256,8000,0,0.5,'t');%Mel滤波器的阶数为24,fft变换的长度为256,采样频率为8000Hz 
%归一化mel滤波器组系数 
bank=full(bank); 
bank=bank/max(bank(:)); 
% DCT系数,12*p
for k=1:12      
n=0:23; 
dctcoef(k,:)=cos((2*n+1)*k*pi/(2*24)); 
end 
%归一化倒谱提升窗口 
w=1+6*sin(pi*[1:12]./12); 
%w=w/max(w);
%语音信号分帧 
xx=enframe(x,256,80);%对x 256点分为一帧  
%计算每帧的MFCC参数 
for i=1:size(xx,1) 
y=xx(i,:); 
s=y'.*hamming(256); 
t=abs(fft(s));%fft快速傅立叶变换 
t=t.^2; 
c1=dctcoef*log(bank*t(1:129)); 
c2=c1.*w'; 
end  
plot(c2);title('MFCC');

结果:

基于MATLAB和Python实现MFCC特征参数提取

4、Python实现方法

import numpy as np 
from scipy import signal
from scipy.fftpack import dct
import pylab as plt

def enframe(wave_data, nw, inc, winfunc):
  '''将音频信号转化为帧。
  参数含义:
  wave_data:原始音频型号
  nw:每一帧的长度(这里指采样点的长度,即采样频率乘以时间间隔)
  inc:相邻帧的间隔(同上定义)
  '''
  wlen=len(wave_data) #信号总长度
  if wlen<=nw: #若信号长度小于一个帧的长度,则帧数定义为1
    nf=1
  else: #否则,计算帧的总长度
    nf=int(np.ceil((1.0*wlen-nw+inc)/inc))
  pad_length=int((nf-1)*inc+nw) #所有帧加起来总的铺平后的长度
  zeros=np.zeros((pad_length-wlen,)) #不够的长度使用0填补,类似于FFT中的扩充数组操作
  pad_signal=np.concatenate((wave_data,zeros)) #填补后的信号记为pad_signal
  indices=np.tile(np.arange(0,nw),(nf,1))+np.tile(np.arange(0,nf*inc,inc),(nw,1)).T #相当于对所有帧的时间点进行抽取,得到nf*nw长度的矩阵
  indices=np.array(indices,dtype=np.int32) #将indices转化为矩阵
  frames=pad_signal[indices] #得到帧信号
  win=np.tile(winfunc,(nf,1)) #window窗函数,这里默认取1
  return frames*win  #返回帧信号矩阵

Df=5
fs=8000
N=fs/Df
t = np.arange(0,(N-1)/fs,1/fs)   
wave_data=np.sin(2*np.pi*200*t)
#预加重
#b,a = signal.butter(1,1-0.97,'high')
#emphasized_signal = signal.filtfilt(b,a,wave_data)
#归一化倒谱提升窗口
lifts=[]
for n in range(1,13):
  lift =1 + 6 * np.sin(np.pi * n / 12)
  lifts.append(lift)
#print(lifts)  

#分帧、加窗 
winfunc = signal.hamming(256) 
X=enframe(wave_data, 256, 80, winfunc)  #转置的原因是分帧函数enframe的输出矩阵是帧数*帧长
frameNum =X.shape[0] #返回矩阵行数18,获取帧数
#print(frameNum)
for i in range(frameNum):
  y=X[i,:]
  #fft
  yf = np.abs(np.fft.fft(y)) 
  #print(yf.shape)
  #谱线能量
  yf = yf**2
  #梅尔滤波器系数
  nfilt = 24
  low_freq_mel = 0
  NFFT=256
  high_freq_mel = (2595 * np.log10(1 + (fs / 2) / 700)) # 把 Hz 变成 Mel
  mel_points = np.linspace(low_freq_mel, high_freq_mel, nfilt + 2) # 将梅尔刻度等间隔
  hz_points = (700 * (10**(mel_points / 2595) - 1)) # 把 Mel 变成 Hz
  bin = np.floor((NFFT + 1) * hz_points / fs)
  fbank = np.zeros((nfilt, int(np.floor(NFFT / 2 + 1))))
  for m in range(1, nfilt + 1):
    f_m_minus = int(bin[m - 1])  # left
    f_m = int(bin[m])       # center
    f_m_plus = int(bin[m + 1])  # right
    for k in range(f_m_minus, f_m):
      fbank[m - 1, k] = (k - bin[m - 1]) / (bin[m] - bin[m - 1])
    for k in range(f_m, f_m_plus):
      fbank[m - 1, k] = (bin[m + 1] - k) / (bin[m + 1] - bin[m])
  filter_banks = np.dot(yf[0:129], fbank.T)
  filter_banks = np.where(filter_banks == 0, np.finfo(float).eps, filter_banks) # 数值稳定性
  filter_banks = 10 * np.log10(filter_banks) # dB 
  filter_banks -= (np.mean(filter_banks, axis=0) + 1e-8)
  #print(filter_banks)
  #DCT系数
  num_ceps = 12
  c2 = dct(filter_banks, type=2, axis=-1, norm='ortho')[ 1 : (num_ceps + 1)] # Keep 2-13
  c2 *= lifts
print(c2)
plt.plot(c2)
plt.show()

结果:

基于MATLAB和Python实现MFCC特征参数提取 

由MATLAB和Python绘制出来的波形可以看出二者计算出来的MFCC倒谱系数的基本走势相同。

参考:http://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
9种python web 程序的部署方式小结
Jun 30 Python
Python实现包含min函数的栈
Apr 29 Python
一张图带我们入门Python基础教程
Feb 05 Python
Python Tkinter模块实现时钟功能应用示例
Jul 23 Python
python basemap 画出经纬度并标定的实例
Jul 09 Python
使用python模拟高斯分布例子
Dec 09 Python
解决更改AUTH_USER_MODEL后出现的问题
May 14 Python
keras 读取多标签图像数据方式
Jun 12 Python
PyCharm2020.1.2社区版安装,配置及使用教程详解(Windows)
Aug 07 Python
python Tornado框架的使用示例
Oct 19 Python
Python学习工具jupyter notebook安装及用法解析
Oct 23 Python
Python爬取你好李焕英豆瓣短评生成词云的示例代码
Feb 24 Python
Python 使用 docopt 解析json参数文件过程讲解
Aug 13 #Python
Django项目中实现使用qq第三方登录功能
Aug 13 #Python
一篇文章搞定Python操作文件与目录
Aug 13 #Python
Python Django Cookie 简单用法解析
Aug 13 #Python
Django中ajax发送post请求 报403错误CSRF验证失败解决方案
Aug 13 #Python
Python人工智能之路 jieba gensim 最好别分家之最简单的相似度实现
Aug 13 #Python
Python人工智能之路 之PyAudio 实现录音 自动化交互实现问答
Aug 13 #Python
You might like
我的论坛源代码(五)
2006/10/09 PHP
PHP删除特定数组内容并且重建数组索引的方法.
2011/03/25 PHP
php二维数组排序与默认自然排序的方法介绍
2013/04/27 PHP
php获取新浪微博数据API实例
2013/11/12 PHP
php计算两个日期时间差(返回年、月、日)
2014/06/19 PHP
php有效防止图片盗用、盗链的两种方法
2016/11/01 PHP
Aster vs KG BO3 第三场2.18
2021/03/10 DOTA
基于jquery的一个图片hover的插件
2010/04/24 Javascript
分享两个手机访问pc网站自动跳转手机端网站代码
2020/12/24 Javascript
javascript编写贪吃蛇游戏
2015/07/07 Javascript
JS组件Bootstrap Select2使用方法解析
2016/05/30 Javascript
JS button按钮实现submit按钮提交效果
2016/11/01 Javascript
Vue2.0表单校验组件vee-validate的使用详解
2017/05/02 Javascript
xmlplus组件设计系列之选项卡(Tabbar)(5)
2017/05/03 Javascript
详解react-router如何实现按需加载
2017/06/15 Javascript
详解用Webpack与Babel配置ES6开发环境
2019/03/12 Javascript
vue.js实现回到顶部动画效果
2019/07/31 Javascript
Python Mysql数据库操作 Perl操作Mysql数据库
2009/01/12 Python
python文件读写并使用mysql批量插入示例分享(python操作mysql)
2014/02/17 Python
Python将DataFrame的某一列作为index的方法
2018/04/08 Python
树莓派与PC端在局域网内运用python实现即时通讯
2019/06/22 Python
Python处理时间日期坐标轴过程详解
2019/06/25 Python
Django中Middleware中的函数详解
2019/07/18 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
2020/06/09 Python
如何使用html5与css3完成google涂鸦动画
2012/12/16 HTML / CSS
Bravofly德国:预订廉价航班和酒店
2019/09/22 全球购物
印尼在线旅游门户网站:NusaTrip
2019/11/01 全球购物
CK澳大利亚官网:Calvin Klein澳大利亚
2020/12/12 全球购物
中年人生感言
2014/02/04 职场文书
优秀团支部事迹材料
2014/02/08 职场文书
优秀毕业自我鉴定
2014/02/15 职场文书
《天安门广场》教学反思
2014/04/23 职场文书
关爱残疾人标语
2014/06/25 职场文书
党员教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
Java 实现限流器处理Rest接口请求详解流程
2021/11/02 Java/Android
Spring JPA 增加字段执行异常问题及解决
2022/06/10 Java/Android