2014-10-13 21:56:14 u011747781 阅读数 4243
  • C++语音识别开篇

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

    5922 人正在学习 去看看 杨波

最近做项目,用到离线语音识别,整了好久,查了好多方法,终于完成,网上资料有点乱,而且大部分就是那几个人写的,一群人转!下面我总结一下,也为后来人行个方便。


关于环境配置我就不多说了,我就是按照这个教程一步步来的,绝对是可行的。http://gaebolg.blog.163.com/blog/static/19826906820136232810723/



下面重点讲解一下demo的运行和语音库的配置(注意:上面那个教程的运行demo最后写的一塌糊涂,可以从拷贝声学模型和语音库那里开始看我的!)


首先,demo运行需要以下文件:pocketsphinx/model/en_US lm文件夹( .dic文件, .lm文件),以及hmm文件夹。如果觉得麻烦可以下载我提供的文件。http://download.csdn.net/detail/u011747781/8034061


下面进入重头戏,就是如何设置属于自己的中文语音库:

1、编写自己的命令集:

新建一个txt文件,输入命令,如:


百度
谷歌

点击文件,另存为,注意将编码改为UTF-8格式!(正下方编码选项)保存为txt文件。

2、利用在线工具http://www.speech.cs.cmu.edu/tools/lmtool.html将写好的txt文件生成文件。下载tgz文件即可(里面有所有文件),复制tgz压缩包中的lm文件,因为只有这个有用(如果是英语的话,dic文件可以直接用,就不用我下面介绍的方法生成dic文件了!!)


3、新建一个txt文件。在我给的data文件夹里,有个叫做standard.dic的文件,那个是标准语音库,ctrl+F 查找你需要的发音,复制到你新建的txt文件中。

格式如下:

百度 b ai d u

完事后存为UTF-8格式,改名为 .dic文件。


4、这样属于你的语音库就建好了,只需覆盖我的data文件夹中相应的dic , lm文件 即可!


最后,奉上亲测可用的完整demo  http://download.csdn.net/detail/u011747781/8034195


2012-03-26 11:17:23 huazaihepa 阅读数 301
  • C++语音识别开篇

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

    5922 人正在学习 去看看 杨波

 最近语音识别很火,但是都是用的在线语音识别,研究了一下离线语音识别,小范围内的语音识别率还不错,在此记录一下

首先本文要说的两个前提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%以上,但是输入命令集以外的无法识别。



 

6.附件为工程文件,将data解压,按照3里面写的位置放到sd卡里面即可。以下字典内的词可以识别

 

 

2016-07-06 16:37:35 victor_barnett 阅读数 3500
  • C++语音识别开篇

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

    5922 人正在学习 去看看 杨波

        用了半天时间弄明白了在iOS上如何配置语音识别功能,然后用半天时间写了一个demo,公司坑爹的是不用科大飞讯的语音识别,而使用的是OpenEars,用google查了一下最新的介绍文章是2013年的,OpenEars是一款国外比较主流的语音识别的第三方框架,全是英文文档(吐槽一下,做开发必须要学好英语啊).

1.什么是OpenEars?

        OpenEars是面向iOS平台的一个离线的语音识别和text-to-speech(文字语音转换)开发工具包.OpenEars主要是针对英语,也支持中文的语言包,但是我感觉它的识别性不是太好.最重要的是,这是一款免费的工具包,除了基本的免费功能,它还提供了可以用来扩展基本功能的付费插件.今天主要介绍的是它的免费功能,即简单的语音识别功能.


        当前OpenEars的最新版本为2.5,下载地址为http://www.politepix.com/wp-content/uploads/OpenEarsDistribution.tar.bz2


2.详细配置OpenEars的步骤

(1)点击上方链接下载OpenEars的扩展包,打击打开扩展包,里面有一个Framework的文件夹,将这个文件拖进你的工程文件中.然后检查这个文件的路径(正常情况下Xcode会为你自动添加好文件的路径),点击你的工程文件,然后点击Build Settings,在搜索输入框输入Framework Search Paths,右键点击刚刚添加的Framework文件夹,然后show in finder即可查看文件的路径,核对两个路径是否正确.不正确或者不存在,手动添加即可.见图


核对检查好路径之后,为了添加二进制文件的存储,需要将Build Settings里的Deployment Postprocessing设置为YES.然后添加AudioToolbox库和AVFoundation库到你的项目里边.



(2)在你需要进行语音识别的.m文件下引入头文件,需引入头文件如下:


在你需要进行语音识别的.h文件下引入头文件,需引入头文件如下:


然后跟你需要实现语音识别的文件下引入协议(绿色<>部分为需要引入的协议),例如


并将OEEventsObserver属性添加到您的其他类属性(OEEventsObserver必须您的类的属性,否则它不会工作):



然后在viewDidLoad或者你需要的地方进行初始化观察者并签订协议:



下一步是创建你需要使用到的语音类文件,这决定你将使用什么语言进行识别,在viewDidLoad或者其他地方均可,具体实现如下:


其中的words是你创建的需要识别的单词.

最后在你需要开启语音识别的地方添加如下方法,开启语音识别:



其中你注册的观察者签订的协议方法如下所示



包含中文和英文声学模型的demo地址:Demo地址



2018-03-08 22:26:33 a403238926 阅读数 1875
  • C++语音识别开篇

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

    5922 人正在学习 去看看 杨波

在一些教育 医疗产业中, 很多的词汇都非常专业, 并不是一般的语音识别系统所能提供服务的, 这时就需要我们自己构建一个离线的可以在手机或者平板上运行的语音识别系统, 我选择的是Kaldi, 因为Kaldi的识别能力要比上一代的CMU SPHINX高很多, WER(错误识别率)能做到2%以下, 而且提供基于神经网络系统的模型训练。

要把kaldi做到手机基本的步骤是:

1 把kaldi的所有库编译成移动平台能够使用的架构(armv7 和 arm64)

2  掌握构建语音识别系统的顺序,训练语音模型和语言模型

3  学会使用kaldi的类构建语音识别系统

由于代码仍在改进中,只能提供一些思路,如果希望有进一步的合作可以联系

403238926@qq.com


=================================== update ========================================

由于受到一些大家的邮件, 所以更新一下

代码已经和一家公司合作, 所以不好意思,不能分享了, 但是技术上的讨论还是可以的, 回答几个小问题:

1. 我是编译了两个库 一个kaldi.a 一个 openfst.a 我这里是针对ios 平台的

2. 做的时候注意kaldi的版本 kaldi 5.0 之前应该是不支持c11, 5.0之后支持了 所以编译的时候会有影响

3. 编译的时候,碰到最多的就是linker error,主要是老板的kaldi 支持 libstdc++, 但是新版的xcode不支持了,全面改libc++了, 所以在编译kaldi和openfst的库的时候一定要注意,不然用不了


主要是这几个问题,有其他问题还是可以联系我的邮箱或者在帖子下面留言



2016-12-30 15:09:26 liulanluo 阅读数 872
  • C++语音识别开篇

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

    5922 人正在学习 去看看 杨波

本文仅是自我学习,加强自己记忆。

百度语音是百度提供的语音技术服务,目前基础服务永久免费,包含语音识别、语音合成、语音唤醒三个功能。
以下先介绍语音识别功能。

按照百度语音使用流程指南(如下图),首先要注册百度账号并申请为开发者,然后在应用管理中创建应用,选择要使用的服务,这里可以选择语音识别和语音合成2种。然后下载它的SDK(含有demo——eclipse工程),最后将其libs(so库和.jar文件)集成到自己的应用中,按照开发文档开发。
这里写图片描述

下载的sdk如下图:
这里写图片描述

以下步骤都是以Android Studio的项目工程为例。

1. 将libs和res集成到自己的应用

将libs中文件和res中的文件复制到项目工程对应的文件夹,如下图
这里写图片描述

在build.gradle(Module:app)文件中添加如下代码,这是将jniLibs的路径指向libs文件夹,这样.so库就能导入项目中:

android {
   ……
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    ……
}

2.在AndroidManifest.xml文件中添加appId,权限等信息

appId等在应用管理中添加应用时会生成对应的id,key等。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cykj.baiduyuyintest">

    <!-- 录音 -->
    <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_WIFI_STATE" />
    <!-- 获取用户手机的IMEI,用来唯一的标识用户 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!-- 写入外部存储 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    ……

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
<!-- begin: baidu speech sdk -->
        <!-- 请填写应用实际的APP_ID -->
        <meta-data
            android:name="com.baidu.speech.APP_ID"
            android:value="your appId" />
        <!-- 请填写应用实际的API_KEY -->
        <meta-data
            android:name="com.baidu.speech.API_KEY"
            android:value="your appKey" />
        <!-- 请填写应用实际的SECRET_KEY -->
        <meta-data
            android:name="com.baidu.speech.SECRET_KEY"
            android:value="your secretKey" />

        <service
            android:name="com.baidu.speech.VoiceRecognitionService"
            android:exported="false" />

        <activity
            android:name="com.baidu.voicerecognition.android.ui.BaiduASRDigitalDialog"
            android:configChanges="orientation|keyboardHidden|screenLayout"
            android:exported="false"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Dialog">
            <intent-filter>
                <action android:name="com.baidu.action.RECOGNIZE_SPEECH" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <!-- end : baidu speech sdk -->
    ……
   </application>

