2009-02-10 17:19:00 chenlanmin 阅读数 1402
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

语音识别技术是2000年至2010年间信息技术领域十大重要的科技发展技术之一。它是一门交叉学科,正逐步成为信息技术中人机接口的关键技术。语音识别 技术与语音合成技术结合使人们能够甩掉键盘,通过语音命令进行操作。语音技术的应用已经成为一个具有竞争性的新兴高技术产业。

语音识别技术

与 机器进行语音交流,让机器明白你说什么,这是人们长期以来梦寐以求的事情。语音识别技术就是让机器通过识别和理解过程把语音信号转变为相应的文本或命令的 高技术。语音识别是一门交叉学科。近二十年来,语音识别技术取得显著进步,开始从实验室走向市场。人们预计,未来10年内,语音识别技术将进入工业、家 电、通信、汽车电子、医疗、家庭服务、消费电子产品等各个领域。
语音识别听写机在一些领域的应用被美国新闻界评为1997年计算机发展十件大事之一。很多专家都认为语音识别技术是2000年至2010年间信息技术领域十大重要的科技发展技术之一。

语音识别技术的基础

语音识别技术关系到多学科的研究领域,不同领域上的研究成果都对语音识别的发展作了贡献。

让机器识别语音的困难在某种程度上就像一个外语不好的人听外国人讲话一样,它和不同的说话人、不同的说话速度、不同的说话内容、以及不同的环境条件有关。语音信号本身的特点造成了语音识别的困难。这些特点包括多变性,动态性,瞬时性和连续性等。

计算机语音识别过程与人对语音识别处理过程基本上是一致的。目前主流的语音识别技术是基于统计模式识别的基本理论。一个完整的语音识别系统可大致分为三部分:

(1)语音特征提取:其目的是从语音波形中提取出随时间变化的语音特征序列。

(2)声学模型与模式匹配(识别算法):声学模型通常将获取的语音特征通过学习算法产生。在识别时将输入的语音特征同声学模型(模式)进行匹配与比较,得到最佳的识别结果。

(3)语言模型与语言处理:语言模型包括由识别语音命令构成的语法网络或由统计方法构成的语言模型,语言处理可以进行语法、语义分析。对小词表语音识别系统,往往不需要语言处理部分。

声 学模型是识别系统的底层模型,并且是语音识别系统中最关键的一部分。声学模型的目的是提供一种有效的方法计算语音的特征矢量序列和每个发音模板之间的距 离。声学模型的设计和语言发音特点密切相关。声学模型单元大小(字发音模型、半音节模型或音素模型)对语音训练数据量大小、系统识别率,以及灵活性有较大 的影响。必须根据不同语言的特点、识别系统词汇量的大小决定识别单元的大小。

语言模型对中、大词汇量的语音识别系统特别重要。当分类发生 错误时可以根据语言学模型、语法结构、语义学进行判断纠正,特别是一些同音字则必须通过上下文结构才能确定词义。语言学理论包括语义结构、语法规则、语言 的数学描述模型等有关方面。目前比较成功的语言模型通常是采用统计语法的语言模型与基于规则语法结构命令语言模型。语法结构可以限定不同词之间的相互连接 关系,减少了识别系统的搜索空间,这有利于提高系统的识别。

语音识别过程实际上是一种认识过程。就像人们听语音时,并不把语音和语言的语法结构、语义结构分开来,因为当语音发音模糊时人们可以用这些知识来指导对语言的理解过程,但是对机器来说,识别系统也要利用这些方面的知识,只是如何有效地描述这些语法和语义还有困难:

(1)小词汇量语音识别系统。通常包括几十个词的语音识别系统。

(2)中等词汇量的语音识别系统。通常包括几百个词至上千个词的识别系统。

(3)大词汇量语音识别系统。通常包括几千至几万个词的语音识别系统。这些不同的限制也确定了语音识别系统的困难度。

语音识别技术的发展情况

我 国语音识别研究工作起步于五十年代,但近年来发展很快。研究水平也从实验室逐步走向实用。从1987年开始执行国家863计划后,国家863智能计算机专 家组为语音识别技术研究专门立项,每两年滚动一次。我国语音识别技术的研究水平已经基本上与国外同步,在汉语语音识别技术上还有自己的特点与优势,并达到 国际先进水平。其中具有代表性的研究单位为清华大学电子工程系与中科院自动化研究所模式识别国家重点实验室。

清华大学电子工程系语音技术 与专用芯片设计课题组,研发的非特定人汉语数码串连续语音识别系统的识别精度,达到94.8%(不定长数字串)和96.8%(定长数字串)。在有5%的拒 识率情况下,系统识别率可以达到96.9%(不定长数字串)和98.7%(定长数字串),这是目前国际最好的识别结果之一,其性能已经接近实用水平。研发 的5000词邮包校核非特定人连续语音识别系统的识别率达到98.73%,前三选识别率达99.96%;并且可以识别普通话与四川话两种语言,达到实用要 求。

2000年7月在北京自然博物馆新开设的动物展馆中展出的具有语音识别口语对话功能“熊猫”,采用了我们研发非特定人连续语音识别系 统,在展览馆这样高噪声的环境下,该识别系统的识别率也超过了98%,达到实用要求。通过该系统观众与“熊猫”自然对话可以了解熊猫的生活习惯、生理结构 等信息,其形式生动、活泼,吸引了大量的学生与参观者。

采用嵌入式芯片设计技术研发了语音识别专用芯片系统,该芯片以8位微控制器 (MCU)核心,加上低通滤波器,模/数(A/D),数/模(D/A),预放,功率放大器,RAM,ROM,脉宽调幅(PWM)等模块,构成了一个完整的 系统芯片,这是国内研发的第一块语音识别专用芯片。芯片中包括了语音识别、语音编码、语音合成功能,可以识别30条特定人语音命令,识别率超过95%,其 中的语音编码速率为16kbits/s。该芯片可以用于智能语音玩具;也可以与普通电话机相结合构成语音拨号电话机。这些系统的识别性能完全达到国际先进 水平。研发的成果已经进入实用领域,一些应用型产品正在研发中,其商品化的过程也越来越快。

语音识别技术的前景和应用

在 电话与通信系统中,智能语音接口正在把电话机从一个单纯的服务工具变成为一个服务的“提供者”和生活“伙伴”;使用电话与通信网络,人们可以通过语音命令 方便地从远端的数据库系统中查询与提取有关的信息;随着计算机的小型化,键盘已经成为移动平台的一个很大障碍,想象一下如果手机仅仅只有一个手表那么大, 再用键盘进行拨号操作已经是不可能的。语音识别正逐步成为信息技术中人机接口的关键技术,语音识别技术与语音合成技术结合使人们能够甩掉键盘,通过语音命 令进行操作。语音技术的应用已经成为一个具有竞争性的新兴高技术产业。

