2016-10-07 21:18:45 sac761 阅读数 21568
  • Python全栈视频教程

    Python全栈视频培训教程,帮助开发者从零到一入门python:1.深入理解python语法机制与底层原理,2.深入实战python各种案例 , 3.语音识别,图形界面,多线程爬虫,语音合成,游戏控制等等精彩案例。

    213933 人正在学习 去看看 尹成

本项目做出的产品是一个Windows下的增强现实系统,系统很庞大,产品功能已经基本完善,考虑到给用户带来更好的体验,故综合评估后采用讯飞语音识别方案进行嫁接。

项目介绍:

1)打开系统时启动语音识别,检测到用户说出关键词(如:上一步,下一步,结束等)时,系统自动进行相应的操作;

2)不需要按任何按键进行连续的语音识别控制,延迟为2秒左右;

3)可以识别词语,句子,中文,英文数字字母通吃,不限语速。并且语句结束判断机制很智能;

3)离线!离线!现在做一个基于windows的离线的语音识别系统在网络上还真没谁,讯飞自己也还没有推出这款SDK,我是在讯飞的离线命令词识别SDK开发包上开发出的介于两者之间功能的系统。

为什么用讯飞:

之前使用过语音识别开发版,用驻极体采集声音,通过串口传输信号来进行识别,只能讲开发版只适合用来做个课程设计啥的玩玩,做产品还是太LOW,识别率地下并且识别范围窄,貌似只能识别数字字母;之后调查过汉语语音识别库如Sphinx,Julius,百度语音等。去网上问,很多人推荐这些方案的,我没试过,不过一个SDK也只有自己正真开发过才知道好不好用强不强大,说的再牛逼也是在别人手上玩的转,到你这就不一定了。我用讯飞就是看上它的鲁棒,免费,毕竟是久经考验的平台,讯飞有一个开发者论坛,开发别人的SDK有个社区很重要,不然有问题没地方问。


项目开发经验与源码如下:

一、跑通讯飞离线命令词识别SDK

首先去讯飞官网下载相应SDK,要注册登录,绑定产品才能下载,下载后跑一跑给的demo,跑不通的话去讯飞的论坛找答案。

我用的demo是asr_record_demo,这个demo可以实现的功能是按下R键从mic中录制缓冲音频并按下S键后进行识别。

稍微看一看这个demo中的东西吧,把该删的东西删了,该修整的修整,玩转了demo才能进一步做移植。

二、文件分析与移植

把SDK包中的需要的.lib  .h  .c和所需要的其余文件拷贝到项目相应的文件夹去,最好是分个类,看起来比较清楚。它比较重要的几个文件有以下几个:

msc.lib   讯飞语音离线命令词识别所依赖的库(X64版本为msc_x64.lib)才15KB就能有如此强大的功能。

call.bnf    采用巴科斯范式语法规则的自定义语法库(call是根据自己需要命名的),用来编写语音识别过程中的语法规则,这个语法写的好语音识别更智能。

speech_recognizer.c  基于录音接口和MSC接口封装一个MIC录音识别的模块,SDK的主要文件

winrec.c  封装windows录音,Windows平台下SDK的主要文件


好了,既然demo已经知道怎么用了,把demo所依赖的所有文件和库照搬进自己的项目去,就可以在自己的项目中调用讯飞的函数了(注意头文件和库文件的路径问题)。

三、使用讲解

先看看我的语法文件

call.bnf:


巴科斯范式语法语法文件怎么写在讯飞的论坛里有很多资源自己去看吧,我写的比较简单,写得好的语法可以更加智能。


大致讲讲源码:

为了看起来简洁,我在speech_recognizer.h中做了一个类SR,把主文件中的一些函数定义和一些宏搬进去。

speech_recognizer.h:

class SR {
public:

	const char * ASR_RES_PATH = "fo|res/asr/common.jet";  //离线语法识别资源路径
#ifdef _WIN64
	const char * GRM_BUILD_PATH = "res/asr/GrmBuilld_x64";  //构建离线语法识别网络生成数据保存路径
#else
	const char * GRM_BUILD_PATH = "res/asr/GrmBuilld";  //构建离线语法识别网络生成数据保存路径
#endif
	const char * GRM_FILE = "call.bnf"; //构建离线识别语法网络所用的语法文件

	int build_grammar(UserData *udata);//构建语法
	int run_asr(UserData *udata);//启动引擎

};
speech_recognizer.c:

#pragma comment(lib,"../../lib/msc_x64.lib") //x64
#else
#pragma comment(lib,"XXXXXX/lib/msc.lib") //x86
#endif
这里的库目录要注意,用相对路径可能找不到文件,可以使用绝对路径

#ifdef _WIN64
<pre name="code" class="cpp">static int update_format_from_sessionparam(const char * session_para, WAVEFORMATEX *wavefmt)
{
	char *s;
	/*if ((s = strstr(session_para, "sample_rate"))) {
		if (s = strstr(s, "=")) {
			s = skip_space(s);
			if (s && *s) {
				wavefmt->nSamplesPerSec = atoi(s);
				wavefmt->nAvgBytesPerSec = wavefmt->nBlockAlign * wavefmt->nSamplesPerSec;
			}
		}
		else
			return -1;
	}
	else {
		return -1;
	}*/

	return 0;
}


