语音识别之DTW算法的应用(Python)

简介

本文目的是探究语音识别中DTW算法的应用,本人在相关算法中加入了自己的理解并对实时识别进行了扩展。

代码链接:基于Python的智能家居语言识别模拟系统

注意:在运行之前,需要修改代码os.chdir()中的绝对路径。

1  设计任务及要求

设计高准确率的连续语音识别系统。本实验模拟智能家居声控系统,对使用者的语音进行录制与识别,得到对应的命令词。10个命令词为:开灯、关灯、播放音乐、关闭音乐、打开空调、关闭空调、打开电视、关闭电视、开始扫地、停止扫地。

2  引言

语音识别以语音为研究对象,是语音信号处理的一个重要研究方向,也是语音信号处理的一个基本问题。是模式识别的一个分支,涉及到生理学,心理学,语言学,计算机科学,以及信号处理等诸多领域,其最终实现的是人机交互,同时也在其他领域发挥着重要的作用,如导航,辅助机器人技术,移动设备服务等多个领域。

语音识别系统的分类方式及依据是根据说话人说话方式的要求,可以分为孤立字(词)语音识别系统,连接字语音识别系统以及连续语音识别系统,本文建立的系统为连续语音识别系统。不同的语音识别系统,尽管设计和实现的细节不同,但所采用的技术都是相似的,一个典型的语音识别系统如图1所示,主要包括预处理,特征提取和训练识别网络。

图1 语音识别系统组成部分

本系统用于模拟智能家居的声控部分,对10个命令词进行识别。系统首先对原始语音进行预加重、分帧、加窗等预处理操作,提取语音对应的特征参数。在得到了特征参数的基础上,采用不同的方法进行识别:(1).采用模板匹配技术DTW算法进行进行时间的对准和相似度度量. (2).利用GMM-HMM建立声学模型,最终完成识别。

3  实验原理及应用

3.1 预处理

在信号处理系统中,对原始信号进行预处理是必要的这样可以获得一个比较理想的处理对象。在语音识别系统中,语音信号的预处理主要包括分帧,预加重及端点检测。

3.1.1  分帧

语音信号是一种典型的非平稳信号,它的均值函数u(x)和自相关函数R(xl,x2)都随时间而发生较大的变化。但研究发现,语音信号在短时间内频谱特性保持平稳,即具有短时平稳特性。因此,在实际处理时可以将语音信号分成很小的时间段(约10~30ms),称之为“帧”,作为语音信号处理的最小单位,帧与帧的非重叠部分称为帧移,而将语音信号分成若干帧的过程称为分帧。分帧小能清楚地描绘语音信号的时变特征但计算量大;分帧大能减少计算量但相邻帧间变化不大,容易丢失信号特征。一般取帧长20ms,帧移为帧长的1/3~1/2。

在本系统中帧长25ms,帧移10ms。

3.1.2  预加重

对于语音信号的频谱,通常是频率越高幅值越小,在语音信号的频率增加两倍时,其功率谱的幅度下降6dB。因此必须对高频进行加重处理,一般是将语音信号通过一个一阶高通滤波器1-0.9375z-1,即为预加重滤波器。其目的是滤除低频干扰,特别是50Hz到60Hz的工频干扰,将对语音识别更为有用的高频部分进行频谱提升。在计算短时能量之前将语音信号通过预加重滤波器还可起到消除直流漂移、抑制随机噪声和提升清音部分能量的效果。

3.1.3  端点检测

语音信号起止点的判别是任何一个语音识别系统中必不可少的组成部分。因为只有准确的找出语音段的起始点和终止点,才能得到真正要分析的语言信号。为达到提取人声部分的语音段,本实验采用双门限法进行端点检测。该算法使用了三个阈值(包括两个短时能量阈值和一个过零率阈值)。

短时能量计算方法:

这里使用矩形窗w(m),对于每一个要计算的帧而言,它是1,因此这里可以忽略掉,因此,每一帧采样点平方和对应的就是该帧的短时能量。

短时过零率计算方法:

其中,sgn函数:

w(m)函数为:

本实验采用的端点检测算法具体分为三步:

图2 双门限法示意图

第一步:取一个较高的短时能量作为阈值MH,首先分出语音中的浊音部分(如图2,A1-A2区间)。本实验的MH,取值为所有帧的短时能量的平均数的一半(平均数偏大)。

第二步:取一个较低的能量阈值ML,从A1-A2区间,向两端进行搜索,将较低能量段的语音部分也加入到语音段,进一步扩大语音段范围(如图所示,B1-B2区间)。本实验中,首先计算语音前一段的静音部分的能量均值(前5帧),本文将静音部分的能量均值和MH相加的一半作为ML。

