用PocketSphinx做离线命令词识别

  主要内容转自Android平台使用PocketSphinx做离线语音识别,小范围语音99%识别率,在此只是记录一下实现过程中遇到的坑。
  

最近语音识别很火,但是都是用的在线语音识别,研究了一下离线语音识别,小范围内的语音识别率还不错,在此记录一下
首先本文要说的两个前提1.android平台离线语音识别 2.小范围语音
小范围语音指的是相对固定的命令。本文的例子大概实现了20条语音命令,超出范围的无法识别。因此本文中离线语音的使用范围也有限,对于一些固定的输入可能有用,比如用语音命令代替打开,播放,重启这些简单的固定的命令。
先上个例子
1.按照 http://leiwuluan.iteye.com/blog/1287305 的方法,先跑一个PocketSphinxDemo的例子起来。跑起来之后会发现语音识别率很低,大概20%不到。下面来优化一下
2.编写自己的命令集
<s>百度</s>
<s>谷歌</s>
<s>音乐</s>
<s>抬头</s>
<s>低头</s>
保存为command.txt
在http://www.speech.cs.cmu.edu/tools/lmtool.html上点Browse,提交command.txt,在线生成语言模型文件。这里只要生成的lm文件,命名为test.lm。从这里下载pocketsphinx-win32,解压后在/model/lm/zh_cn有个mandarin_notone.dic的文件,打开后,搜索command.txt里面的词,然后替换相应的内容,替换后的内容如下
这里写图片描述
存为test.dic
3.替换语言模型文件。下载附件中的data.zip,解压后文件如下(之前附件中的data不可用,已更新)
这里写图片描述
分别放到一下目录
/sdcard/Android/data/test/hmm/tdt_sc_8k
/sdcard/Android/data/test/lm/test.dic
/sdcard/Android/data/test/lm/test.lm
如果要换目录的话,对应修改RecognizerTask.RecognizerTask()里的如下代码
c.setString(“-hmm”, “/sdcard/Android/data/test/hmm/tdt_sc_8k”);
c.setString(“-dict”, “/sdcard/Android/data/test/lm/test.dic”);
c.setString(“-lm”, “/sdcard/Android/data/test/lm/test.lm”);
lm和dic文件即3中生成的文件,tdt_sc_8k也可以从这里下载。
4.文件准备完毕,重新跑1中的demo。语音输入2中的命令,识别率99%以上,但是输入命令集以外的无法识别。
用PocketSphinx做离线命令词识别_第1张图片
6.附件为工程文件,将data解压,按照3里面写的位置放到sd卡里面即可。以下字典内的词可以识别
用PocketSphinx做离线命令词识别_第2张图片

按照他的方法,弄了几个小时,最终成功实现了自己的离线语音命令词识别。不过中途遇到的一些坑需要提一下,希望后面学习的朋友不再被这些困扰。
1、编写自己的命令集
  <s>百度</s>
  <s>谷歌</s>
  <s>音乐</s>
  <s>抬头</s>
  <s>低头</s>
实际上这样写是错误的,正确的形式应该是
    百度  
    谷歌
    音乐
    抬头
    低头
因为在生成lm文件的时候会产生很多<s></s>符号导致无法识别
2、编码问题

1) test.lm文件

上传到http://www.speech.cs.cmu.edu/tools/lmtool.html的命令集的txt文件必须为utf-8的形式。且不能有UTF-8文件头
在txt文件保存为UTF-8格式之后,TXT文件会默认为文件加上EF BB BF文件头,导致数据出现问题。如图:
用PocketSphinx做离线命令词识别_第3张图片
正确的形式应该将这部分默认添加的内容删掉,正确的格式如图:
用PocketSphinx做离线命令词识别_第4张图片
(我用的010Editor,随便找个16进制编辑器就可以打开了)

2) test.dic文件
同理,编辑好命令之后,需要用16进制编辑器把UTF-8头信息去掉。
用PocketSphinx做离线命令词识别_第5张图片

最后效果:个人感觉识别率还不错。虽然说达不到99%那么夸张,90%应该还是有的。
用PocketSphinx做离线命令词识别_第6张图片

3、start监听的时间:
在我的三星note2上测试,语音识别start开始,一直不说话,在163秒的时候会出现下面的错误,可能是因为缓存区溢出的原因。我的解决办法是:new 一个新线程来作计时器,在100秒的时候就stop语音识别,再延迟200ms,重新start。

01-13 15:22:01.991: A/libc(31349): /root/workspace/VoiceRecognition/sphinxbase/src/libsphinxbase/feat/feat.c:362: feat_array_alloc: assertion "nfr > 0" failed

01-13 15:22:01.991: A/libc(31349): Fatal signal 6 (SIGABRT) at 0x00007a75 (code=-6), thread 31369 (Thread-925)

由于原博客下载DEMO需要注册之后等待一天才能下载,我把它重新打包上传了,需要的朋友不用再等待一天了。
下载地址:http://download.csdn.net/detail/adzcsx2/9401224

你可能感兴趣的:(android-语音)