语音识别技术发展到今天,特别是中小词汇量非特定人语音识别系统识 别精度已经大于98%,对特定人语音识别系统的识别精度就更高。这些技术已经能够满足通常应用的要求。由于大规模集成电路技术的发展,这些复杂的语音识别 系统也已经完全可以制成专用芯片,大量生产。在西方经济发达国家,大量的语音识别产品已经进入市场和服务领域。一些用户交机、电话机、手机已经包含了语音 识别拨号功能,还有语音记事本、语音智能玩具等产品也包括语音识别与语音合成功能。人们可以通过电话网络用语音识别口语对话系统查询有关的机票、旅游、银 行信息,并且取得很好的结果。调查统计表明多达85%以上的人对语音识别的信息查询服务系统的性能表示满意。

可以预测在近五到十年内,语 音识别系统的应用将更加广泛。各种各样的语音识别系统产品将出现在市场上。人们也将调整自己的说话方式以适应各种各样的识别系统。在短期内还不可能造出具 有和人相比拟的语音识别系统,要建成这样一个系统仍然是人类面临的一个大的挑战,我们只能一步步朝着改进语音识别系统的方向一步步地前进。至于什么时候可 以建立一个像人一样完善的语音识别系统则是很难预测的。就像在60年代,谁又能预测今天超大规模集成电路技术会对我们的社会产生这么大的影响。

2014-12-17 21:59:40 ninggezhenbang 阅读数 4296
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

语音云开放平台是科大讯飞股份有限公司旗下的全球首个面向互联网开发者的智能语音交互平台,为开发者免费开放语音识别、语音合成、智能语义等服务。自2010年首度在北京香格里拉饭店发布以来,吸引了各个领域的优秀APP的加盟,目前已经为数以亿计的终端提供了智能语音交互的服务。本文主要讲述其两个比较常用的功能,语音识别与文本朗读,这两个功能可以方便地嵌入各开发者的应用中。

1.搭建开发环境

  1.1 Eclipse中建立你的Android工程,如MyiFly

  1.2 Msc.jarSunflower.jar以及armeabi复制到新建工程的libs目录中,并将导进来的jarBuild Path(如下图示)。

 

  1.3 将所需的资源文件放进assets文件夹中(如下图所示)。

1.4 在AndroidManifest.xml配置如下权限

    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

1.5 在application节点下配置meta-data,value值为自己在讯飞语音云的应用秘钥

      (开发者可到讯飞语音云平台注册自己的账号和应用http://open.voicecloud.cn/)

<application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <meta-data

            android:name="IFLYTEK_APPKEY"

            android:value="myappkey" />

        <activity

            android:name=".MainActivity"

            android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden  |navigation|orientation|screenLayout|fontScale"

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

2.应用界面

  2.1 该界面很简单,只是一个EditText和两个Button,当用户点击识别时,即可将用户的讲话转成文字并显示在 EditText下。当用户在EditText输好文本点击朗读时即可将文本转为语音

  2.2布局代码

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context="com.example.myifly.MainActivity" >

 

    <EditText

        android:id="@+id/content_rec"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:hint="识别内容" />

 

    <Button

        android:id="@+id/button2"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_alignParentBottom="true"

        android:onClick="startRec"

        android:text="识别" />

 

    <Button

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_above="@+id/button2"

        android:layout_alignLeft="@+id/button2"

        android:layout_alignParentRight="true"

        android:onClick="read"

        android:text="朗读" />

 

</RelativeLayout>

3.主要代码

  3.1初始化,验证用户秘钥,// 创建语音听写对象,听写UI和音合成对象

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

this.requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

//用于验证应用的key

SpeechUtility.createUtility(MainActivity.this, "appid=548ee912");

// 创建语音听写对象

mIat = SpeechRecognizer.createRecognizer(this, mInitListener);

// 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer

// 创建语音听写UI

iatDialog = new RecognizerDialog(this, mInitListener);

// 创建语音合成对象

mTts = SpeechSynthesizer.createSynthesizer(this, mInitListener);

mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);

mResultText = ((EditText) findViewById(R.id.content_rec));

}

// mInitListener为验证用户秘钥的回调方法

private InitListener mInitListener = new InitListener() {

 

@Override

public void onInit(int code) {

Log.d(TAG, "SpeechRecognizer init() code = " + code);

if (code != ErrorCode.SUCCESS) {

showTip("初始化失败,错误码:" + code);

}

}

};

  3.2 识别

public void startRec(View view) {

mResultText.setText(null);

setParam();

boolean isShowDialog = true;

if (isShowDialog) {

// 显示听写对话框

iatDialog.setListener(recognizerDialogListener);

iatDialog.show();

// showTip("begin");

} else {

// 不显示听写对话框

ret = mIat.startListening(recognizerListener);

if (ret != ErrorCode.SUCCESS) {

// showTip("听写失败,错误码:" + ret);

} else {

// showTip("begin");

}

}

}

//注意,在使用语音听写对象要为其设置好参数,在setParam()方法中进行

public void setParam() {

// 清空参数

mIat.setParameter(SpeechConstant.PARAMS, null);

// 设置语言

mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");

// 设置语言区域

mIat.setParameter(SpeechConstant.ACCENT, "mandarin");

// 设置语音前端点

mIat.setParameter(SpeechConstant.VAD_BOS, "4000");

// 设置语音后端点

mIat.setParameter(SpeechConstant.VAD_EOS, "1000");

// 设置标点符号 1为有标点 0为没标点

mIat.setParameter(SpeechConstant.ASR_PTT, "0");

// 设置音频保存路径

mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH,

Environment.getExternalStorageDirectory()

+ "/iflytek/wavaudio.pcm");

}

当用户点击识别时会弹出下图UI

/**

 * 听写UI监听器,用户倾听用于语音,在onResult方法中获得服务器返回的识别结果

 */

private RecognizerDialogListener recognizerDialogListener = new RecognizerDialogListener() {

 

public void onResult(RecognizerResult results, boolean isLast) {

String text = JsonParser.parseIatResult(results.getResultString());

mResultText.append(text);

mResultText.setSelection(mResultText.length());

}

/**

 * 识别回调错误.

 */

public void onError(SpeechError error) {

showTip(error.getPlainDescription(true));

}

};

本文用UI返回结果所以将isShowDialog 设为 true,如果你不用的话就使用下面的识别方式

/**

 * 听写监听器。

 */