第三步:使用短时过零率阈值为Zs。由于语音的两端部分是辅音(也就是清音部分),也是语音中的一部分,但是辅音的能量与静音部分的能量一样低,但是过零率比静音部分高出很多。为了区分开二者,将利用短时能量区分完的语音段继续向两端进行搜索,短时过零率大于3倍Zs的部分,则认为是语音的清音部分。将该部分加入语言段,就是求得的语音段(如图2,C1-C2区间)。

3.2 特征提取

人的听觉系统是一个特殊的非线性系统,它响应不同频率信号的灵敏度是不同的,基本上是一个对数的关系。近年来,一种能够比较充分利用人耳的这种特殊感知特性的系数得到了广泛应用,这就是Mel尺度倒谱系数(Mel-scaled Cepstrum Coefficients,简称MFCC)。

MFCC系数的计算流程(图3)如下:

  1. 先对语音进行预加重、分帧和加窗;
  2. 对每一个短时分析窗,通过FFT得到对应的频谱;
  3. 将上面的频谱通过Mel滤波器组得到Mel频谱;
  4. 在Mel频谱上面进行倒谱分析(取对数,做逆变换,实际逆变换一般是通过DCT离散余弦变换来实现),获得Mel频率倒谱系数MFCC,这个MFCC就是这帧语音的特征;
图3 MFCC系数计算流程图

本实验采用 HTK工具包中的Hcopy命令进行FFCC特征提取,存储在.mfc文件中。提取的特征39维MFCC特征。包括12维dct系数,能量特征,一阶差分和二阶差分等。提取算法如下:

首先进行预加重,然后进行分帧,加窗,然后进行快速傅里叶变换,将它转换为频域上的能量分布;将能量谱通过一组Mel尺度的三角形滤波器组,对频谱进行平滑化,并消除谐波的作用,突显原先语音的共振峰;计算每个滤波器输出的对数能量,经离散余弦变换(DCT)得到MFCC系数;然后计算对数能量;最后提取动态差分参数(包括一阶差分和二阶差分等)

图4为Hcopy命令参数设置,图5为一段语音信号的第一帧MFCC特征:

图4 Hcopy命令参数设置
图5 语音信号单帧MFCC特征值

3.3 DTW语音匹配

由于即使同一个人不同时间发出同一个声音,也不可能具有相同的长度,因此就需要用到动态时间归正(DTW)算法。把时间归正和距离测度计算结合起来的一种非线性归正技术。DTW 本质上是一个简单的动态规划算法,是用来计算两个维数不同的向量之间的相似度的问题,即计算向量 M1 和 M2 的最短距离。是一种非常常用的语音匹配算法。

3.3.1  算法基本思想

对两个不同维数的语音向量 m1 和 m2进行匹配(m1 和 m2 的每一维也是一个向量,是语音每一帧的特征值,这里利用的是 MFCC 特征)。设两个向量的长度为 M1 和 M2,则距离可以表示为:

那么,就可以这样进行匹配:

  1. 每一条从(1,1)到(M1,M2)路径都有一个累计距离称为路径的代价;

  2. 每一条路径都代表一种对齐情况;

  3. 代价最小的路径就是所求的对准路径。

这样就可以将对准问题,或者说将求两个语音段的相似度问题,转化成了搜索代价最小的最优路径问题,图6为其中一条路径。

6 1 1 )到( M1,M2 )路径其中一条路径

在搜索过程中,往往要进行路径的限制,如图7,(i,j)点只能由相邻的三点到达:

7 路径限制

在此限制条件下,可以将全局最优化问题转化为许多局部最优化问题一步一步地来求解,这就动态规划(Dynamic Programming,简称DP )的思想。

3.3.2  算法基本步骤

1. 定义一个代价函数 , 表示从起始点(1,1)出发,到达(i,j)点最小代价路径的累计距离。有:

2. 要计算两个向量之间的最短距离,可以表示为:

依次类推,可由更低一层的代价函数计算得到:

3. 因此,可以从  开始计算,递推出(1,1)到(i,j)的路径。递推过程中定义加权系数wn,加权系数的取值与局部路径有关:

4. 为了减少计算量,可以定义平行四边形区域约束,如图8:

8 平行四边形路径限制

3  实验结果(DTW)

3.1 设计实验任务及过程

本实验旨在模拟智能家居声控系统,一共录制了6组语音,每组 10 个命令词,一共 60 段语音。通过实验,取出2组作为模板。剩余的 40 个语音命令作为测试样例,测试 语音识别系统的精确度。

