2019-11-01 17:05:20 caiji_is_studying 阅读数 42

前段时间在做语音识别技术的研讨,通过对网上资料的学习,加上自己的一些理解,整理出一篇DTW算法简介,欢迎大家指出不足之处。

DTW算法简介

在进行语音帧对应关系的建立和总失真度的计算时,我们采用的是动态时间规整算法(DTW),该算法本质上是一种动态规划算法,利用局部最佳化的处理来寻找这样一条路径:沿着这条路径,两个特征矢量序列间的累积失真量最小,即是要寻找一条从起始点到终止点的最佳路径,使得该路径上所有帧失真度总和(总失真)达到最小。


设测试模板T共有N帧,参考模板R共有M帧,将测试模板和参考模板的帧号分别在坐标系的横轴和纵轴上标出,则各个帧号之间的关系形成一个网络,网格中的任何一个交叉点(n,m)表示测试模板的T(n)和参考模板R(m)相交,并且该交叉点拥有帧失真度为D[T(n), R(m)]。DTW算法利用动态规划思想求出一条由起点(1, 1)到终点(n, m)的路径,该路径实现了输入模板和测试模板时间帧的对应,并且满足路径上所经过的交叉点所对应的失真度总和最小(全局最优解)。

事实上,在上述搜索过程中路径的选择并不是任意的。首先,考虑到实际语音的发音情况,虽然语音的发音快慢会有所变化,但是各个部分的先后次序不可能颠倒,因此上述路径必然从左下角出发,终止于右上角;其次,为了防止盲目的搜索,一般不容许横轴或纵轴过分倾斜的路径,一般对路径中点处路径的斜率的最大、最小值作出规定,通常最大斜率为2,最小斜率为1/2。图示的外边框平行四边形说明了DTW算法的搜索范围,其中两个边框的斜率分别为1和1/2。


将路径上的当前点记为(n. m),根据上图,DTW算法的约束条件是:

(1)路径经过起始点和终止点,即:
(2)路径所通过的网格点必须在上左图所示的平行四边形区域内;

(3)根据上右图,当前的的上一个路径点必须满足以下条件:
在这里插入图片描述
根据上述约束条件,定义路径代价函数d[n, m],其意义为从起始点(n0, m0)(即(1, 1))到点(n, m)的路径上失真度和的最小值,则有以下递推公式:
在这里插入图片描述
其中D[T(n), R(m)]为当前点对应帧T(n)和R(m)的失真度。该算法从点(1, 1)开始,到(N, M)结束,当n = N,m = M时算法停止,返回最小失真度总和,并且沿算法所得路径向前回溯,即得到(1, 1)到(N, M)的最优路径,即为测试模板和参考模板语音帧之间的最佳匹配。

附主要参考资料链接

2019-10-04 17:44:36 qq_41131259 阅读数 111

简介