private RecognizerListener recognizerListener = new RecognizerListener() {

@Override

public void onBeginOfSpeech() {

showTip("开始说话");

}

 

@Override

public void onEndOfSpeech() {

showTip("结束说话");

}

 

@Override

public void onResult(RecognizerResult results, boolean isLast) {

String text = JsonParser.parseIatResult(results.getResultString());

mResultText.append(text);

mResultText.setSelection(mResultText.length());

if (isLast) {

// TODO 最后的结果

}

}

@Override

public void onVolumeChanged(int volume) {

showTip("当前正在说话,音量大小:" + volume);

}

 

@Override

public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {

}

 

@Override

public void onError(SpeechError arg0) {

// TODO Auto-generated method stub

}

 

};

  3.3朗读功能

public void read(View view) {

String text = mResultText.getText().toString();

// 设置参数

setParam2();

//朗读

int code = mTts.startSpeaking(text, mTtsListener);

if (code != ErrorCode.SUCCESS) {

if (code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED) {

// 未安装则跳转到提示安装页面

} else {

showTip("语音合成失败,错误码: " + code);

}

}

}

setParam2()为语音合成对象设置如下参数

/**

 * 参数设置

 * 

 * @param param

 * @return

 */

private void setParam2() {

 

// 设置合成

mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);

// 设置发音人

mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);

// 设置语速

mTts.setParameter(SpeechConstant.SPEED, "50");

// 设置音调

mTts.setParameter(SpeechConstant.PITCH, "50");

// 设置音量

mTts.setParameter(SpeechConstant.VOLUME, "50");

// 设置播放器音频流类型

mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");

}

 

mTtsListener为合成语音对象回调监听,监听内容看监听方法名称即可知道

/**

 * 

 */

private SynthesizerListener mTtsListener = new SynthesizerListener() {

@Override

public void onSpeakBegin() {

showTip("开始播放");

}

 

@Override

public void onSpeakPaused() {

showTip("暂停播放");

}

 

@Override

public void onSpeakResumed() {

showTip("继续播放");

}

 

@Override

public void onBufferProgress(int percent, int beginPos, int endPos,

String info) {

mPercentForBuffering = percent;

showTip(String.format(getString(R.string.tts_toast_format),

mPercentForBuffering, mPercentForPlaying));

}

 

@Override

public void onSpeakProgress(int percent, int beginPos, int endPos) {

mPercentForPlaying = percent;

showTip(String.format(getString(R.string.tts_toast_format),

mPercentForBuffering, mPercentForPlaying));

}

 

@Override

public void onCompleted(SpeechError error) {

if (error == null) {

showTip("播放完成");

} else if (error != null) {

showTip(error.getPlainDescription(true));

}

}

 

@Override

public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {

 

}

};

 4.结语

至此,整个讯飞语音云的语音识别与文本朗读功能介绍完毕,希望对大家有帮助。


 5.MyiFly下载链接 http://download.csdn.net/detail/ninggezhenbang/8271675


 

 


2018-04-09 23:12:33 wangzhanxidian 阅读数 142
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

参考:http://www.julyedu.com/video/play/104/916

    语音信号的频率一般在300Hz-3400Hz,按照奈奎斯特采样定理,为保证频谱不混叠,采样率至少为最高频率的2倍,一般最低采样率为8000Hz。

    在2010年以前,语音识别的技术主要基于混合高斯模型(GMM)和隐性马尔科夫(HMM)模型,2010年以后,主要基于神经网络。该讲座主要是讲怎样将语音转换成文字,相关课题包括(本讲座不涉及)

-元数据识别:语种、说话人、情感等

-语音增强与分离

-语音合成(文字变语音)与转换

-自然语言理解、对话系统

 

孤立词识别

1.特征提取

    (1)分段提取,一段即一帧,一帧信号通常为20-50ms,包含2-3个周期,在一个音素(如你好,n、i、h 、a、o是一个音素)内(保证傅里叶变换区间的稳定性)。

    (2)傅里叶变换—>三角滤波—>离散余弦变换(DCT)

男声的基频在100Hz左右,女声的基频在200Hz左右,频谱具有精细结构和包络,通过三角滤波提取频谱的包络。

 

MFCC序列是最常用的特征

 

2.“动态弯(Dynamic Time Warping)”算法(计算两个特征序列的举例)

通过动态规划算法匹配待计算距离的两个帧,总距离为各帧欧式距离之和。

 

3. GMM(混合高斯模型)

如果Yes这个单词有多个模板怎么办?模板—>模型

以其中一个模板为标准,其他模板与之对齐,把模板切分成多个段落,用高斯分布的叠加拟合每段中特征向量的分布。

通过期望最大化估计GMM模型的参数。

 

4. HMM(隐性马尔科夫模型)

对音素持续时间建模(添加状态间的转移概率)

模型的参数:

-转移概率

-观测概率

-模型是单向的,不必讨论初始概率

 

 

EM训练算法

-如果知道对齐方式,则易得模型参数,知道模型参数,则易得对齐方式,现在是都不知道,先瞎猜一种对齐方式,如均匀分割,由此求出模型参数(M步),再更新对齐方式(E步),对齐方式可用Viterbi,实际中用Forward-backward,迭代直到收敛。

2013-04-24 09:26:09 xiaoding133 阅读数 4634
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

          研究生期间收集了一些有关语音识别方面的网址,感觉非常有用,保留一下,留到以后用。

国际最顶尖会议:
ICASSP:International Conference on Acoustics, Speech and Signal Processing
ICSLP:International Conference on Semiconductor Laser and Photonics
EUROSPEECH:European Conference on Speech Communication and Technology
其他
ICSMC:Int l Conference on Systems, Man & Cybernetics
NAECON:National Aerospace and Electronics Conference
ICTTA:International Conference on Telecommunication Technology and Applications
ISSPA: Information Sciences, Signal Processing and their Applications
ISPACS:International Symposium on Intelligent Signal Processing and Communications Systems
SBEC:Southern Biomedical Engineering Conference
ICAPR:International Conference on Advances in Pattern Recognition
ICOSP: International Conference on Signal Processing Proceedings
ICSLP: International Conference on Spoken Language Processing
ICICIC:International Conference on Innovative Computing, Information and Control
IEMBS:Institute of Electrical and Electronics Engineers
NLPKE: Natural Language Processing and Knowledge Engineering
IECON:Conference of the IEEE Industrial Electronics Society
ICCT:International Council on Clean Transportation
ASRU:Automatic Speech Recognition and Understanding
ISCAS:International Symposium on Circuits and Systems
ISPACS:International Symposium on Intelligent Signal Processing and Communications Systems
ICDSP:International Conference on Digital Signal Processing
SPAWC:signal processing advances in wireless communications
ICCSIT: International Conference on Computer Science and Information Technology
ICSE: International Conference on Software Engineering
ICIAS:International Conference on Intelligent and Advanced Systems
TENCON:Technical Environmental Consulting
ICFCC:International Conference on Future Computer and Communication
WCICA:World Congress on Intelligent Control and Automation
MMSP:international workshop on multimedia signal processing
IROS: Intelligent Robots and Systems
ICSDA: INTERNATIONAL COMBATIVES SELF DEFENSE ASSOCIATION
ICCCE:International Conference on Computer and Communication Engineering
其他的会议还有:ISPA,ASPAA,INDICO,NetCom等