实验过程如下:

  1. 首先录制 60 个语音,采样频率为16kHz,存储在 RecordedVoice 文件夹下;
  2. 利用实验一的代码对录制的语音进行端点检测,存储在 RecordedVoice-EndPointed 文件夹下;
  3. 对端点检测后的语音命令进行操作,利用 HTK 中的 HCopy 工具提取出 MFCC 特征,存放在 xxx.mfc 文件中,放在 MFCC-EndPointedVoice 文件夹下;
  4. 在代码中取出所有语音命令的 MFCC 特征,区分开模板和测试样例。根据 DTW 算法,对 40 个测试样例进行静态语音匹配,检测正确率;
  5. 在代码中录音,然后保存录音的文件,存放在 RecordedVoice-RealTime 中。利用端点检测的代码对其进行端点检测,保存在 RecordedVoice-RealTime 中;
  6. 在代码中动态调用 HCopy 程序,对实时录的语音进行 MFCC 特征提取,然后进行语音匹配,检测是否与对应的命令匹配上;

3.2 实验结果

本次测试的4组数据,40段语音,识别率达到95%,结果如图9。该结果表明,DTW算法的语音识别率十分理想,最后两端语音识别失败的主要原因是,录音者的声调、响度和速度与模板差别巨大所造成的。因此,DTW的识别率受到模板数量的限制,因此在实际的智能家居声控系统应用中,需要采集每个家庭成员尽量多的语音作为模板,以提高系统识别率。

图9   前两组段语音识别结果

另外,本实验还设计了简洁的GUI界面,用于实时对使用者的语音信号进行采集和识别,更好的模拟智能家居声控系统。GUI界面如图10:

图10 语音识别GUI界面

4  总结

在使用DWT匹配算法过程中,模板的好坏直接影响了整个识别系统的准确率,因此我们通过多组数据对比,选取了最优的模板,便能够达到高识别率。

参考:https://blog.csdn.net/rocketeerLi/article/details/84638701

  • 10
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,下面我来给您介绍一下如何使用Python实现DTW算法进行孤立字语音识别: 1. 首先,需要准备一些语音数据,包括若干个发音相同的孤立字,每个孤立字的语音数据应该保存为一个.wav文件。 2. 接下来,需要使用Python的科学计算库NumPy和信号处理库librosa来读取和处理.wav文件,将语音数据转换为时间序列。 ```python import librosa import numpy as np # 读取.wav文件并转换为时间序列 def read_audio(filename): y, sr = librosa.load(filename, sr=None) return y, sr # 提取语音信号的MFCC特征 def extract_mfcc(y, sr): mfccs = librosa.feature.mfcc(y, sr, n_mfcc=13) return mfccs ``` 3. 接下来,需要使用DTW算法比较不同孤立字的语音数据之间的相似度,从而识别出输入语音信号中的孤立字。下面是一个简单的DTW算法实现: ```python def dtw_distance(x, y): dtw = np.zeros((len(x), len(y))) for i in range(len(x)): for j in range(len(y)): dist = np.linalg.norm(x[i] - y[j]) if i == 0 and j == 0: dtw[i][j] = dist elif i == 0: dtw[i][j] = dist + dtw[i][j-1] elif j == 0: dtw[i][j] = dist + dtw[i-1][j] else: dtw[i][j] = dist + min(dtw[i-1][j], dtw[i][j-1], dtw[i-1][j-1]) return dtw[-1][-1] # 将输入语音信号与每个孤立字的语音数据进行比较,找到最相似的孤立字 def recognize_audio(input_audio, isolated_words): input_mfcc = extract_mfcc(input_audio) min_distance = np.inf recognized_word = None for word in isolated_words: word_mfcc = extract_mfcc(word) distance = dtw_distance(input_mfcc.T, word_mfcc.T) if distance < min_distance: min_distance = distance recognized_word = word return recognized_word ``` 4. 最后,可以将上述函数组合起来,实现一个简单的孤立字语音识别器: ```python import os # 读取所有孤立字的语音数据 isolated_words = [] for filename in os.listdir('isolated_words'): if filename.endswith('.wav'): y, sr = read_audio(os.path.join('isolated_words', filename)) isolated_words.append(y) # 读取输入语音信号 input_audio, sr = read_audio('input.wav') # 识别输入语音信号中的孤立字 recognized_word = recognize_audio(input_audio, isolated_words) # 输出识别结果 print('The recognized word is:', recognized_word) ``` 上述代码中,我们假设所有孤立字的语音数据保存在一个名为“isolated_words”的文件夹中,输入语音信号保存为一个名为“input.wav”的.wav文件。通过调用recognize_audio函数,可以找到输入语音信号中最相似的孤立字,并输出识别结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值