识别手势语音重点

不说点废话,看代码是不是蒙圈了呢

环境配置

  Kinect2 SDK直接安装,安装完成后会在系统环境变量中加入变量值 KINECTSDK20_DIR,语音文件安装需要安装多个文件,其中包括 runtime(speech SDK 的运行环境)、speech SDK、语言文件,要先安装运行环境在安装SDK,接下来安装需要的语言包

Kinect for Windows SDK 2.0
Microsoft Speech Platform - Software Development Kit (SDK) (Version 11)

kinect SDK

初始化SDK 并打开

IKinectSensor* m_pKinect ;
GetDefaultKinectSensor(&m_pKinect);
m_pKinect->Open();

读取身体数据

inline HRESULT KinectApp::initBodySource()
{
    //添加身体数据源
    IBodyFrameSource* bodySource = nullptr;
    HRESULT hr = m_pKinect->get_BodyFrameSource(&bodySource);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("get_BodyFrameSource failed");
        return hr;
    }
    //读取身体数据源
    INT32 nBodyNum = 0;
    bodySource->get_BodyCount(&nBodyNum);
    hr = bodySource->OpenReader(&bodyReader); // 准备读取body数据
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("OpenReader failed");
        return hr;
    }
    return hr;
}

获取身体数据

inline void KinectApp::getBody(void){

    Sleep(sleeptime);
    // 获取最近的一帧数据
    IBodyFrame* bodyf = nullptr;
    bodyReader->AcquireLatestFrame(&bodyf);
    if (!bodyf)
    {
        return;
    }
    // 更新所有人身体数据
    IBody* ppBodies[BODY_COUNT] = { 0 };
    bodyf->GetAndRefreshBodyData(BODY_COUNT, ppBodies);

    IBody*pbody = getTrackedBody(ppBodies);
    if (pbody != nullptr)
    {
        getTrackedBodyJoints(pbody);
    }

    SafeRelease(bodyf);
}

每次获取到身体都为6个人的数组,因为是单人控制鼠标,获取到任务的id是无先后顺序的,所以获取到任务之后要进行锁定,下次获取是先判断当前锁定人物还在不,如果在直接获取手势,如果不在则锁定当前第一人

inline IBody* KinectApp::getTrackedBody(IBody* ppBodies[])

获取手势

HandState rightHandState = HandState_Unknown;
pBody->get_HandRightState(&rightHandState);

判断是不是在范围内,因为设备可获取范围为4米这里规定为2.8米内

inline bool KinectApp::isInScope(IBody* pBody)

获取手势坐标

Joint joints[JointType_Count];
HRESULT hr = pBody->GetJoints(_countof(joints), joints);
Joint rightJoint = joints[JointTypeArray[i]];
rightJoint.Position.X;
rightJoint.Position.Y;
rightJoint.Position.Z;

记录历史6个点的位置,用于求每次的位置的平均值,在误差值范围内更准确,显然鼠标的移动显得没有直接取当前那么流畅,还可以接受,不卡顿

inline BodyRect KinectApp::getHandRect(Joint joints[],JointType JointTypeArray[])

数据回调

void KinectApp::m_setActionCallBack(ActionCallBack call)
void KinectApp::m_setErrorActionCallBack(ErrorCallBack call)
void KinectApp::m_setPanActionCallBack(PanActionCallBack call)
void KinectApp::m_actionCallBack(int x,int y,int z,ActionType type)

滑动手势,实现难,操作起来更难,起始点难以确定,最后放弃

void KinectApp::m_panActionCallBack()

Speech SDK