期刊方面:
国内:信号处理,电子学报、声学学报,应用声学,声学工程
国外:最著名的:IEEE Signal Processing Magazine (IF:2.655),一年6期,是双月刊)
            还有IEEE Transactions on Signal Processing (TSP)-- (IF:1.57)
                IEEE Transactions on Circuits and Systems-I: Regular Papers (CAS-I)---(IF:1.139)
                Signal Processing: Image Communication (IF: 1.109)
                IEE Electronics Letters (IF:1.063)
                IEEE Transactions on Circuits and Systems-II: Express Briefs (CAS-II)---(IF:0.922)
                Digital Signal Processing(IF: 0.889)
                IEEE Signal Processing Letters (SPL)---(IF: 0.722)
                Signal Processing (IF: 0.669)
                IET Signal Processing
其中IF为影响因子


1.1 国际语音识别技术研究机构
AT&T 
http://www.research.att.com/editions/201304_home.html
ATR    http://www.slt.atr.co.jp/index.html
BBN    http://www.bbn.com/technology/speech_recognition/
Cambridge University Engineering Department (CUED) http://mi.eng.cam.ac.uk/
Carnegie Mellon University (CMU)
HP Labs  
http://www.hpl.hp.com/
Columbia University
Centre for Speech Technology Research at Edinburgh University
ESAT - PSI Speech Group at K.U.Leuven
International Computer Science Institute (ICSI)
IBM Human Language Technologies    
http://www.research.ibm.com/hlt/
IDIAP Research Institute
INESC-ID Lisboa, Spoken Language Systems Lab
IRST
ISIP
Johns Hopkins University (CLSP)
Speech, Music and Hearing at KTH
LIMSI
Alcatel Lucent (Bell Labs) 
http://www.alcatel-lucent.com/wps/portal/BellLabs
Microsoft    http://research.microsoft.com/en-us/groups/speech/
MIT Spoken Language Systems
Oregon Graduate Institute (OGI) Center for Spoken Language Understanding
Speech and Language Processing Laboratory at Rutgers University
RWTH Aachen
University of Colorado, Boulder (CLEAR)
University of Sheffield
SRI
Furui Laboratory, Tokyo Institute of Technology
University of Illinois at Urbana and Champaign
University of Washington
Universitaet Erlangen-Nürnberg

剑桥大学
http://htk.eng.cam.ac.uk/

CMU大学
http://www.speech.cs.cmu.edu/

张智星 语音识别,机器学习
http://mirlab.org/jang/
安徽科大讯飞
http://www.iflytek.com/

1.2 国际语音识别技术期刊
(1)Speech Communication
(2)Computer Speech and Language (CSL)
(3)IEEE Transactions on Speech and Audio Processing

1.3 国际语音识别技术会议
(1)ICASSP(International Conference on Acoustic, Speech and Signal Processing)
每年一届,10月截稿,次年5月开会。
(2)ICSLP(International Conference on Spoken Language Processing)
偶数年举办,4月截稿,9月开会。
(3)EuroSpeech:奇数年举办,4月截稿,9月开会。

1.4 国际语音识别技术评测
 NIST Spoken Language Technology Evaluations Benchmark Tests