</manifest>

3.在Activity中添加代码

package com.cykj.baiduyuyintest;

import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.speech.RecognitionListener;
import android.speech.SpeechRecognizer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.baidu.speech.VoiceRecognitionService;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MainActivity extends AppCompatActivity implements RecognitionListener {


    private static final String TAG = "MainActivity";
    private SpeechRecognizer speechRecognizer;
    private TextView tvResult;
    private TextView tvError;
    private View speechTips;
    private View speechWave;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建识别器
        speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this, new ComponentName(this, VoiceRecognitionService.class));
        //注册识别监听
        speechRecognizer.setRecognitionListener(this);

        //语音识别说话时显示的录音界面(麦克风)
        speechTips = View.inflate(this, R.layout.bd_asr_popup_speech, null);
        speechWave = speechTips.findViewById(R.id.wave);
        speechTips.setVisibility(View.GONE);
        addContentView(speechTips, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        //点击按钮开始说话进行语音识别
        Button bt = (Button) findViewById(R.id.bt);
        bt.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN://按下时开始识别
                        speechTips.setVisibility(View.VISIBLE);
                        speechRecognizer.cancel();
                        tvError.setText("");
                        tvResult.setText("");
                        startASR();
                        break;
                    case MotionEvent.ACTION_UP://抬起时停止识别
                        speechRecognizer.stopListening();
                        speechTips.setVisibility(View.GONE);
                        break;
                }
                return false;
            }
        });

        //显示识别结果
        tvResult = (TextView) findViewById(R.id.tv_result);
        //显示错误内容
        tvError = (TextView) findViewById(R.id.tv_error);

        //进入语音唤醒
        findViewById(R.id.bt_wp).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, WakeUpActivity.class));
            }
        });

    }

    /**
     * 开始识别
     */
    void startASR() {
        Intent intent = new Intent();
        //绑定识别参数
        bindParams(intent);
        speechRecognizer.startListening(intent);
    }

    /**
     * 设置识别参数
     *
     * @param intent
     */
    private void bindParams(Intent intent) {
        intent.putExtra("sample", 16000);// 离线仅支持16000采样率
        intent.putExtra("language", "cmn-Hans-CN"); // 离线仅支持中文普通话
//        intent.putExtra("prop", 10060); //垂直领域(按照文档意思应该是如果垂直领域是音乐,如果是类似发音优先识别和音乐相关的词语),2.1版本后离线功能请使用grammar参数
        //识别中的提示音,比如识别成功,识别错误等
        intent.putExtra("sound_start", R.raw.bdspeech_recognition_start);//
        intent.putExtra("sound_end", R.raw.bdspeech_speech_end);
        intent.putExtra("sound_success", R.raw.bdspeech_recognition_success);
        intent.putExtra("sound_error", R.raw.bdspeech_recognition_error);
        intent.putExtra("sound_cancel", R.raw.bdspeech_recognition_cancel);

//        intent.putExtra("vad", "input"); //语音活动检测
//        intent.putExtra("nlu", "enable"); //是否启用语义解析
        //音频源,可以识别此pcm文件中的语音内容
//        intent.putExtra("infile", Environment.getExternalStorageDirectory()+"/outfile1.pcm");
        //保存识别过程产生的录音文件
        intent.putExtra("outfile", Environment.getExternalStorageDirectory() + "/outfile.pcm");


        /**根据开发文档,这个垂类设置应该是2.1版本之前的用法,2.1版本以后都用grammar代替了。
         int prop = 10060;
         // value替换为资源文件实际路径
         intent.putExtra("asr-base-file-path", Environment.getExternalStorageDirectory()+"/s_1");

         if (prop == 10060) {
         // 地图类附加资源,value替换为资源文件实际路径
         intent.putExtra("lm-res-file-path", Environment.getExternalStorageDirectory() + "/s_2_Navi");
         } else if (prop == 20000) {
         // 语音输入附加资源,value替换为资源文件实际路径
         intent.putExtra("lm-res-file-path", Environment.getExternalStorageDirectory() + "/s_2_InputMethod");
         }*/

        // value替换为license文件实际路径,仅在使用临时license文件时需要进行设置,如果在[应用管理]中开通了离线授权,不需要设置该参数
        //具体参考http://yuyin.baidu.com/docs/asr/171中离线授权一节
//        intent.putExtra("license-file-path", Environment.getExternalStorageDirectory() + File.separator + "temp_license_2016-12-27.txt");
        //设置离线识别grammar文件,此文件来自于自定义语义设置 http://yuyin.baidu.com/asr
        intent.putExtra("grammar", "assets:///baidu_speech_grammar.bsg");
        //设置slot-data参数,可以替代grammar文件中初始词条内容,比如自定义语义设置中"name"词条内容是"name = 张三, 李四, 王五",添加slot-data后将变为"王云"、"流利"
        JSONObject slotData = new JSONObject();
        JSONArray name = new JSONArray().put("王云").put("流利");
        JSONArray app = new JSONArray().put("百度糯米").put("360卫士");
        try {
            slotData.put("name", name);
            slotData.put("appname", app);
        } catch (JSONException e) {

        }
        intent.putExtra("slot-data", slotData.toString());
        Log.d(TAG, "---" + intent.getExtras().toString());
    }


    @Override
    public void onReadyForSpeech(Bundle params) {
        // 准备就绪
        Log.v(TAG, "onReadyForSpeech--" + params);
    }


    @Override
    public void onBeginningOfSpeech() {
        // 开始说话处理
        Log.v(TAG, "onBeginningOfSpeech--");
    }


    @Override
    public void onRmsChanged(float rmsdB) {
        //音量变化处理
        final int VTAG = 0xFF00AA01;
        Integer rawHeight = (Integer) speechWave.getTag(VTAG);
        if (rawHeight == null) {
            rawHeight = speechWave.getLayoutParams().height;
            speechWave.setTag(VTAG, rawHeight);
        }

        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) speechWave.getLayoutParams();
        params.height = (int) (rawHeight * rmsdB * 0.01);
        params.height = Math.max(params.height, speechWave.getMeasuredWidth());
        speechWave.setLayoutParams(params);
    }

    @Override
    public void onBufferReceived(byte[] buffer) {
        // 录音数据传出处理
        Log.v(TAG, "onBufferReceived--");
    }

    @Override
    public void onEndOfSpeech() {
        //说话结束处理
        Log.v(TAG, "onEndOfSpeech--");
    }

    @Override
    public void onError(int error) {
        //出错
        Log.e(TAG, "onError--" + error);
        StringBuilder sb = new StringBuilder();

        switch (error) {
            case SpeechRecognizer.ERROR_AUDIO:
                sb.append("音频错误");
                break;
            case SpeechRecognizer.ERROR_CLIENT:
                sb.append("其他客户端错误");
                break;
            case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
                sb.append("权限不足");
                break;
            case SpeechRecognizer.ERROR_NETWORK:
                sb.append("网络连接错误");
                break;
            case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
                sb.append("网络连接超时");
                break;
            case SpeechRecognizer.ERROR_NO_MATCH:
                sb.append("没有匹配的识别结果");
                break;
            case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
                sb.append("引擎忙");
                break;
            case SpeechRecognizer.ERROR_SERVER:
                sb.append("服务器端错误");
                break;
            case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
                sb.append("超时");
                break;
        }

        tvError.setText(sb);

    }

    @Override
    public void onResults(Bundle results) {
        //最终结果
        Log.v(TAG, "onResults--" + results);
        tvResult.setText("");
        ArrayList<String> resultsRecognition = results.getStringArrayList("results_recognition");
        for (String s : resultsRecognition) {
            tvResult.append(s + " ");
        }
    }

    @Override
    public void onPartialResults(Bundle partialResults) {
        // 临时结果处理
        Log.v(TAG, "onPartialResults--");
    }

    @Override
    public void onEvent(int eventType, Bundle params) {
        // 处理事件回调
        Log.e(TAG, "onEvent--" + eventType + "--" + params);
    }
}

识别返回结果:

onResults--Bundle[{results_recognition=[开始], error=0, origin_result={"content":{"item":["开始"]},"result":{"sn":"d42c1a78-0f44-40e9-8ea6-80e640110a6f","idx":-11,"res_type":3,"err_no":0,"corpus_no":6369803402677818267}}}]

参考的资料:百度开发文档地址grammar文件生成地址源代码下载

语音识别

阅读数 1537

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