如果加到讯飞提供的demo使用的是VS2010如果放到VS2015中就会出一些语法上的错,自己看着改一改,比如上面这个函数,是更新用户词典用的,我不需要但是又存在语法错误,就把它的内容直接注释掉得了。

我的项目的主文件中:

首先定义几个宏:

UserData asr_data;//语音识别用户配置
speech_rec asr;//麦克风输入存储结构体
SR sr;//语音识别实体
string SPEAKER="";//用于缓存语音识别内容
在程序初始化处配置如下:

openVoiceRecognizer = true;//语音识别开关
	if (openVoiceRecognizer)
	{
		const char *login_config = "appid = XXXXX"; //登录参数
		int ret = 0;


		ret = MSPLogin(NULL, NULL, login_config); //第一个参数为用户名,第二个参数为密码,传NULL即可,第三个参数是登录参数
		if (MSP_SUCCESS != ret) {
			printf("登录失败:%d\n", ret);
			openVoiceRecognizer = false;
		}


		memset(&asr_data, 0, sizeof(UserData));
		printf("构建离线识别语法网络...\n");
		ret = sr.build_grammar(&asr_data);  //第一次使用某语法进行识别,需要先构建语法网络,获取语法ID,之后使用此语法进行识别,无需再次构建
		if (MSP_SUCCESS != ret) {
			printf("构建语法调用失败!\n");
			openVoiceRecognizer = false;
		}


		while (1 != asr_data.build_fini)
			_sleep(300);
		if (MSP_SUCCESS != asr_data.errcode)
			_sleep(300);
		printf("离线识别语法网络构建完成,开始识别...\n");
		ret = sr.run_asr(&asr_data);//预启动语音识别引擎
	}
在初始化这里我修改了 sr.run_asr(&asr_data);这个函数,我把它调用的sr_start_listening(&asr);函数抽离出来,不让它启动识别引擎而只让它预启动,把所有结构体,变量先初始化待命。

void recognize_mic(const char* session_begin_params)  //根据自己项目需要写的语音识别预热函数
{
	int errcode;
	HANDLE helper_thread = NULL;

	struct speech_rec_notifier recnotifier = {
		on_result,
		on_speech_begin,
		on_speech_end
	};
	errcode = sr_init(&asr, session_begin_params, SR_MIC, DEFAULT_INPUT_DEVID, &recnotifier);
	if (errcode) {
		printf("speech recognizer init failed\n");
		return;
	}

	/*	while (1) {
			errcode = sr_start_listening(&asr);//我把它调用的sr_start_listening(&asr);函数抽离出来,不让它启动识别引擎而只让它预启动,把所有结构体,变量先初始化待命。
		}

	exit:
		sr_uninit(&asr);*/
}

int SR::run_asr(UserData *udata)
{
	char asr_params[MAX_PARAMS_LEN] = { NULL };
	const char *rec_rslt = NULL;
	const char *session_id = NULL;
	const char *asr_audiof = NULL;
	FILE *f_pcm = NULL;
	char *pcm_data = NULL;
	long pcm_count = 0;
	long pcm_size = 0;
	int last_audio = 0;
	int aud_stat = MSP_AUDIO_SAMPLE_CONTINUE;
	int ep_status = MSP_EP_LOOKING_FOR_SPEECH;
	int rec_status = MSP_REC_STATUS_INCOMPLETE;
	int rss_status = MSP_REC_STATUS_INCOMPLETE;
	int errcode = -1;
	int aud_src = 0;

	//离线语法识别参数设置
	_snprintf(asr_params, MAX_PARAMS_LEN - 1,         //<span style="font-family: Arial, Helvetica, sans-serif;">离线语法识别参数根据自己的需要进行更改</span>

		"engine_type = local, \
		asr_res_path = %s, sample_rate = %d, \
		grm_build_path = %s, local_grammar = %s, ",
		sr.ASR_RES_PATH,
		SAMPLE_RATE_16K,
		sr.GRM_BUILD_PATH,
		udata->grammar_id
		);

	recognize_mic(asr_params);
	return 0;
}
而后是三个语音识别的中间过程和结果处理的函数:

void on_result(const char *result, char is_last)   //根据自己的需要写结果处理
{
	char *p = "上一步";
	char *pq = "下一步";
	char *q = "扫频仪操作演示";
	char *end1 = "结束";
	char *end2 = "退出";
	if (strstr(result, p)) {
		SPEAKER = "上一步";	
	}
	else if (strstr(result, pq)) {
		SPEAKER = "下一步";
	}
	else if (strstr(result, q)) {
		SPEAKER = "扫频仪操作演示";
	}
	else if (strstr(result,end1)|| strstr(result, end2)) {
		SPEAKER = "退出";
	}
	cout << SPEAKER << endl;
}
void on_speech_begin()
{
	if (g_result)
	{
		free(g_result);
	}
	g_result = (char*)malloc(BUFFER_SIZE);
	g_buffersize = BUFFER_SIZE;
	memset(g_result, 0, g_buffersize);

	printf("Start Listening...\n");
}
void on_speech_end(int reason)
{
	if (reason == END_REASON_VAD_DETECT)
		printf("\nSpeaking done \n");
	else
		printf("\nRecognizer error %d\n", reason);
}
最后就是在自己项目哪里需要语音识别就在哪里抛出缓冲线程启动识别引擎:

if (openVoiceRecognizer) {
		
		sr_start_listening(&asr);//抛出缓冲线程进行语音识别

		if (SPEAKER=="下一步") {
			keyPressed(' ');
		}
		else if (SPEAKER == "上一步") {
			keyPressed('b');
		}
		else if (SPEAKER == "扫频仪操作演示") {
			keyPressed('1');
		}
		else if (SPEAKER=="退出") {
			std::exit(0);
		}
		SPEAKER = "";
	}

上面代码中的关键就是sr_start_listening(&asr);这个函数,前面也说了这是从run_asr()调用的方法中抽离出来的,抽离出来后run_asr()就变成了预热函数,只需在程序初始化的时候调用它后面的语音识别就不要重复调用了,节省资源。

必须要说说这个关键函数sr_start_listening(&asr);

这是讯飞这款SDK中不需要动的最后一个封装好的函数,里面的东西不要动,前面的东西配置好一调用它就可以进行语音识别了,这个函数中的东西是这款SDK的精华,实现过程很复杂不需要管,但是要记住它的几个特性:

1)一调用它就相当于抛出了一个带缓冲的新线程,这个线程独立进行语音的识别可以不干扰项目的主循环的进行。

2)这个线程寿命是自动的,程序一开始启动到这里调用这个函数后启动线程,当程序的主循环又回来这里不会重复启动这个线程,而是该线程识别完用户的语音判断语句结束机制触发后才待命,等待下一次循环的启动。这句话有些费解,用我的项目解释下:我的项目在update()函数中调用sr_start_listening(&asr); 我的update()函数每100毫秒循环一次,第一次循环启动这个函数,抛出线程进行语音识别,语音识别用了10秒结束,在这10秒过程中update()循环了100次,但是只启动该函数一次,第101次循环的时候就可以第二次启动该函数了,同时在上面代码片中我用SPEAKER转存的字符串的判断条件已经成立,就可以进行相应的操作了,在这里我触发了不同的按键来代替各种操作。

3)举个栗子,我在update()中可以在每一次循环时画一帧图片的方式实现一个视频的播放,而在这里面调用语音引擎sr_start_listening(&asr);,在引擎识别的过程中会不会中断视频的播放或者视频出现卡帧或迟滞呢?答案是不会,上面也解释了,这个函数抛出一个独立的线程,不影响主函数的循环。所以可以用这种方法实现用语音控制视频的播放:快进、后退、暂停、截屏、全屏、音量加大、切换到高清......是不是很酷!

上面的几个源码文件我打了个包,下载看可能更清楚:

http://download.csdn.net/detail/sac761/9647029

四、总结

我用这个方案实现了离线的语音控制系统,语音识别率达到百分之九十以上,而且词语句子中英文通吃,实时性强,系统鲁棒。

畅想一下用这个方法加方案开发这几个产品:

语音控制的媒体播放器,功能在上面也讲了,很酷的!

语音控制的PPT遥控器

语音控制的AR/VR系统

语音交互智能眼镜

.............





2019-04-23 21:09:37 qq_37082966 阅读数 778
  • Python全栈视频教程

    Python全栈视频培训教程,帮助开发者从零到一入门python:1.深入理解python语法机制与底层原理,2.深入实战python各种案例 , 3.语音识别,图形界面,多线程爬虫,语音合成,游戏控制等等精彩案例。

    213933 人正在学习 去看看 尹成

科大讯飞语音识别控制实际机器人运动。

本文将ros与语音识别想结合进行开发。进行以下步骤,
1、创作ros工作空间
2、安装mpalyer播放器

sudo apt-get install mplayer

3、将讯非的语音库动态文件.so文件放到/usr/lib/下
4、ros工程目录src下新建文件xf_asr.cpp 并将以下内容复制进去,appid改成你自己的(官网申请)。

/*
* 语音听写(iFly Auto Transform)技术能够实时地将语音转换成对应的文字。
*/
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "qisr.h"
#include "msp_cmn.h"
#include "msp_errors.h"
#include "speech_recognizer.h"
#include <iconv.h>
 
#include "ros/ros.h"
#include "std_msgs/String.h"
 
#define FRAME_LEN   640 
#define BUFFER_SIZE 4096
 
int wakeupFlag   = 0 ;
int resultFlag   = 0 ;
 
static void show_result(char *string, char is_over)
{
    resultFlag=1;   
    printf("\rResult: [ %s ]", string);
    if(is_over)
        putchar('\n');
}
 
static char *g_result = NULL;

static unsigned int g_buffersize = BUFFER_SIZE;
 