(
http://www.nist.gov/speech/tests/index.htm)

1.5 语音识别技术工具包
 AT&T FSM Library
 CMU-Cambridge Statistical LM Toolkit
 CMU Sphinx
 CSLU toolkit
 CUED HTK
 Edinburgh Speech Tools Library
 KTH WaveSurfer
 MSState ASR Toolkit
 NIST Utility Software
 SPRACHcore software package
 SRI Language Modelling Toolkit
 SoX -- Sound eXchange
 Transcriber
 UCL Speech Filing System
 FBVIEW multi-channel audio file viewer

1.6语音识别网站及相关论坛

http://www.voxforge.org/home/forums/message-boards/acoustic-model-discussions
http://bbs.matwav.com
http://www.yuyinshibie.com/
http://www.ctiforum.com/voice.html
http://liceu.uab.es/~joaquim/phonetics/fon_anal_acus/herram_anal_acus.html
http://www.phon.ucl.ac.uk/resource/scribe/

2019-04-27 23:33:11 qq_43433255 阅读数 429
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

语音识别是一门交叉学科。近二十年来,语音识别技术取得显著进步,开始从实验室走向市场。人们预计,未来10年内,语音识别技术将进入工业、家电、通信、汽车电子、医疗、家庭服务、消费电子产品等各个领域。 语音识别听写机在一些领域的应用被美国新闻界评为1997年计算机发展十件大事之一。很多专家都认为语音识别技术是2000年至2010年间信息技术领域十大重要的科技发展技术之一。 语音识别技术所涉及的领域包括:信号处理、模式识别、概率论和信息论、发声机理和听觉机理、人工智能等等。

此次用的是python3.6的版本实现的,安装一些相关模块sklearn:

pip install sklearn

会自动下载相关的包,好像一般来说,是下载最新的(不敢确认)。
在这里插入图片描述
中间也可能会存在一定的错误,导致失败,但可以重新,继续下载,反正我是这样的。
在这里插入图片描述
知道成功安装。

gParam的代码:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
u'''
Created on 2019年4月27日

@author: wuluo
'''
__author__ = 'wuluo'
__version__ = '1.0.0'
__company__ = u'重庆交大'
__updated__ = '2019-04-27'

TRAIN_DATA_PATH = 'G:/2018and2019two/duomeitijishu/data/train/'
TEST_DATA_PATH = 'G:/2018and2019two/duomeitijishu/data/test/'
NSTATE = 4
NPDF = 3
MAX_ITER_CNT = 100
NUM = 10

if __name__ == "__main__":
    pass

对于读入的路径,我用的是绝对路径,也就是写死。
test的代码:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
u'''
Created on 2019年4月27日

@author: wuluo
'''
__author__ = 'wuluo'
__version__ = '1.0.0'
__company__ = u'重庆交大'
__updated__ = '2019-04-27'

import numpy as np
from numpy import *
from duomeiti import gParam
from duomeiti import my_hmm
from my_hmm import gmm_hmm  #可会出现报错,但实际运行起来,没有问题
my_gmm_hmm = gmm_hmm()

my_gmm_hmm.loadWav(gParam.TRAIN_DATA_PATH)
my_gmm_hmm.hmm_start_train()
my_gmm_hmm.recog(gParam.TEST_DATA_PATH)

if __name__ == "__main__":
    pass

在编译与修改代码的边缘,疯狂试探;
在这里插入图片描述
主要还是python版本的原因,版本的不同,有些函数的用法也不同。具体详细请见这个网址:https://www.runoob.com/python3/python3-att-list-extend.html

my_hmm的代码:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
u'''
Created on 2019年4月27日

@author: wuluo
'''
__author__ = 'wuluo'
__version__ = '1.0.0'
__company__ = u'重庆交大'
__updated__ = '2019-04-27'

import numpy as np
from numpy import *
from sklearn.cluster import KMeans
from scipy import sparse
import scipy.io as sio
from scipy import signal
import wave
import math
from duomeiti import gParam
import copy

def pdf(m, v, x):
    est_v = np.prod(v, axis=0)
    test_x = np.dot((x - m) / v, x - m)
    p = (2 * math.pi * np.prod(v, axis=0))**-0.5 * \
        np.exp(-0.5 * np.dot((x - m) / v, x - m))
    return p

class sampleInfo:
    def __init__(self):
        self.smpl_wav = []
        self.smpl_data = []
        self.seg = []
    def set_smpl_wav(self, wav):
        self.smpl_wav.append(wav)
    def set_smpl_data(self, data):
        self.smpl_data.append(data)
    def set_segment(self, seg_list):
        self.seg = seg_list

class mixInfo:
    def __init__(self):
        self.Cmean = []
        self.Cvar = []
        self.Cweight = []
        self.CM = []

class hmmInfo:
    def __init__(self):
        self.init = []  # 初始矩阵
        self.trans = []  # 转移概率矩阵
        self.mix = []  # 高斯混合模型参数
        self.N = 0  # 状态数

class gmm_hmm:
    def __init__(self):
        self.hmm = []  # 单个hmm序列,
        self.gmm_hmm_model = []  # 把所有的训练好的gmm-hmm写入到这个队列
        self.samples = []  # 0-9 所有的音频数据
        self.smplInfo = []  # 这里面主要是单个数字的音频数据和对应mfcc数据
        # 每一个HMM对应len(stateInfo)个状态,每个状态指定高斯个数(3)
        self.stateInfo = [gParam.NPDF, gParam.NPDF, gParam.NPDF, gParam.NPDF]
        
  def loadWav(self, pathTop):
        for i in range(gParam.NUM):
            tmp_data = []
            for j in range(gParam.NUM):
                wavPath = pathTop + str(i) + str(j) + '.wav'
                f = wave.open(wavPath, 'rb')
                params = f.getparams()
                nchannels, sampwidth, framerate, nframes = params[:4]
                str_data = f.readframes(nframes)
                # print shape(str_data)
                f.close()
                wave_data = np.fromstring(str_data, dtype=short) / 32767.0
                #wave_data.shape = -1,2
                #wave_data = wave_data.T
                #wave_data = wave_data.reshape(1,wave_data.shape[0]*wave_data.shape[1])
                # print shape(wave_data),type(wave_data)
                tmp_data.append(wave_data)
            self.samples.append(tmp_data)
   
    # 循环读数据,然后进行训练
    def hmm_start_train(self):
        Nsmpls = len(self.samples)
        for i in range(Nsmpls):
            tmpSmplInfo0 = []
            n = len(self.samples[i])
            for j in range(n):
                tmpSmplInfo1 = sampleInfo()
                tmpSmplInfo1.set_smpl_wav(self.samples[i][j])
                tmpSmplInfo0.append(tmpSmplInfo1)
            # self.smplInfo.append(tmpSmplInfo0)
            print('现在训练第' + str(i) + '个HMM模型')
            hmm0 = self.trainhmm(tmpSmplInfo0, self.stateInfo)
            print('第' + str(i) + '个模型已经训练完毕')
            # self.gmm_hmm_model.append(hmm0)
    # 训练hmm
    def trainhmm(self, sample, state):
        K = len(sample)
        print('首先进行语音参数计算-MFCC')
        for k in range(K):
            tmp = self.mfcc(sample[k].smpl_wav)
            sample[k].set_smpl_data(tmp)  # 设置MFCCdata
        hmm = self.inithmm(sample, state)
        pout = zeros((gParam.MAX_ITER_CNT, 1))
        for my_iter in range(gParam.MAX_ITER_CNT):
            print('第' + str(my_iter) + '训练')
            hmm = self.baum(hmm, sample)
            for k in range(K):
                pout[my_iter, 0] = pout[my_iter, 0] + \
                    self.viterbi(hmm, sample[k].smpl_data[0])
            if my_iter > 0:
                if(abs((pout[my_iter, 0] - pout[my_iter - 1, 0]) / pout[my_iter, 0]) < 5e-6):
                    print('收敛')
                    self.gmm_hmm_model.append(hmm)
                    return hmm
        self.gmm_hmm_model.append(hmm)

    # 获取MFCC参数
    def mfcc(self, k):
        M = 24  # 滤波器的个数
        N = 256  # 一帧语音的采样点数
        arr_mel_bank = self.melbank(M, N, 8000, 0, 0.5, 'm')
        arr_mel_bank = arr_mel_bank / np.amax(arr_mel_bank)
        #计算DCT系数, 12*24
        rDCT = 12
        cDCT = 24
        dctcoef = []
        for i in range(1, rDCT + 1):
            tmp = [np.cos((2 * j + 1) * i * math.pi * 1.0 / (2.0 * cDCT))
                   for j in range(cDCT)]
            dctcoef.append(tmp)
        # 归一化倒谱提升窗口
        w = [1 + 6 * np.sin(math.pi * i * 1.0 / rDCT)
             for i in range(1, rDCT + 1)]
        w = w / np.amax(w)
        # 预加重
        AggrK = double(k)
        AggrK = signal.lfilter([1, -0.9375], 1, AggrK)  # ndarray
        #AggrK = AggrK.tolist()
        # 分帧
        FrameK = self.enframe(AggrK[0], N, 80)
        n0, m0 = FrameK.shape
        for i in range(n0):
            #temp = multiply(FrameK[i,:],np.hamming(N))
            # print shape(temp)
            FrameK[i, :] = multiply(FrameK[i, :], np.hamming(N))
        FrameK = FrameK.T
        # 计算功率谱
        S = (abs(np.fft.fft(FrameK, axis=0)))**2
        # 将功率谱通过滤波器组
        P = np.dot(arr_mel_bank, S[0:129, :])
        # 取对数后做余弦变换
        D = np.dot(dctcoef, log(P))
        n0, m0 = D.shape
        m = []
        for i in range(m0):
            m.append(np.multiply(D[:, i], w))
        n0, m0 = shape(m)
        dtm = zeros((n0, m0))
        for i in range(2, n0 - 2):
            dtm[i, :] = -2 * m[i - 2][:] - m[i - 1][:] + \
                m[i + 1][:] + 2 * m[i + 2][:]
        dtm = dtm / 3.0
        # cc = [m,dtm]
        cc = np.column_stack((m, dtm))
        # cc.extend(list(dtm))
        cc = cc[2:n0 - 2][:]
        # print shape(cc)
        return cc
        
    # melbank
    def melbank(self, p, n, fs, f1, fh, w):
        f0 = 700.0 / (1.0 * fs)
        fn2 = floor(n / 2.0)
        lr = math.log((float)(f0 + fh) / (float)(f0 + f1)) / (float)(p + 1)
        tmpList = [0, 1, p, p + 1]
        bbl = []
        for i in range(len(tmpList)):
            bbl.append(n * ((f0 + f1) * math.exp(tmpList[i] * lr) - f0))
        #b1 = n*((f0+f1) * math.exp([x*lr for x in tmpList]) - f0)
        # print bbl
        b2 = ceil(bbl[1])
        b3 = floor(bbl[2])
        if(w == 'y'):
            pf = np.log((f0 + range(b2, b3) / n) / (f0 + f1)) / lr  # note
            fp = floor(pf)
            r = [ones((1, b2)), fp, fp + 1, p * ones((1, fn2 - b3))]
            c = [range(0, b3), range(b2, fn2)]
            v = 2 * [0.5, ones((1, b2 - 1)), 1 - pf + fp,
                     pf - fp, ones((1, fn2 - b3 - 1)), 0.5]
            mn = 1
            mx = fn2 + 1
        else:
            b1 = floor(bbl[0]) + 1
            b4 = min([fn2, ceil(bbl[3])]) - 1
            pf = []
            for i in range(int(b1), int(b4 + 1), 1):
                pf.append(math.log((f0 + (1.0 * i) / n) / (f0 + f1)) / lr)
            fp = floor(pf)
            pm = pf - fp
            k2 = b2 - b1 + 1
            k3 = b3 - b1 + 1
            k4 = b4 - b1 + 1
            r = fp[int(k2 - 1):int(k4)]
            r1 = 1 + fp[0:int(k3)]
            r = r.tolist()
            r1 = r1.tolist()
            r.extend(r1)
            #r = [fp[int(k2-1):int(k4)],1+fp[0:int(k3)]]
            c = list(range(int(k2), int(k4 + 1)))
            c2 = list(range(1, int(k3 + 1)))
            # c = c.tolist()
            # c2 = c2.tolist()
            c.extend(c2)
            #c = [range(int(k2),int(k4+1)),range(0,int(k3))]
            v = 1 - pm[int(k2 - 1):int(k4)]
            v = v.tolist()
            v1 = pm[0:int(k3)]
            v1 = v1.tolist()
            v.extend(v1)  # [1-pm[int(k2-1):int(k4)],pm[0:int(k3)]]
            v = [2 * x for x in v]
            mn = b1 + 1
            mx = b4 + 1
        if(w == 'n'):
            v = 1 - math.cos(v * math.pi / 2)
        elif (w == 'm'):
            tmpV = []
            # for i in range(v):
            #     tmpV.append(1-0.92/1.08*math.cos(v[i]*math))
            v = [1 - 0.92 / 1.08 * math.cos(x * math.pi / 2) for x in v]
        # print type(c),type(mn)
        col_list = [x + int(mn) - 2 for x in c]
        r = [x - 1 for x in r]
        x = sparse.coo_matrix((v, (r, col_list)), shape=(p, 1 + int(fn2)))
        matX = x.toarray()
        #np.savetxt('./data.csv',matX, delimiter=' ')
        return matX  # x.toarray()
        
    # 分帧函数
    def enframe(self, x, win, inc):
        nx = len(x)
        try:
            nwin = len(win)
        except Exception as err:
            # print err
            nwin = 1
        if (nwin == 1):
            wlen = win
        else:
            wlen = nwin
        # print inc,wlen,nx
        # here has a bug that nf maybe less than 0
        nf = fix(1.0 * (nx - wlen + inc) / inc)
        f = zeros((int(nf), wlen))
        indf = [inc * j for j in range(int(nf))]
        indf = (mat(indf)).T
        inds = mat(range(wlen))
        indf_tile = tile(indf, wlen)
        inds_tile = tile(inds, (int(nf), 1))
        mix_tile = indf_tile + inds_tile
        for i in range(int(nf)):
            for j in range(wlen):
                f[i, j] = x[mix_tile[i, j]]
                # print x[mix_tile[i,j]]
        if nwin > 1:  # TODOd
            w = win.tolist()
            #w_tile = tile(w,(int))
        return f
        
    # init hmm
    def inithmm(self, sample, M):
         K = len(sample)
        N0 = len(M)
        self.N = N0
        # 初始概率矩阵
        hmm = hmmInfo()
        hmm.init = zeros((N0, 1))
        hmm.init[0] = 1
        hmm.trans = zeros((N0, N0))
        hmm.N = N0
        # 初始化转移概率矩阵
        for i in range(self.N - 1):
            hmm.trans[i, i] = 0.5
            hmm.trans[i, i + 1] = 0.5
        hmm.trans[self.N - 1, self.N - 1] = 1
        # 概率密度函数的初始聚类
        # 分段
        for k in range(K):
            T = len(sample[k].smpl_data[0])
            #seg0 = []
            seg0 = np.floor(arange(0, T, 1.0 * T / N0))
            #seg0 = int(seg0.tolist())
            seg0 = np.concatenate((seg0, [T]))
            # seg0.append(T)
            sample[k].seg = seg0
        # 对属于每个状态的向量进行K均值聚类,得到连续混合正态分布
        mix = []
        for i in range(N0):
            vector = []
            for k in range(K):
                seg1 = int(sample[k].seg[i])
                seg2 = int(sample[k].seg[i + 1])
                tmp = []
                tmp = sample[k].smpl_data[0][seg1:seg2][:]
                if k == 0:
                    vector = np.array(tmp)
                else:
                    vector = np.concatenate((vector, np.array(tmp)))
                # vector.append(tmp)
            # tmp_mix = mixInfo()
            # print id(tmp_mix)
            tmp_mix = self.get_mix(vector, M[i], mix)
            # mix.append(tmp_mix)
        hmm.mix = mix
        return hmm
        
    # get mix data
    def get_mix(self, vector, K, mix0):
        kmeans = KMeans(n_clusters=K, random_state=0).fit(np.array(vector))
        # 计算每个聚类的标准差,对角阵,只保存对角线上的元素
        mix = mixInfo()
        var0 = []
        mean0 = []
        #ind = []
        for j in range(K):
            #ind = [i for i in kmeans.labels_ if i==j]
            ind = []
            ind1 = 0
            for i in kmeans.labels_:
                if i == j:
                    ind.append(ind1)
                ind1 = ind1 + 1
            tmp = [vector[i][:] for i in ind]
            var0.append(np.std(tmp, axis=0))
            mean0.append(np.mean(tmp, axis=0))
        weight0 = zeros((K, 1))
        for j in range(K):
            tmp = 0
            ind1 = 0
            for i in kmeans.labels_:
                if i == j:
                    tmp = tmp + ind1
                ind1 = ind1 + 1
            weight0[j] = tmp
        weight0 = weight0 / weight0.sum()
        mix.Cvar = multiply(var0, var0)
        mix.Cmean = mean0
        mix.CM = K
        mix.Cweight = weight0
        mix0.append(mix)
        return mix0
        
    # baum-welch 算法实现函数体
    def baum(self, hmm, sample):
        mix = copy.deepcopy(hmm.mix)  # 高斯混合
        N = len(mix)  # HMM状态数
        K = len(sample)  # 语音样本数
        SIZE = shape(sample[0].smpl_data[0])[1]  # 参数阶数,MFCC维数
        print('计算样本参数.....')
        c = []
        alpha = []
        beta = []
        ksai = []
        gama = []
        for k in range(K):
            c0, alpha0, beta0, ksai0, gama0 = self.getparam(
                hmm, sample[k].smpl_data[0])
            c.append(c0)
            alpha.append(alpha0)
            beta.append(beta0)
            ksai.append(ksai0)
            gama.append(gama0)
        # 重新估算概率转移矩阵
        print('----- 重新估算概率转移矩阵 -----')
        for i in range(N - 1):
            denom = 0
            for k in range(K):
                ksai0 = ksai[k]
                tmp = ksai0[:, i, :]  # ksai0[:][i][:]
                denom = denom + sum(tmp)
            for j in range(i, i + 2):
                norm = 0
                for k in range(K):
                    ksai0 = ksai[k]
                    tmp = ksai0[:, i, j]  # [:][i][j]
                    norm = norm + sum(tmp)
                hmm.trans[i, j] = norm / denom
        # 重新估算发射概率矩阵,即GMM的参数
        print('----- 重新估算输出概率矩阵,即GMM的参数 -----')
        for i in range(N):
            for j in range(mix[i].CM):
                nommean = zeros((1, SIZE))
                nomvar = zeros((1, SIZE))
                denom = 0
                for k in range(K):
                    gama0 = gama[k]
                    T = shape(sample[k].smpl_data[0])[0]
                    for t in range(T):
                        x = sample[k].smpl_data[0][t][:]
                        nommean = nommean + gama0[t, i, j] * x
                        nomvar = nomvar + gama0[t, i, j] * \
                            (x - mix[i].Cmean[j][:])**2
                        denom = denom + gama0[t, i, j]
                hmm.mix[i].Cmean[j][:] = nommean / denom
                hmm.mix[i].Cvar[j][:] = nomvar / denom
                nom = 0
                denom = 0
                # 计算pdf权值
                for k in range(K):
                    gama0 = gama[k]
                    tmp = gama0[:, i, j]
                    nom = nom + sum(tmp)
                    tmp = gama0[:, i, :]
                    denom = denom + sum(tmp)
                hmm.mix[i].Cweight[j] = nom / denom
        return hmm
        
    # 前向-后向算法
    def getparam(self, hmm, O):
        T = shape(O)[0]
        init = hmm.init  # 初始概率
        trans = copy.deepcopy(hmm.trans)  # 转移概率
        mix = copy.deepcopy(hmm.mix)  # 高斯混合
        N = hmm.N  # 状态数
        # 给定观测序列,计算前向概率alpha
        x = O[0][:]
        alpha = zeros((T, N))
        #----- 计算前向概率alpha -----#
        for i in range(N):  # t=0
            tmp = hmm.init[i] * self.mixture(mix[i], x)
            alpha[0, i] = tmp  # hmm.init[i]*self.mixture(mix[i],x)
        # 标定t=0时刻的前向概率
        c = zeros((T, 1))
        c[0] = 1.0 / sum(alpha[0][:])
        alpha[0][:] = c[0] * alpha[0][:]
        for t in range(1, T, 1):  # t = 1~T
            for i in range(N):
                temp = 0.0
                for j in range(N):
                    temp = temp + alpha[t - 1, j] * trans[j, i]
                alpha[t, i] = temp * self.mixture(mix[i], O[t][:])
            c[t] = 1.0 / sum(alpha[t][:])
            alpha[t][:] = c[t] * alpha[t][:]
        #----- 计算后向概率 -----#
        beta = zeros((T, N))
        for i in range(N):  # T时刻
            beta[T - 1, i] = c[T - 1]
        for t in range(T - 2, -1, -1):
            x = O[t + 1][:]
            for i in range(N):
                for j in range(N):
                    beta[t, i] = beta[t, i] + beta[t + 1, j] * \
                        self.mixture(mix[j], x) * trans[i, j]
            beta[t][:] = c[t] * beta[t][:]
        # 过渡概率ksai
        ksai = zeros((T - 1, N, N))
        for t in range(0, T - 1):
            denom = sum(np.multiply(alpha[t][:], beta[t][:]))
            for i in range(N - 1):
                for j in range(i, i + 2, 1):
                    norm = alpha[t, i] * trans[i, j] * \
                        self.mixture(mix[j], O[t + 1][:]) * beta[t + 1, j]
                    ksai[t, i, j] = c[t] * norm / denom
        # 混合输出概率 gama
        gama = zeros((T, N, max(self.stateInfo)))
        for t in range(T):
            pab = zeros((N, 1))
            for i in range(N):
                pab[i] = alpha[t, i] * beta[t, i]
            x = O[t][:]
            for i in range(N):
                prob = zeros((mix[i].CM, 1))
                for j in range(mix[i].CM):
                    m = mix[i].Cmean[j][:]
                    v = mix[i].Cvar[j][:]
                    prob[j] = mix[i].Cweight[j] * pdf(m, v, x)
                    if mix[i].Cweight[j] == 0.0:
                        print(pdf(m, v, x))
                tmp = pab[i] / pab.sum()
                tmp = tmp[0]
                temp_sum = prob.sum()
                for j in range(mix[i].CM):
                    gama[t, i, j] = tmp * prob[j] / temp_sum
        return c, alpha, beta, ksai, gama

    def mixture(self, mix, x):
        prob = 0.0
        for i in range(mix.CM):
            m = mix.Cmean[i][:]
            v = mix.Cvar[i][:]
            w = mix.Cweight[i]
            tmp = pdf(m, v, x)
            # print tmp
            prob = prob + w * tmp  # * pdf(m,v,x)
        if prob == 0.0:
            prob = 2e-100
        return prob
        
    # 维特比算法
    def viterbi(self, hmm, O):
        init = copy.deepcopy(hmm.init)
        trans = copy.deepcopy(hmm.trans)  # hmm.trans
        mix = hmm.mix
        N = hmm.N
        T = shape(O)[0]
        # 计算Log(init)
        n_init = len(init)
        for i in range(n_init):
            if init[i] <= 0:
                init[i] = -inf
            else:
                init[i] = log(init[i])
        # 计算log(trans)
        m, n = shape(trans)
        for i in range(m):
            for j in range(n):
                if trans[i, j] <= 0:
                    trans[i, j] = -inf
                else:
                    trans[i, j] = log(trans[i, j])
        # 初始化
        delta = zeros((T, N))
        fai = zeros((T, N))
        q = zeros((T, 1))
        # t=0
        x = O[0][:]
        for i in range(N):
            delta[0, i] = init[i] + log(self.mixture(mix[i], x))
        # t=2:T
        for t in range(1, T):
            for j in range(N):
                tmp = delta[t - 1][:] + trans[:][j].T
                tmp = tmp.tolist()
                delta[t, j] = max(tmp)
                fai[t, j] = tmp.index(max(tmp))
                x = O[t][:]
                delta[t, j] = delta[t, j] + log(self.mixture(mix[j], x))
        tmp = delta[T - 1][:]
        tmp = tmp.tolist()
        prob = max(tmp)
        q[T - 1] = tmp.index(max(tmp))
        for t in range(T - 2, -1, -1):
            q[t] = fai[t + 1, int(q[t + 1, 0])]
        return prob
        
 
    # 用于测试的程序 
    def vad(self, k, fs):
         k = double(k)
        k = multiply(k, 1.0 / max(abs(k)))
        
        # 计算短时过零率
        FrameLen = 240
        FrameInc = 80
        FrameTemp1 = self.enframe(k[0:-2], FrameLen, FrameInc)
        FrameTemp2 = self.enframe(k[1:], FrameLen, FrameInc)
        signs = np.sign(multiply(FrameTemp1, FrameTemp2))
        signs = list(map(lambda x: [[i, 0][i > 0] for i in x], signs))
        signs = list(map(lambda x: [[i, 1][i < 0] for i in x], signs))
        diffs = np.sign(abs(FrameTemp1 - FrameTemp2) - 0.01)
        diffs = list(map(lambda x: [[i, 0][i < 0] for i in x], diffs))
        zcr = sum(multiply(signs, diffs), 1)
        
        # 计算短时能量
        amp = sum(abs(self.enframe(signal.lfilter(
            [1, -0.9375], 1, k), FrameLen, FrameInc)), 1)
        # print '短时能量%f' %amp
        # 设置门限
        print('设置门限')
        ZcrLow = max([round(mean(zcr) * 0.1), 3])  # 过零率低门限
        ZcrHigh = max([round(max(zcr) * 0.1), 5])  # 过零率高门限
        AmpLow = min([min(amp) * 10, mean(amp) * 0.2, max(amp) * 0.1])  # 能量低门限
        AmpHigh = max([min(amp) * 10, mean(amp) *
                       0.2, max(amp) * 0.1])  # 能量高门限
                       
        # 端点检测
        MaxSilence = 8  # 最长语音间隙时间
        MinAudio = 16  # 最短语音时间
        Status = 0  # 状态0:静音段,1:过渡段,2:语音段,3:结束段
        HoldTime = 0  # 语音持续时间
        SilenceTime = 0  # 语音间隙时间
        print('开始端点检测')
        StartPoint = 0
        for n in range(len(zcr)):
            if Status == 0 or Status == 1:
                if amp[n] > AmpHigh or zcr[n] > ZcrHigh:
                    StartPoint = n - HoldTime
                    Status = 2
                    HoldTime = HoldTime + 1
                    SilenceTime = 0
                elif amp[n] > AmpLow or zcr[n] > ZcrLow:
                    Status = 1
                    HoldTime = HoldTime + 1
                else:
                    Status = 0
                    HoldTime = 0
            elif Status == 2:
                if amp[n] > AmpLow or zcr[n] > ZcrLow:
                    HoldTime = HoldTime + 1
                else:
                    SilenceTime = SilenceTime + 1
                    if SilenceTime < MaxSilence:
                        HoldTime = HoldTime + 1
                    elif (HoldTime - SilenceTime) < MinAudio:
                        Status = 0
                        HoldTime = 0
                        SilenceTime = 0
                    else:
                        Status = 3
            elif Status == 3:
                break
            if Status == 3:
                break
        HoldTime = HoldTime - SilenceTime
        EndPoint = StartPoint + HoldTime
        return StartPoint, EndPoint
        
    def recog(self, pathTop):
        N = gParam.NUM
        for i in range(N):
            wavPath = pathTop + str(i) + '.wav'
            f = wave.open(wavPath, 'rb')
            params = f.getparams()
            nchannels, sampwidth, framerate, nframes = params[:4]
            str_data = f.readframes(nframes)
            # print shape(str_data)
            f.close()
            wave_data = np.fromstring(str_data, dtype=short) / 32767.0
            x1, x2 = self.vad(wave_data, framerate)
            O = self.mfcc([wave_data])
            O = O[x1 - 3:x2 - 3][:]
            print('第' + str(i) + '个词的观察矢量是:' + str(i))
            pout = []
            for j in range(N):
                pout.append(self.viterbi(self.gmm_hmm_model[j], O))
            n = pout.index(max(pout))
            print('第' + str(i) + '个词,识别是:' + str(n))
            
if __name__ == "__main__":
                   pass
             


这里是运行结果:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

语音识别(三)

阅读数 51

语音识别技术综述

阅读数 5634

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