第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > Python语音基础操作--10.1基于动态时间规整(DTW)的孤立字语音识别试验

Python语音基础操作--10.1基于动态时间规整(DTW)的孤立字语音识别试验

时间:2018-05-09 10:34:40

相关推荐

Python语音基础操作--10.1基于动态时间规整(DTW)的孤立字语音识别试验

《语音信号处理试验教程》(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的。使用CSDN博客查看帮助文件:

Python语音基础操作–2.1语音录制,播放,读取

Python语音基础操作–2.2语音编辑

Python语音基础操作–2.3声强与响度

Python语音基础操作–2.4语音信号生成

Python语音基础操作–3.1语音分帧与加窗

Python语音基础操作–3.2短时时域分析

Python语音基础操作–3.3短时频域分析

Python语音基础操作–3.4倒谱分析与MFCC系数

Python语音基础操作–4.1语音端点检测

Python语音基础操作–4.2基音周期检测

Python语音基础操作–4.3共振峰估计

Python语音基础操作–5.1自适应滤波

Python语音基础操作–5.2谱减法

Python语音基础操作–5.4小波分解

Python语音基础操作–6.1PCM编码

Python语音基础操作–6.2LPC编码

Python语音基础操作–6.3ADPCM编码

Python语音基础操作–7.1帧合并

Python语音基础操作–7.2LPC的语音合成

Python语音基础操作–10.1基于动态时间规整(DTW)的孤立字语音识别试验

Python语音基础操作–10.2隐马尔科夫模型的孤立字识别

Python语音基础操作–11.1矢量量化(VQ)的说话人情感识别

Python语音基础操作–11.2基于GMM的说话人识别模型

Python语音基础操作–12.1基于KNN的情感识别

Python语音基础操作–12.2基于神经网络的情感识别

Python语音基础操作–12.3基于支持向量机SVM的语音情感识别

Python语音基础操作–12.4基于LDA,PCA的语音情感识别

代码可在Github上下载:busyyang/python_sound_open

基于动态时间规整(DTW)的孤立字语音识别试验

模板匹配法语音识别系统

用户将词汇表中每个词依次说一遍,并且将其特征矢量时序作为模板存入模板库,在识别阶段,将输入语音的特征矢量时间序列依次与模板库中每个模板进行相识度比较,将相识度最高者作为识别的结果输出。

特征

使用MFCC系数以及一阶和二阶差分作为特征参数。MFCC是将人耳的听觉特征与语音参数相结合的一种特征参数。MFCC的计算可以参考3.4节。

动态时间规整(DTW)

在识别阶段的模式匹配中,不能简单地将输入模板与词库中模板相比较实现识别,因为语音信号具有相当大的随机性,这些差异不仅在音强的大小,频谱的偏移,还有发音持续时间不可能是完全相同的,而词库中模板不可能睡着模板输入持续时间的变换而进行伸缩,所以时间规整是不可少的。DTW是吧时间规整和距离测度计算结合起来的非线性规整技术,是模板匹配的方法。

假设某一参考模板的特征矢量为: a 1 , . . . a m , . . . , a M a_1,...a_m,...,a_M a1​,...am​,...,aM​,输入语音的特征矢量序列 b 1 , . . , b m , . . . , b M b_1,..,b_m,...,b_M b1​,..,bm​,...,bM​,而且 M ≠ N M\neq N M​=N,那么动态时间规整就是要找到时间规整函数 m = T ( n ) m=T(n) m=T(n),把输入的时间轴n非线性映射到参考模板的时间轴 m m m上,并且满足:

D = min ⁡ T ( n ) ∑ n = 1 N d [ n , T ( n ) ] D=\underset{T(n)}{\min}\sum_{n=1}^Nd[n,T(n)] D=T(n)min​n=1∑N​d[n,T(n)]

d [ n , T ( n ) ] d[n,T(n)] d[n,T(n)]表示两个矢量之间的距离,可以采用欧式距离计算 d ( x , y ) = 1 k ∑ i = 1 k ( x i − y i ) 2 d(x,y)=\frac{1}{k}\sqrt{\sum_{i=1}^k(x_i-y_i)^2} d(x,y)=k1​∑i=1k​(xi​−yi​)2 ​,D是最佳时间路径下的两个矢量的距离测度。

这是一个典型的最优化问题,一般采用动态规划算法(DP)实现,为了方便计算,把一个N阶段的决策过程转化为N个简单段的决策过程,也就是为N个子问题逐一做出决策,根据语音信号的性质,时间规整函数要满足:

边界条件, T ( 1 ) = 1 , T ( N ) = M T(1)=1,T(N)=M T(1)=1,T(N)=M单调上升: T ( n + 1 ) − T ( n ) ⩾ 0 T(n+1)-T(n)\geqslant 0 T(n+1)−T(n)⩾0连续性限制:有些特殊音素可能会对正确识别起很大作用,某个音素的差异可能就是区分的依据,为了保证信息损失最小,规整函数一般规定不云溪跳过任何一点,即 Φ ( i n + 1 ) − Φ ( i n ) ⩽ 1 \Phi(i_n+1)-\Phi(i_n)\leqslant 1 Φ(in​+1)−Φ(in​)⩽1

使用递推的方式进行计算,也就是计算(0,0)到(N,M)点的最短距离,首先计算(N,M)前一个点到他的距离,然后在计算(0,0)到(N,M)前一个点的距离,得到最短距离。

import numpy as npfrom chapter3_分析实验.timefeature import *from chapter2_基础.soundBase import *from chapter3_分析实验.mel import *def my_vad(x):"""端点检测:param X:输入为录入语音:return:输出为有用信号"""Ini = 0.1 # 初始静默时间Ts = 0.01 # 窗的时长Tsh = 0.005 # 帧移时长Fs = 16000 # 采样频率counter1 = 0 # 以下四个参数用来寻找起始点和结束点counter2 = 0counter3 = 0counter4 = 0ZCRCountf = 0 # 用于存储过零率检测结果ZCRCountb = 0ZTh = 40 # 过零阈值w_sam = int(Ts * Fs) # 窗口长度o_sam = int(Tsh * Fs) # 帧移长度lengthX = len(x)segs = int((lengthX - w_sam) / o_sam) + 1sil = int((Ini - Ts) / Tsh) + 1win = np.hamming(w_sam)Limit = o_sam * (segs - 1) + 1FrmtIndex = [i for i in range(0, Limit, o_sam)] # 每一帧的起始位置# 短时过零率ZCR_Vector = STZcr(x, w_sam, o_sam)# 能量Erg_Vector = STMn(x, w_sam, o_sam)IMN = np.mean(Erg_Vector[:sil])IMX = np.max(Erg_Vector)l1 = 0.03 * (IMX - IMN) + IMNl2 = 4 * IMNITL = 100 * np.min((l1, l2))ITU = 10 * ITLIZC = np.mean(ZCR_Vector[:sil])stddev = np.std(ZCR_Vector[:sil])IZCT = np.min((ZTh, IZC + 2 * stddev))indexi = np.zeros(lengthX)indexj, indexk, indexl = indexi, indexi, indexi# 搜寻超过能量阈值上限的部分for i in range(len(Erg_Vector)):if Erg_Vector[i] > ITU:indexi[counter1] = icounter1 += 1ITUs = int(indexi[0])# 搜寻能量超过能量下限的部分for j in range(ITUs - 1, -1, -1):if Erg_Vector[j] < ITL:indexj[counter2] = jcounter2 += 1start = int(indexj[0]) + 1Erg_Vectorf = np.flip(Erg_Vector, axis=0)# 重复上面过程相当于找结束帧for k in range(len(Erg_Vectorf)):if Erg_Vectorf[k] > ITU:indexi[counter3] = kcounter3 += 1ITUs = int(indexk[0])for l in range(ITUs - 1, -1, -1):if Erg_Vectorf[l] < ITL:indexl[counter4] = lcounter4 += 1finish = len(Erg_Vector) - int(indexl[0]) # 第一级判决结束帧# 从第一级判决起始帧开始进行第二判决(过零率)端点检测BackSearch = np.min((start, 25))for m in range(start, start - BackSearch, -1):rate = ZCR_Vector[m]if rate > IZCT:ZCRCountb += 1realstart = mif ZCRCountb > 3:start = realstartFwdSearch = np.min((len(Erg_Vector) - finish, 25))for n in range(finish, finish + FwdSearch):rate = ZCR_Vector[n]if rate > IZCT:ZCRCountf += 1realfinish = nif ZCRCountf > 3:finish = realfinishx_start = FrmtIndex[start]x_finish = FrmtIndex[finish]trimmed_X = x[x_start:x_finish]return trimmed_Xdef myDCW(F, R):"""动态时间规划:param F:为模板MFCC参数矩阵:param R:为当前语音MFCC参数矩阵:return:cost为最佳匹配距离"""r1, c1 = F.shaper2, c2 = R.shapedistence = np.zeros((r1, r2))for n in range(r1):for m in range(r2):FR = np.power(F[n, :] - R[m, :], 2)distence[n, m] = np.sqrt(np.sum(FR)) / c1D = np.zeros((r1 + 1, r2 + 1))D[0, :] = np.infD[:, 0] = np.infD[0, 0] = 0D[1:, 1:] = distence# 寻找整个过程的最短匹配距离for i in range(r1):for j in range(r2):dmin = min(D[i, j], D[i, j + 1], D[i + 1, j])D[i + 1, j + 1] += dmincost = D[r1, r2]return costdef deltacoeff(x):"""计算MFCC差分系数:param x::return:"""nr, nc = x.shapeN = 2diff = np.zeros((nr, nc))for t in range(2, nr - 2):for n in range(N):diff[t, :] += n * (x[t + n, :] - x[t - n, :])diff[t, :] /= 10return diffdef mfccf(num, s, Fs):"""计算并返回信号s的mfcc参数及其一阶和二阶差分参数:param num::param s::param Fs::return:"""N = 512 # FFT数Tf = 0.02 # 窗口的时长n = int(Fs * Tf) # 每个窗口的长度M = 24 # M为滤波器组数l = len(s)Ts = 0.01 # 帧移时长FrameStep = int(Fs * Ts) # 帧移lifter = np.array([i for i in range(num)])lifter = 1 + int(num / 2) * np.sin(lifter * np.pi / num)if np.mean(np.abs(s)) > 0.01:s = s / np.max(s)# 计算MFCCmfcc = Nmfcc(s, Fs, M, n, FrameStep)mfcc_l = np.multiply(mfcc, lifter)d1 = deltacoeff(mfcc_l)d2 = deltacoeff(d1)return np.hstack((mfcc_l, d1, d2))def CMN(r):"""归一化:param r::return:"""return r - np.mean(r, axis=1, keepdims=True)def DTWScores(r, features, N):"""DTW寻找最小失真值:param r:为当前读入语音的MFCC参数矩阵:param features:模型参数:param N:为每个模板数量词汇数:return:"""# 初始化判别矩阵scores1 = np.zeros(N)scores2 = np.zeros(N)scores3 = np.zeros(N)for i in range(N):scores1[i] = myDCW(CMN(features['p1_{}'.format(i)]), r)scores2[i] = myDCW(CMN(features['p2_{}'.format(i)]), r)scores3[i] = myDCW(CMN(features['p2_{}'.format(i)]), r)return scores1, scores2, scores3if __name__ == '__main__':# 制作模板集features = {}for i in range(10):data, fs, bits = soundBase('p1/{}.wav'.format(i)).audioread()speechIn1 = my_vad(data)fm = mfccf(12, speechIn1, fs)features['p1_{}'.format(i)] = fmfor i in range(10):data, fs, bits = soundBase('p2/{}.wav'.format(i)).audioread()speechIn1 = my_vad(data)fm = mfccf(12, speechIn1, fs)features['p2_{}'.format(i)] = fmfor i in range(10):data, fs, bits = soundBase('p3/{}.wav'.format(i)).audioread()speechIn1 = my_vad(data)fm = mfccf(12, speechIn1, fs)features['p3_{}'.format(i)] = fmsoundBase('mysound.wav').audiorecorder(rate=16000, channels=1)data, fs, bits = soundBase('mysound.wav').audioread()mysound = my_vad(data)fm_my = mfccf(12, mysound, fs)fm_my = CMN(fm_my)scores = DTWScores(fm_my, features, 10)s = {}for i in range(len(scores)):tmp = np.argsort(scores[i])[:2]for j in tmp:if j in s.keys():s[j] += 1else:s[j] = 1print(s)s = sorted(s.items(), key=lambda x: x[1], reverse=True)[0]if np.max(data) < 0.01:print('Microphone get no signal......')elif s[1] < 2:print('The word you have said could not be properly recognised.')else:print('You just saied: {}'.format(s[0]))

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。