void on_result(const char *result, char is_last)
{
    if (result) {
        size_t left = g_buffersize - 1 - strlen(g_result);
        size_t size = strlen(result);
        if (left < size) {
            g_result = (char*)realloc(g_result, g_buffersize + BUFFER_SIZE);
            if (g_result)
                g_buffersize += BUFFER_SIZE;
            else {
                printf("mem alloc failed\n");
                return;
            }
        }
        strncat(g_result, result, size);
        show_result(g_result, is_last);
    }
}
 

void on_speech_begin()
{
    if (g_result)
    {
        free(g_result);
    }
    g_result = (char*)malloc(BUFFER_SIZE);
    g_buffersize = BUFFER_SIZE;
    memset(g_result, 0, g_buffersize);
 
    printf("Start Listening...\n");
}
void on_speech_end(int reason)
{
    if (reason == END_REASON_VAD_DETECT)
        printf("\nSpeaking done \n");
    else
        printf("\nRecognizer error %d\n", reason);
}
 


/* demo recognize the audio from microphone */
static void demo_mic(const char* session_begin_params)
{
    int errcode;
    int i = 0;
 
    struct speech_rec iat;
 
    struct speech_rec_notifier recnotifier = {
        on_result,
        on_speech_begin,
        on_speech_end
    };
 
    errcode = sr_init(&iat, session_begin_params, SR_MIC, &recnotifier);
    if (errcode) {
        printf("speech recognizer init failed\n");
        return;
    }
    errcode = sr_start_listening(&iat);
    if (errcode) {
        printf("start listen failed %d\n", errcode);
    }
    /* demo 10 seconds recording */
    while(i++ < 2)
        sleep(1);
    errcode = sr_stop_listening(&iat);
    if (errcode) {
        printf("stop listening failed %d\n", errcode);
    }
 
    sr_uninit(&iat);
}
 
 
/* main thread: start/stop record ; query the result of recgonization.
 * record thread: record callback(data write)
 * helper thread: ui(keystroke detection)
 */
 

void WakeUp(const std_msgs::String::ConstPtr& msg)
{
    printf("waking up\r\n");
    usleep(700*1000);
    wakeupFlag=1;
}


int main(int argc, char* argv[])
{
    // 初始化ROS
    ros::init(argc, argv, "voiceRecognition");
    ros::NodeHandle n;
    ros::Rate loop_rate(10);
 
    // 声明Publisher和Subscriber
    // 订阅唤醒语音识别的信号
    ros::Subscriber wakeUpSub = n.subscribe("voiceWakeup", 1000, WakeUp);   
    // 订阅唤醒语音识别的信号    
    ros::Publisher voiceWordsPub = n.advertise<std_msgs::String>("voiceWords", 1000);  
 
    ROS_INFO("Sleeping...");
    int count=0;
    while(ros::ok())
    {
        // 语音识别唤醒
        if (wakeupFlag){
            ROS_INFO("Wakeup...");
            int ret = MSP_SUCCESS;
            const char* login_params = "appid = , work_dir = .";
 
            const char* session_begin_params =
                "sub = iat, domain = iat, language = zh_cn, "
                "accent = mandarin, sample_rate = 16000, "
                "result_type = plain, result_encoding = utf8";
 
            ret = MSPLogin(NULL, NULL, login_params);
            if(MSP_SUCCESS != ret){
                MSPLogout();
                printf("MSPLogin failed , Error code %d.\n",ret);
            }
 
            printf("Demo recognizing the speech from microphone\n");
	
	    printf("Speak in 3 seconds\n");
 	
            demo_mic(session_begin_params);
 
            printf("3 sec passed\n");
        
            wakeupFlag=1;
            MSPLogout();
        }
 
        // 语音识别完成
        if(resultFlag)
	{
            resultFlag=0;
            std_msgs::String msg;
            msg.data = g_result;
            voiceWordsPub.publish(msg);
        }
 
        ros::spinOnce();
        loop_rate.sleep();
        count++;
    }
 
exit:
    MSPLogout(); // Logout...
 
    return 0;
}

5、CMakeLists.txt增加以下代码

add_executable(xf_asr src/xf_asr.cpp)
target_link_libraries(xf_asr ${catkin_LIBRARIES} -lmsc  -ldl -lpthread -lm -lrt)
add_dependencies(xf_asr xf_voice_generate_messages_cpp)(这句要不要都可以)

6、回到工作空间编译,编译后source一下。此时语音识别已经可以运行,打开新的终端运行roscore。在另一个终端运行asr。
7、添加语音控制的package,新创建一个新的package,在新的src里面创建voice_cmd.cpp。复制一下代码、

#include<ros/ros.h>
#include<geometry_msgs/Twist.h>
#include<std_msgs/String.h>
#include<pthread.h>
#include<iostream>
#include<stdio.h>
//#include<string.h>
using namespace std;
ros::Publisher pub;
geometry_msgs::Twist vel_cmd;
pthread_t pth_[5];