本文目的是探究语音识别中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 11)到(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

2018-05-16 15:39:00 qq_39239990 阅读数 1511

语音识别,声音的特征通过mfcc算出来了以后,我们进行进行跟模板对比,进行判断语音的内容了

先录制“目标词”语音,计算出MFCC保存,然后通过录音录入声音,进行计算MFCC,然后跟目标词进行对比,对比使用DTW算法

DTW参考:https://blog.csdn.net/zouxy09/article/details/9140207

算法实现 C语言,C++比较多


Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks


Class DTW


    Const DTWMAXNUM As Integer = 2000
    Const DTWVERYBIG As Double = 100000000.0
    Private distance As Double(,) = New Double(DTWMAXNUM - 1, DTWMAXNUM - 1) {}
    '保存距离
    Private dtwpath As Double(,) = New Double(DTWMAXNUM - 1, DTWMAXNUM - 1) {}
    '保存路径


    '***************************************************************************


    ' DTWDistance,求两个数组之间的匹配距离
    '        /* A,B分别为第一第二个数组,Alen,Blen为其数组长度,r为匹配窗口的大小
    '
    '        /* r的大小一般取为数组长度的1/10到1/30
    '        /* 返回两个数组之间的匹配距离,如果返回-1.0,表明数组长度太大了
    '        /****************************************************************************


    Public Function DTWDistanceFun(A As Double(), Alen As Integer, B As Double(), Blen As Integer, r As Integer) As Double
        Dim i As Integer, j As Integer
        Dim dist As Double
        Dim istart As Integer, imax As Integer
        Dim r2 As Integer = r + Math.Abs(Alen - Blen)
        '匹配距离
        Dim g1 As Double, g2 As Double, g3 As Double
        Dim pathsig As Integer = 1
        '路径的标志


        '检查参数的有效性


        If Alen > DTWMAXNUM OrElse Blen > DTWMAXNUM Then
            'printf("Too big number\n");
            Return -1.0
        End If


        '进行一些必要的初始化


        For i = 0 To Alen - 1
            For j = 0 To Blen - 1
                dtwpath(i, j) = 0
                distance(i, j) = DTWVERYBIG
            Next
        Next


        '动态规划求最小距离


        '这里我采用的路径是 -------
        '                                      . |
        '                                    .   |
        '                                  .     |
        '                                .       |
        '             


        distance(0, 0) = CDbl(2) * Math.Abs(A(0) - B(0))
        For i = 1 To r2
            distance(i, 0) = distance(i - 1, 0) + Math.Abs(A(i) - B(0))
        Next
        For j = 1 To r2
            distance(0, j) = distance(0, j - 1) + Math.Abs(A(0) - B(j))
        Next


        For j = 1 To Blen - 1
            istart = j - r2
            If j <= r2 Then
                istart = 1
            End If
            imax = j + r2
            If imax >= Alen Then
                imax = Alen - 1
            End If


            For i = istart To imax
                g1 = distance(i - 1, j) + Math.Abs(A(i) - B(j))
                g2 = distance(i - 1, j - 1) + 2 * Math.Abs(A(i) - B(j))
                g3 = distance(i, j - 1) + Math.Abs(A(i) - B(j))
                g2 = Math.Min(g1, g2)
                g3 = Math.Min(g2, g3)
                distance(i, j) = g3
            Next
        Next


        dist = distance(Alen - 1, Blen - 1) / CDbl(Alen + Blen)
        Return dist
    End Function
    'end DTWDistance




    '***************************************************************************


    ' DTWTemplate,进行建立模板的工作
    '        /* 其中A为已经建立好的模板,我们在以后加入训练样本的时候,
    '        /* 以已建立好的模板作为第一个参数,Alen为模板的长度,在这个模板中不再改变
    '        /* B为新加入的训练样本,Blen为B的长度,turn为训练的次数,在第一次
    '        /* 用两个数组建立模板时,r为1,这是出于权值的考虑
    '        /* temp保存匹配最新训练后的模板,建议temp[DTWMAXNUM],函数返回最新训练后模板的长度
    '        /* 如果函数返回-1,表明训练样本之间距离过大,需要重新选择训练样本,
    '        /* tt为样本之间距离的阀值,自行定义
    '        /* rltdistance保存距离,第一次两个数组建立模板时可以随意赋予一个值,
    '        /* 后面用前一次返回的值赋予该参数
    '        /****************************************************************************


    Public Function DTWTemplate(A As Double(), Alen As Integer, B As Double(), Blen As Integer, temp As Double(), turn As Integer,
            tt As Double, rltdistance As Double()) As Integer
        Dim dist As Double
        Dim i As Integer, j As Integer
        Dim pathsig As Integer = 1
        dist = DTWDistanceFun(A, Alen, B, Blen, CInt(Alen / 30))
        If dist > tt Then
            Console.WriteLine(vbLf & "Sample doesn't match!" & vbLf)
            Return -1
        End If




        '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        'If turn = 1 Then
        '    rltdistance.Target = dist
        'Else
        '    rltdistance.Target = ((rltdistance.Target) * (turn - 1) + dist) / turn
        'End If




        If turn = 1 Then
            rltdistance(0) = dist
        Else
            rltdistance(0) = ((rltdistance(0)) * (turn - 1) + dist) / turn
        End If


        '----------------------------------------------------------------------------
        '寻找路径,这里我采用了逆向搜索法


        i = Alen - 1
        j = Blen - 1
        While j >= 1 OrElse i >= 1
            Dim m As Double
            If i > 0 AndAlso j > 0 Then
                m = Math.Min(Math.Min(distance(i - 1, j), distance(i - 1, j - 1)), distance(i, j - 1))
                If m = distance(i - 1, j) Then
                    dtwpath(i - 1, j) = pathsig
                    i -= 1
                ElseIf m = distance(i - 1, j - 1) Then
                    dtwpath(i - 1, j - 1) = pathsig
                    i -= 1
                    j -= 1
                Else
                    dtwpath(i, j - 1) = pathsig
                    j -= 1
                End If
            ElseIf i = 0 Then
                dtwpath(0, j - 1) = pathsig
                j -= 1
            Else
                'j==0
                dtwpath(i - 1, 0) = pathsig
                i -= 1
            End If
        End While
        dtwpath(0, 0) = pathsig
        dtwpath(Alen - 1, Blen - 1) = pathsig


        '建立模板


        For i = 0 To Alen - 1
            Dim ftemp As Double = 0.0
            Dim ntemp As Integer = 0
            For j = 0 To Blen - 1
                If dtwpath(i, j) = pathsig Then
                    ftemp += B(j)
                    ntemp += 1
                End If
            Next
            ftemp /= CDbl(ntemp)
            '注意这里的权值
            temp(i) = (A(i) * turn + ftemp) / CDbl(turn + 1)
        Next


        Return Alen
        '返回模板的长度
    End Function
    'end DTWTemplate
  

End Class

2016-07-14 16:48:12 LG1259156776 阅读数 3374

DTW(动态时间弯折)算法原理:基于动态规划(DP)的思想,解决发音长短不一的模板匹配问题。相比HMM模型算法,DTW算法的训练几乎不需要额外的计算。所以在孤立词语音识别中,DTW算法仍得到广泛的应用。

在训练和识别阶段,首先采用端点检测算法确定语音的起点和终点。对于参考模板{R(1),R(2),…,R(m),…,R(M)}R(m)为第m帧的语音特征矢量。对于测试模板{T(1),T(2),…,T(n),…,T(N)}T(n)为测试模板的第n帧的语音特征矢量。参考模板与测试模板一般采用类型的特征矢量、相同的帧长、相同的窗函数和相同的帧移。

对于测试和参考模板TR,它们之间的相似度之间的距离D[TR],距离越小则相似度越高。在DTW算法中通常采用欧氏距离表示。对于NM不相同的情况,需要考虑T(n)R(m)对齐。一般采用动态规划(DP)的方法将实现TR的映射。

将测试模板的各个帧号n=1~N在一个二维直角坐标系中的横轴上标出,参考模板的各帧号m=1~M在纵轴上标出,通过这些表示帧号的整数坐标画出一些纵横线即可形成一个网格,网格中的每一个交叉点(n,m)表示测试模式中某一帧与训练模式中某一帧的交汇点。DP算法可以归结为寻找一条通过此网格中若干格点的路径,路径通过的格点即为测试和参考模板中进行距离计算的帧号。所选的路径必定是从左下角出发,在右上角结束。

为了使路径不至于过分倾斜,可以约束斜率在0.5~2的范围内,如果路径已通过格点特定人语音识别算法—DTW算法

特定人语音识别算法—DTW算法

搜索路径的方法如下:搜索从特定人语音识别算法—DTW算法点出发,计算每条路径达到特定人语音识别算法—DTW算法点时的总的积累距离,具有最小累积距离者即为最佳路径。若用特定人语音识别算法—DTW算法代表此格点,并将通过该格点之路径延伸而通过特定人语音识别算法—DTW算法,这些此路径的积累距离为:

特定人语音识别算法—DTW算法

这样就可以从特定人语音识别算法—DTW算法=(1,1)出发搜索特定人语音识别算法—DTW算法,再搜索特定人语音识别算法—DTW算法…..,对每个特定人语音识别算法—DTW算法都存储相应的前一格点特定人语音识别算法—DTW算法及相应的帧匹配距离特定人语音识别算法—DTW算法。搜索到特定人语音识别算法—DTW算法时,只保留一条最佳路径。如果有必要的话,通过逐点向前寻找就可以求得整条路径。这套DP算法便是DTW算法。

0~9的数字语音进行测试和识别,识别结果如下:

正在进行模板匹配...

正在计算匹配结果...

测试模板1的识别结果为:1

测试模板2的识别结果为:8

测试模板3的识别结果为:3

测试模板4的识别结果为:4

测试模板5的识别结果为:5

测试模板6的识别结果为:6

测试模板7的识别结果为:7

测试模板8的识别结果为:8

测试模板9的识别结果为:9

测试模板10的识别结果为:10

由上可知,除测试模板2误判外,其它数字语音都能正确识别。

DTW算法的MATLAB程序:

function dist = dtw( t,r )

n=size(t,1);

m=size(r,1);

%%帧匹配距离距阵

d=zeros(n,m);

 

for i=1:n

    for j=1:m

        d(i,j)=sum((t(i,:)-r(j,:)).^2);

    end

end

 

%%累积距离矩阵

D=ones(n,m)*realmax;

D(1,1)=d(1,1);

%%动态规划

for i=2:n

    for j=1:m

        D1=D(i-1,j);

        if j>1

            D2=D(i-1,j-1);

        else

            D2=realmax;

        end

       

        if j>2

            D3=D(i-1,j-2);

        else

            D3=realmax;

        end

        D(i,j)=d(i,j)+min([D1,D2,D3]);

    end

end

dist=D(n,m);

end

 

测试程序:

disp('正在计算参考模板的参数...')

for i=1:10

    fname=sprintf('test1\\�.wav',i-1);

    [x fs]=wavread(fname);

    [x1 x2]=vad(x,fs);

    m=mfcc(x);

    m=m(x1-2:x2-2,:);

    ref(i).mfcc=m;

end

 

disp('正在计算测试模板的参数...')

for i=1:10

    fname=sprintf('train1\\�.wav',i-1);

    [x fs]=wavread(fname);

    [x1 x2]=vad(x,fs);

    m=mfcc(x);

    m=m(x1-2:x2-2,:);

    test(i).mfcc=m;

end

 

disp('正在进行模板匹配...')

dist=zeros(10,10);

for i=1:10

    for j=1:10

        dist(i,j)=dtw(test(i).mfcc,ref(j).mfcc);

    end

end

 

disp('正在计算匹配结果...')

for i=1:10

    [d,j]=min(dist(i,:));

    fprintf('测试模板%d的识别结果为:%d\n',i,j);

end

2013-01-25 01:54:08 fzxy002763 阅读数 38077

DTW主要是应用在孤立词识别的算法,用来识别一些特定的指令比较好用,这个算法是基于DP(动态规划)的算法基础上发展而来的。这里介绍语音识别就先介绍下语音识别的框架,首先我们要有一个比对的模版声音,然后需要去截取其里面包含真正属于语音的部分,这个要采用一个叫做vad(voice activedetection)语音活动检测的算法,而在vad中间我们最常使用双门限端点检测这种方法,如图所示,我们采用vad判断语音的开始和结束,判断方法就是通过音量的大小做一个阈值判定,在时域上很简单就能判定。

图.speech(语音信号),Energy(短时能量),zcr(短时过零率值)

然后需要寻找一个特征矢量,在语音识别中很多采用MFCC,也就是梅尔倒谱这个参数作为特征矢量。一般的谱分析我们都是采用频谱,或者小波这样与频谱的区别只是不同量度,这些都是解决加性噪声的滤波问题,而还存在倒谱,阶次谱这样是为了特定的需求所构建的另外的谱方法,这些是在NI的探讨会上次说的。倒谱是一种为了滤除乘性噪声的谱方法,简单的说就是对功率谱求log,再反傅里叶变换,公式如 ,这种方法用来做信号分离很有用,下面综合下matlab分析下DTW语音识别。

  fname = sprintf('%da.wav',i);

    x=fname;

   [x,fs]=wavread(x);

    [x1 x2] =vad(x);

    m = mfcc(x);

m = m(x1-2:x2-2,:);

ref(i).mfcc = m;

首先这里是读取一段语音,通过wavread,然后通过vad函数获取语音的开始于结束部分,这里很多函数都是调用语音应用库voicebox的,获取x1,x2就是语音的两端时候,先对语音信号整体计算mfcc梅尔倒谱,然后截取其中语音部分的作为其函数值。

    fname= sprintf('%db.wav',i);

    x=fname;

   [x,fs]=wavread(x);   

    [x1 x2] =vad(x);

    m = mfcc(x);

    m =m(x1-2:x2-2,:);

    test(i).mfcc =m;

然后以同样的方法计算需要识别的语音文件其语音段的梅尔倒谱系数,然后对模版与识别文件进行“比对”,这里的比对方法就是DTW算法,我们经常把整个语音识别算法叫做DTW语音识别,但实际上,DTW主要是应用在比对两个梅尔倒谱的比对上,而且这也是一种基于距离的比对,也可以认为是一种基于有导师学习的聚类方法。不过在讲比对之前我们需要讲下匹配,之前图像匹配我们是采用谱分析的方法,而这里属于一维信号的匹配,故解释下相关模板匹配方法。语音识别的匹配需要解决的一个关键问题是说话人对同一个词的两次发音不可能完全相同,这些差异不仅包括音强的大小、频谱的偏移,更重要的是发音时音节的长短不可能完全相同,而且两次发音的音节往往不存在线性对应关系。设参考模板有M帧矢量{R(1),R(2),…R(m),…,R(M)},R(m)为第m帧的语音特征矢量,测试模板有N帧矢量{T(1),T(2),…T(n),…,T(N)},T(n)是第n帧的语音特征矢量。d(T(in),R(im))表示T中第in帧特征与R中im帧特征之间的欧几里得距离。直接匹配是假设测试模板和参考模板长度相等,即in=im;线性时间规整技术假设说话速度是按不同说话单元的发音长度等比例分布的,即。这两种假设其实都不符合实际语音的发音情况,我们需要一种更加符合实际情况的非线性时间规整技术,也就是DTW算法。

图.三种匹配模式的对比

DTW算法的原理图如图,把测试模板的各个帧号n=1~N在一个二维直角坐标系中的横轴上标出,把参考模板的各帧m=1~M在纵轴上标出,通过这些表示帧号的整数坐标画出一些纵横线即可形成一个网格,网格中的每一个交叉点(ti,rj)表示测试模式中某一帧与训练模式中某一帧的交汇。DTW算法分两步进行,一是计算两个模式各帧之间的距离,即求出帧匹配距离矩阵,二是在帧匹配距离矩阵中找出一条最佳路径。搜索这条路径的过程可以描述如下:搜索从(1,1)点出发,对于局部路径约束如图,点(in,im)可达到的前一个格点只可能是(in-1,im)、(in-1,im-l)和(in-1,im-2)。那么(in,im)一定选择这三个距离中的最小者所对应的点作为其前续格点,这时此路径的累积距离为:

D(in,im)=d(T(in),R(im))+min{D(in-1,im),D(in-1,im-1),D(in-1,im-2)},这样从(l,1)点出发(令D(1,1)=0)搜索,反复递推,直到(N,M)就可以得到最优路径,而且D(N,M)就是最佳匹配路径所对应的匹配距离。在进行语音识别时,将测试模板与所有参考模板进行匹配,得到的最小匹配距离 Dmin(N,M)所对应语音即为识别结果。


图.DTW算法原理

图.局部约束路径

以下就是matlab对于DTW算法的具体实现:

function dist = dtw(t,r)

n = size(t,1);

m = size(r,1);

%帧匹配距离矩阵

d = zeros(n,m);

for i = 1:n

for j = 1:m

    d(i,j) = sum((t(i,:)-r(j,:)).^2);

end

end

%累积距离矩阵

D =  ones(n,m) * realmax;

D(1,1) = d(1,1);

%动态规划

for i = 2:n

for j = 1:m

    D1 = D(i-1,j);

    if j>1

        D2 = D(i-1,j-1);

    else

        D2 = realmax;

    end

    if j>2

        D3 = D(i-1,j-2);

    else

        D3 = realmax;

    end

    D(i,j) = d(i,j) + min([D1,D2,D3]);

end

end

dist = D(n,m);

图.DTW语音识别算法测试结果

最终测试结果如图,我们可以完成特定孤立词的识别,其实这种局部优化的想法还有很多地方被使用到,如N皇后的解法上,我们可以采用的比较快速的方法中就有局部搜索法。在语音识别我们除了梅尔倒谱还可以采用LPC(Linear Prediction Coefficient,线性预测系数)推导出的LPCC(LinearPrediction Cepstrum Coefficient,线性预测倒谱系数),但是据说其对辅音结果差,对元音结果好,以上介绍的DTW算法实际上也是在英语的识别率上比较高,实际上英语的识别应该要比汉语简单,在话语识别技术上,我们还需要考虑语音合成技术等一系列如何组成一段语音的方法,才能够方便实现。



没有更多推荐了,返回首页