HRESULT MKSpeech::init_speech_recognizer()
{
    HRESULT hr = S_OK;
    // 创建语音输入流
    hr = CoCreateInstance(CLSID_SpStream, nullptr, CLSCTX_INPROC_SERVER, __uuidof(ISpStream), (void**)&m_pSpeechStream);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("CoCreateInstance CLSID_SpStream failed");
        return hr;
    }
    // 创建语言识别器
    hr = CoCreateInstance(CLSID_SpInprocRecognizer, nullptr, CLSCTX_INPROC_SERVER, __uuidof(ISpRecognizer), (void**)&m_pSpeechRecognizer);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("CoCreateInstance CLSID_SpInprocRecognizer failed");
        return hr;
    }
    //创建默认音频输入对象
    CComPtr ISPToken = nullptr;
    hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN,&ISPToken);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("SpGetDefaultTokenFromCategoryId failed");
        return hr;
    }
    //设置识别引擎输入源
    hr = m_pSpeechRecognizer->SetInput(ISPToken,TRUE);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("SetInput failed");
        return hr;
    }
    // 创建语音识别对象
    ISpObjectToken *pEngineToken = nullptr;
    hr = SpFindBestToken(SPCAT_RECOGNIZERS, L"language=804", nullptr, &pEngineToken);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("SpFindBestToken failed");
        return hr;
    }
    // 设置待识别语言
    m_pSpeechRecognizer->SetRecognizer(pEngineToken);
    // 创建语音识别上下文
    hr = m_pSpeechRecognizer->CreateRecoContext(&m_pSpeechContext);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechRecognizer CreateRecoContext failed");
        return hr;
    }
    SafeRelease(pEngineToken);
    // 适应性 ON! 防止因长时间的处理而导致识别能力的退化
    hr = m_pSpeechRecognizer->SetPropertyNum(L"AdaptationOn", 0);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechRecognizer SetPropertyNum failed");
        return hr;
    }
    // 创建语法
    hr = m_pSpeechContext->CreateGrammar(1, &m_pSpeechGrammar);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechContext CreateGrammar failed");
        return hr;
    }
    //加载语法规则
    hr = m_pSpeechGrammar->LoadCmdFromFile(s_GrammarFileName, SPLO_DYNAMIC);
    if (!SUCCEEDED(hr)){
        hr = m_pSpeechGrammar->LoadCmdFromFile(L".\\resources\\app\\kinectLib\\Grammar.xml", SPLO_DYNAMIC);     
    }
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechGrammar LoadCmdFromFile failed");
        return hr;
    }
    // 激活语法规则
    hr = m_pSpeechGrammar->SetRuleState(nullptr, nullptr, SPRS_ACTIVE);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechGrammar SetRuleState failed");
        return hr;
    }
    // 设置识别器一直读取数据
    hr = m_pSpeechRecognizer->SetRecoState(SPRST_ACTIVE);
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechRecognizer SetRecoState failed");
        return hr;
    }
    // 设置对识别事件感兴趣
    hr = m_pSpeechContext->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));
    if (!SUCCEEDED(hr))
    {
        m_errorCallBack("m_pSpeechContext SetInterest failed");
        return hr;
    }
    // 保证语音识别处于激活状态
    m_pSpeechContext->Resume(0);
    // 获取识别事件
    m_hSpeechEvent = m_pSpeechContext->GetNotifyEventHandle();
    
    return hr;
}

音频处理线程,语音识别是异步的,这里用了WaitForMultipleObjects 查看信号量是否改变, 在异步线程中执行该方法

void MKSpeech::AudioThread(MKSpeech* pointer){
    // 先设置
    HANDLE events[] = { pointer->m_hSpeechEvent };
    bool exit = false;
    while (!exit) {
        switch (::WaitForMultipleObjects(lengthof(events), events, FALSE, 8000)){
        case WAIT_OBJECT_0:
            // 语言识别
            pointer->speech_process();
            exit = true;
            pointer->close();
            break;
        case WAIT_TIMEOUT:
            pointer->m_audioCallBack("faild",AudioCallStatus_Faild);
            exit = true;
            pointer->close();
            break;
        }
    }
}

音频处理

void MKSpeech::speech_process()

音频文件格式介绍
item tag 这里采用了base64字符串 5qyn5rSy,亚洲、青海、黑龙江、欧洲 等语音识别到都返回 5qyn5rSy 作为识别到的字符


5qyn5rSy

河南大写
欧洲
亚洲
青海
黑龙江


  
    
      
        5qyn5rSy
        
          河南大写
          欧洲
          亚洲
          青海
          黑龙江
        
      
      
        5qyn5rSy
        
          河南大写
          欧洲
          亚洲
          青海
          黑龙江
        
      
    
  

代码地址:链接: https://pan.baidu.com/s/1aY8S2VWOBIsW-JbAqcdEow 提取码: kujw

你可能感兴趣的:(识别手势语音重点)