void* vel_ctr(void* arg)
{
    while(true)
    {

        pub.publish(vel_cmd);
        ros::spinOnce();
        sleep(1);
    }
    return 0;
}
//void callback(const package_name::type_name & msg)
void callback(const std_msgs::String::ConstPtr& msg)
{
    cout<<"收到:"<<msg->data.c_str()<<endl;
    string str1 = msg->data.c_str();
    string str2 = "11";
    string str3 = "22";
    string str4 = "33";
    string str5 = "44";
    string str6 = "55";
    //if(str1 == str2)
    if(str1.find("前进"))
//    if(strstr(&str1, &str2))
    {
      //  cout<<"11111"<<endl;
        vel_cmd.linear.x = 0.2;
        vel_cmd.angular.z = 0;
        pthread_create(&pth_[0],NULL,vel_ctr,NULL);
    }
    //if(str1 == str3)
    if(str1.find("后退“))
    //if(strstr(&str1 , &str3))
    {
        vel_cmd.linear.x = -0.2;
        vel_cmd.angular.z = 0;
        pthread_create(&pth_[1],NULL,vel_ctr,NULL);
    }
    if(str1.find("左转"))
    //if(strstr(&str1 , &str4))
    {
        vel_cmd.linear.x = 0;
        vel_cmd.angular.z = 0.05;
        pthread_create(&pth_[2],NULL,vel_ctr,NULL);
    }
    if(str1.find("右转"))
    //if(strstr(&str1 ,&str5))
    {
        vel_cmd.linear.x = 0;
        vel_cmd.angular.z = -0.05;
        pthread_create(&pth_[3],NULL,vel_ctr,NULL);
    }
    if(str1.find("停止"))
    //if(strstr(&str1 ,&str6))
    {
        vel_cmd.linear.x = 0;
        vel_cmd.angular.z = 0;
        pthread_create(&pth_[4],NULL,vel_ctr,NULL);
    }    
}

int main(int argc, char** argv)
{

    ros::init(argc, argv, "sub_word");
    ros::NodeHandle n;
    //pub = n.advertise<geometry_msgs::Twist>("/cmd_vel_mux/input/teleop",10);
    pub = n.advertise<geometry_msgs::Twist>("/mobile_base/mobile_base_controller/cmd_vel",1000);
    
    ros::Subscriber sub = n.subscribe("/voiceWords",10,callback);
//    ros::Subscriber sub = n.subscribe("read",10,callback);
    //ros::Publisher pub = n.advertise<geometry_msgs::Twist>("/cmd_vel_mux/input/teleop", 10);
    
cout<<"您好!你可以语音控制啦!"<<endl;
cout<<"向前行———————————>前进"<<endl;
cout<<"向后退———————————>后退"<<endl;
cout<<"向左转———————————>左转"<<endl;
cout<<"向右转———————————>右转"<<endl;
cout<<"使停止———————————>停止"<<endl;
    ros::spin();
}

8、同理在Cmakelist加上以下:

add_executable(voice_cmd src/voice_cmd.cpp)
target_link_libraries(voice_cmd ${catkin_LIBRARIES} )
add_dependencies(voice_cmd voice_cmd_generate_messages_cpp)

9、回到工作空间编译,运行。
10、运行上面两个模块后再打开一个终端运行rqt_graph查看节点图是否联通。(完)

或者用python去控制机器人运动,订阅asr的内容,
以下是python代码:

#!/usr/bin/env python
# This Python file uses the following encoding: utf-8
import os, sys

import roslib; roslib.load_manifest('pocketsphinx')
import rospy
import math


from geometry_msgs.msg import Twist
from std_msgs.msg import String

class voice_cmd_vel:

    def __init__(self):
        rospy.on_shutdown(self.cleanup)
        self.speed = 0.2
        self.msg = Twist()
	
	

        # publish to cmd_vel, subscribe to speech output
        #self.pub_ = rospy.Publisher('/mobile_base/commands/velocity', Twist)
	self.pub_ = rospy.Publisher('/mobile_base/mobile_base_controller/cmd_vel', Twist)
        rospy.Subscriber('/voiceWords', String, self.speechCb)

	r = rospy.Rate(10.0)
	while not rospy.is_shutdown():
            self.pub_.publish(self.msg)
            r.sleep()
        
    def speechCb(self, msg):
        rospy.loginfo(msg.data)
	
        #if msg.data.find("full speed") > -1:
	if msg.data.find("加速") > -1:
            if self.speed == 0.2:
                self.msg.linear.x = self.msg.linear.x*2
                self.msg.angular.z = self.msg.angular.z*2
                self.speed = 0.4
        if msg.data.find("减速") > -1:
            if self.speed == 0.4:
                self.msg.linear.x = self.msg.linear.x/2
                self.msg.angular.z = self.msg.angular.z/2
                self.speed = 0.2
	if msg.data.find("前进") > -1:
        #if msg.data.find("forward") > -1:    
            self.msg.linear.x = self.speed
            self.msg.angular.z = 0
        elif msg.data.find("左转") > -1:
            if self.msg.linear.x != 0:
                if self.msg.angular.z < self.speed:
                    self.msg.angular.z += 0.05
            else:        
                self.msg.angular.z = self.speed*2
        elif msg.data.find("右转") > -1:    
            if self.msg.linear.x != 0:
                if self.msg.angular.z > -self.speed:
                    self.msg.angular.z -= 0.05
            else:        
                self.msg.angular.z = -self.speed*2
        elif msg.data.find("后退") > -1:
            self.msg.linear.x = -self.speed
            self.msg.angular.z = 0
        elif msg.data.find("停止") > -1 or msg.data.find("立定") > -1:          
            self.msg = Twist()
        
        self.pub_.publish(self.msg)
	
	

    def cleanup(self):
        # stop the robot!
        twist = Twist()
        self.pub_.publish(twist)

if __name__=="__main__":
    rospy.init_node('voice_cmd_vel')
    try:
        voice_cmd_vel()
    except:
        pass

2019-11-11 21:02:02 weixin_42466538 阅读数 28
  • Python全栈视频教程

    Python全栈视频培训教程,帮助开发者从零到一入门python:1.深入理解python语法机制与底层原理,2.深入实战python各种案例 , 3.语音识别,图形界面,多线程爬虫,语音合成,游戏控制等等精彩案例。

    213933 人正在学习 去看看 尹成
基于文本情感分类的语音识别控制系统
技术领域
本发明涉及语音识别技术领域,更为具体地,涉及一种基于文本情感分类的语音识别控制系统。
背景技术
传统的语音识别技术,主要采用模板匹配的方法,在孤立词汇的识别上取得了较好的效果。但是,对于大量的连续语音而言,模板匹配方法遇到了困难,由于语音识别的准确率依赖于匹配的准确率,因此需要大量的语音匹配模板,造成匹配系统设计复杂,匹配效率低,消耗资源要求也高。
近年来,提出了一些基于文本情感分类和深度学习的语音识别方法,由于基于情感词典的文本情感分类对人的记忆和判断思维的最简单的模拟,存在识别准确率较低的问题,进一步利用深度学习算法可以提高准确度,但是实现成本较高,系统设计很复杂等。
发明内容
本发明的目的在于克服现有技术的不足,提供一种基于文本情感分类的语音识别控制系统,提高了语音识别的准确率,降低了语音识别系统的复杂性,保障识别准确度的同时降低了实现成本。
本发明的目的是通过以下技术方案来实现的:
一种基于文本情感分类的语音识别控制系统,包括文本预处理模块,用于剔除html标签,并进行数据清洗识别出情感词汇,将识别出的感词汇分类导入文本情感模板;文件上传模块,用于将文本情感模板和语音文件上传到服务器;语音识别服务器,在所述语音识别服务器中设置有语音识别程序模块,所述语音识别程序模块包括文件查询接口模块、特征提取模块和解码器模块;所述文件查询接口模块,用于检索查询是否上传有新的语音文件;所述特征提取模块用于将上传的语音文件的所有特征向量按时间顺序排列,将排列好的特征向量分成多等份,对每一等份进行池化,然后将所有向量拼起来再次池化处理,从而得到全局特征并形成语音记录文件;所述解码器模块,用于将语音记录文件解码成文本信息,并与文本情感模板进行匹配;文件下载模块,用于将语音记录文件传输到手机端和计算机端;在计算机端通过计算机现实模块输出语音识别结果;在手机端,通过手机显示模块输出语音识别结果。
进一步的,包括数据爬取模块,用于爬取网页数据。
进一步的,所述文本情感模板包括积极词汇情感模板、消极词汇情感模板。
进一步的,包括终端测深度学习模块,所述终端测深度学习模块用于训练识别录入语音。
进一步的,所述终端测深度学习模块包括计算机端深度学习模块,所述终端测深度学习模块用于训练识别录入语音。
进一步的,所述终端测深度学习模块包括手机端深度学习模块,所述终端测深度学习模块用于训练识别录入语音。
本发明的有益效果是:
(1)本发明提高了语音识别的准确率,降低了语音识别系统的复杂性,保障识别准确度的同时降低了实现成本。具体的,形成语音记录文件,提高了特征提取效率,通过将语音记录文件解码成文本信息并与文本情感模板进行匹配,与语音匹配相比,降低了匹配难度,提高了匹配准确性,实现了快速匹配正确的语音记录文件,不仅提高了匹配效率,而且使得系统设计更加简单,降低了实现成本。
附图说明
为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这些附图获得其他的附图。
图1为本发明的结构框图。
具体实施方式
下面结合附图进一步详细描述本发明的技术方案,但本发明的保护范围不局限于以下所述。本说明书中公开的所有特征,或隐含公开的所有方法或过程中的步骤,除了互相排斥的特征和/或步骤以外,均可以以任何方式组合。
本说明书(包括任何附加权利要求、摘要和附图)中公开的任一特征,除非特别叙述,均可被其他等效或具有类似目的的替代特征加以替换。即,除非特别叙述,每个特征只是一系列等效或类似特征中的一个例子而已。
下面将详细描述本发明的具体实施例,应当注意,这里描述的实施例只用于举例说明,并不用于限制本发明。在以下描述中,为了提供对本发明的透彻理解,阐述了大量特定细节。然而,对于本领域普通技术人员显而易见的是:不必采用这些特定细节来实行本发明。在其他实例中,为了避免混淆本发明,未具体描述公知的电路,软件或方法。
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
在对实施例进行描述之前,需要对一些必要的术语进行解释。例如:
若本申请中出现使用“第一”、“第二”等术语来描述各种元件,但是这些元件不应当由这些术语所限制。这些术语仅用来区分一个元件和另一个元件。因此,下文所讨论的“第一”元件也可以被称为“第二”元件而不偏离本发明的教导。应当理解的是,若提及一元件“连接”或者“联接”到另一元件时,其可以直接地连接或直接地联接到另一元件或者也可以存在中间元件。相反地,当提及一元件“直接地连接”或“直接地联接”到另一元件时,则不存在中间元件。
在本申请中出现的各种术语仅仅用于描述具体的实施方式的目的而无意作为对本发明的限定,除非上下文另外清楚地指出,否则单数形式意图也包括复数形式。
当在本说明书中使用术语“包括”和/或“包括有”时,这些术语指明了所述特征、整体、步骤、操作、元件和/或部件的存在,但是也不排除一个以上其他特征、整体、步骤、操作、元件、部件和/或其群组的存在和/或附加。
2019-04-20 18:29:18 cool_bot 阅读数 119
  • Python全栈视频教程

    Python全栈视频培训教程,帮助开发者从零到一入门python:1.深入理解python语法机制与底层原理,2.深入实战python各种案例 , 3.语音识别,图形界面,多线程爬虫,语音合成,游戏控制等等精彩案例。

    213933 人正在学习 去看看 尹成

语音识别控制硬件实验(语音转文字)

首先安装百度的api

sudo apt install mpg123
pip install baidu-aip monotonic pyaudio

如果出现error: command ‘arm-linux-gnueabihf-gcc’ failed with exit status 1
可能是python依赖没做好
python2.x:
sudo apt-get install python-dev
sudo apt-get install libevent-dev
python3.x:
sudo apt-get install python3-dev
sudo apt-get install libevent-dev

作者:PaulYoung_Blog
来源:CSDN
https://blog.csdn.net/talkxin/article/details/52181650

或者进入python激活环境
pi@raspberrypi:~ $ source ~/env/bin/activate# 激活Python虚拟环境

1.获取百度的key
百度keys
在Main_Demo.py里第6,7,8行添加百度密钥

2.打开程序目录4Mic_RGB

pi@raspberrypi:~ $ source ~/env/bin/activate# 激活Python虚拟环境, 如果已经激活,调到下一步
(env) pi@raspberrypi:~/ voice_control $ python Main_Demo.py

就可以实现语音识别并输出文字

2018-08-07 15:51:00 weixin_33995481 阅读数 1016
  • Python全栈视频教程

    Python全栈视频培训教程,帮助开发者从零到一入门python:1.深入理解python语法机制与底层原理,2.深入实战python各种案例 , 3.语音识别,图形界面,多线程爬虫,语音合成,游戏控制等等精彩案例。

    213933 人正在学习 去看看 尹成

代码地址如下:
http://www.demodashi.com/demo/12946.html

Python实时语音识别控制

概述

本文中的语音识别功能采用 百度语音识别库 ,首先利用 PyAudio 库录制语音指令,保存为受支持的 wav 音频文件,然后利用 百度语音识别库 提供的方法实现语音识别,最后检测识别结果,利用 PyUserInput 库提供的方法模拟控制web页面滚动。
百度语音识别为开发者提供业界优质且免费的语音服务,通过场景识别优化,为车载导航,智能家居和社交聊天等行业提供语音解决方案,准确率达到90%以上,让您的应用绘“声”绘色。

百度语音AI

准备工作

安装百度语音识别SDK

pip install baidu-aip

安装Python音频处理库 PyAudio

python -m pip install pyaudio

安装鼠标控制库 PyUserInput

pip install pyuserinput

PyUserInput 库依赖另外两个库 pywin32pyHook ,需要单独安装。
安装方法可以参考下面这篇文章:Win10 Python3.5安装PyUserInput

令附文中提到的资源下载链接:lfd-pythonlibs

另外文中提到的两个包, 需要根据自己的系统和python版本来选择。

如果系统是64位的,就要选择带 amd64 的。

如果python版本为python3.7的,就要选择带 cp37 的。

比如:pywin32-223-cp37-cp37m-win_amd64.whl
pyHook-1.5.1-cp37-cp37m-win_amd64.whl

申请百度开发者帐号

参考下面链接中的文章注册百度帐号,完成开发者认证,创建应用,获取密钥
百度AI开放平台接入流程

用Pyaudio库录制音频

Pyaudio 是一个非常强大的音频处理库,简单几行代码即可实现音频播放,录制等功能.
百度语音识别API支持的语音格式有: pcm(不压缩)wav(不压缩,pcm编码)amr(压缩格式).
推荐 pcm , 采样率: 16000 固定值, 编码: 16bit , 位深: 单声道 .百度服务端会将非pcm格式, 转为pcm格式, 因此使用wav, amr会有额外的转换耗时.
为了实现实时语音识别功能, 这里通过pyaudio录制一段wav格式的音频, 报文成wav音频文件, 供后续识别时调用.

# 用Pyaudio库录制音频
#   out_file:输出音频文件名
#   rec_time:音频录制时间(秒)
def audio_record(out_file, rec_time):
    CHUNK = 1024
    FORMAT = pyaudio.paInt16 #16bit编码格式
    CHANNELS = 1 #单声道
    RATE = 16000 #16000采样频率
    
    p = pyaudio.PyAudio()
    # 创建音频流 
    stream = p.open(format=FORMAT, # 音频流wav格式
                    channels=CHANNELS, # 单声道
                    rate=RATE, # 采样率16000
                    input=True,
                    frames_per_buffer=CHUNK)

    print("Start Recording...")

    frames = [] # 录制的音频流
    # 录制音频数据
    for i in range(0, int(RATE / CHUNK * rec_time)):
        data = stream.read(CHUNK)
        frames.append(data)
    
    # 录制完成
    stream.stop_stream()
    stream.close()
    p.terminate()

    print("Recording Done...")

    # 保存音频文件
    wf = wave.open(out_file, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

调用百度语音API

# 读取paudio录制好的音频文件, 调用百度语音API, 设置api参数, 完成语音识别
#    client:AipSpeech对象
#    afile:音频文件
#    afmt:音频文件格式(wav)
def aip_get_asrresult(client, afile, afmt):
    # 选项参数:
    # cuid    String  用户唯一标识,用来区分用户,填写机器 MAC 地址或 IMEI 码,长度为60以内
    # dev_pid String  语言类型(见下表), 默认1537(普通话 输入法模型)
    # 识别结果已经被SDK由JSON字符串转为dict
    result = client.asr(get_file_content(afile), afmt, 16000, {"cuid": CUID, "dev_pid": DEV_PID,})
    #print(result)
    # 如果err_msg字段为"success."表示识别成功, 直接从result字段中提取识别结果, 否则表示识别失败
    if result["err_msg"] == "success.": 
        #print(result["result"])
        return result["result"]
    else:
        #print(result["err_msg"])
        return ""

dev_pid 参数列表

dev_pid 语言 模型 是否有标点 备注
1536 普通话(支持简单的英文识别) 搜索模型 无标点 支持自定义词库
1537 普通话(纯中文识别) 输入法模型 有标点 不支持自定义词库
1737 英语 有标点 不支持自定义词库
1637 粤语 有标点 不支持自定义词库
1837 四川话 有标点 不支持自定义词库
1936 普通话远场 远场模型 有标点 不支持

控制(鼠标)页面滚动

# 控制鼠标滚动
def mouse_control(dir_tr):
    MOVE_DX = 5 # 每次滚动行数
    ms = PyMouse()
    horizontal = 0
    vertical = 0
    if dir_tr.find("上") != -1: # 向上移动
        vertical = MOVE_DX
        #print("vertical={0}, 向上".format(vertical))
    elif dir_tr.find("下") != -1: # 向下移动
        vertical = 0 - MOVE_DX
        #print("vertical={0}, 向下".format(vertical))
    elif dir_tr.find("左") != -1: # 向左移动
        horizontal = 0 - MOVE_DX
        #print("horizontal={0}, 向左".format(horizontal))
    elif dir_tr.find("右") != -1: # 向右移动
        horizontal = MOVE_DX
        #print("horizontal={0}, 向右".format(horizontal))

    #print("horizontal, vertical=[{0},{1}]".format(horizontal, vertical))
    # 通过scroll(vertical, horizontal)函数控制页面滚动
    # 另外PyMouse还支持模拟move光标,模拟鼠标click,模拟键盘击键等
    ms.scroll(vertical, horizontal) 

完成实时语音识别控制

while(True):
    # 请说出语音指令,例如["向上", "向下", "向左", "向右"]
    print("\n\n==================================================")
    print("Please tell me the command(limit within 3 seconds):")
    #print("Please tell me what you want to identify(limit within 10 seconds):")
    audio_record(AUDIO_OUTPUT, 3) # 录制语音指令
    print("Identify On Network...")
    asr_result =  aip_get_asrresult(client, AUDIO_OUTPUT, AUDIO_FORMAT) # 识别语音指令
    if len(asr_result) != 0: # 语音识别结果不为空,识别结果为一个list
        print("Identify Result:", asr_result[0])
        print("Start Control...")
        mouse_control(asr_result[0]) # 根据识别结果控制页面滚动
        print("Control End...")
        if asr_result[0].find("退出") != -1: # 如果是"退出"指令则结束程序
            break;
        time.sleep(1) # 延时1秒

程序运行截图

语音识别

程序运行截图

语音控制

程序运行截图

项目内文件截图

项目内文件截图
Python实时语音识别控制

代码地址如下:
http://www.demodashi.com/demo/12946.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

占个坑

博文 来自: yzy565280261

语音识别控制游戏

阅读数 145

百度语音识别

阅读数 84

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