• 谈谈NITE 2的姿势探测识别和手势探测识别


    主要内容:

    一、姿势探测识别

    1.1 内容介绍  

      NITE 2的姿势探测识别功能和人体骨骼跟踪一样,是由UserTracker提供的,在NiTE 2.0版本中,提供了两种姿势:“POSE_PSI”(我称它为“投降姿势”)和“POSE_CROSS_HAND”(称之为“双手抱胸”),除此之外,我们没办法提供自己设定的特定姿势的探测和识别。

      在之前的版本中,由于“POSE_PSI”是用来做骨架跟踪校正的标志姿势使用的,但后来NITE提供了不用校正姿势的情况下就可以进行骨架跟踪了,所以在没有特殊使用的情况下,本人(谈谈NITE 2与OpenCV结合的第二个程序(提取人体骨骼坐标))觉得在骨骼跟踪上,姿势的探测已然成为了多余的了;但对于使用姿势识别有关方面的研究的,我想这个姿势探测识别应该还是重要的,没准在NITE后面的版本中提供”自制的特定姿势“跟踪识别了。

      由于在NITE中主要提供的是人体跟踪和手的跟踪,而人体姿势探测属于前者,所以姿势探测识别和人体骨骼跟踪一样,都是使用UserTracker。首先通过获得新的使用者信息;然后根据指定使用者,利用UserTracker开始进行姿势的探测;最后根据每次探测到最新的姿势资料,进行判定识别,以及开始我们自己需要的处理工作。

    1.2 代码介绍

      同样的,直接上代码说明如何利用UserTracker进行姿势探测。

    #include "stdafx.h"
    #include <iostream>
    
    // 载入NiTE头文件
    #include <NiTE.h>
    
    // using namespace
    using namespace std;
    using namespace nite;
    
    int main( int argc, char** argv )
    {
        // 初始化NiTE环境
        NiTE::initialize();
    
        // 创建UserTracker跟踪器
        UserTracker mUserTracker;
        mUserTracker.create();
    
        while(true)
        {
            // 读取帧信息
            UserTrackerFrameRef mUserFrame;
            mUserTracker.readFrame( &mUserFrame);
    
            // 通过帧信息,获得用户数据UserData
            const Array<UserData>& aUsers = mUserFrame.getUsers();
    
            for( int i = 0; i < aUsers.getSize(); ++ i )
            {
                const UserData& rUser = aUsers[i];
                const UserId& uID = rUser.getId();
    
                if( rUser.isNew() )
                {
                    cout << "User " << uID << " found." << endl;
    
                    // 为每一个新用户进行姿势探测
                    cout << "Start pose detection " << uID<< endl;
    
                    // 探测uID的两种姿势
                    mUserTracker.startPoseDetection( uID, POSE_PSI );
                    mUserTracker.startPoseDetection( uID, POSE_CROSSED_HANDS );
                }
                else if( rUser.isLost() )
                {
                    cout << "User " << uID << " lost." << endl;
                }
                else
                {
                    // 读取用户的“POSI_PSI”的姿势状态
                    const PoseData& rPosePSI = rUser.getPose( POSE_PSI );
    
                    // 当做了“POSI_PSI”时:
                    if( rPosePSI.isEntered() )
                        cout << " 开始---投降姿势(PSI pose)" << endl;
    
                    if( rPosePSI.isHeld() )
                        cout << " 保持---投降姿势(PSI pose)" << endl;
    
                    // 当做完了“POSI_PSI”后,双手放下时:
                    if( rPosePSI.isExited() )
                        cout << "停止---投降姿势(PSI pose)" << endl;
    
                    // 同样的读取“POSE_CROSSED_HANDS”的姿势状态
                    const PoseData& rPCH = rUser.getPose( POSE_CROSSED_HANDS );
    
                    if( rPCH.isEntered() )
                        cout << " 开始---双手抱胸(Cross Hand pose)" << endl;
    
                    if( rPCH.isHeld() )
                        cout << " 保持---双手抱胸(Cross Hand pose)" << endl;
    
                    if( rPCH.isExited() )
                        cout << " 停止---双手抱胸(Cross Hand pose)" << endl;
                }
            }
        }
    
        // 关闭UserTracker跟踪
        mUserTracker.destroy();
    
        // 关闭NITE环境
        NiTE::shutdown();
    
        return 0;
    }

    上图:

      当开始姿势探测时,只要双手举起,PSI就会触发,使rPosePSI.isEntered()值为true;当保持着这个姿势一段时间,就会使rPosePSI.isHeld()值为true,表示目前的状态为保持着投降姿势;当双手放下时,rPosePSI.isExited()值为true,表示不再保持着投降姿势。同样的道理,当你做出”双手抱胸“的姿势(POSE_CROSSED_HANDS)时,也同样提供isEntered()、isHeld()和isExited()三个函数来表示当前探测的姿势的状态情况。

      注:当我无论如何做出”双手抱胸“的姿势(POSE_CROSSED_HANDS)时,都无法触发这一姿势的跟踪,所以我的结论是我还不知道怎么去”双手抱胸“~~~

    1.3 总结

      对于姿势探测识别,主要包括以下几个步骤:

    • 初始化NiTE环境:NiTE::initialize();
    • 创建UserTracker跟踪器:UserTracker::create();
    • 读取跟踪器帧信息:UserTracker::readFrame( &UserTrackerFrameRef);
    • 通过帧信息,获得用户数据UserData:mUserFrame::getUsers();
    • 对特定用户开始姿势探测(包括”投降姿势“和”双手抱胸姿势“的探测):UserTracker::startPoseDetection(UserId user, PoseType type);
    • 读取用户的指定姿势的状态信息:PoseData& getPose(PoseType type);
    • 主要有isEntered()、isHeld()、isExited()三个函数来表示当前探测的姿势的状态情况;
    • 停止UserTracker跟踪器:UserTracker::destroy();
    • 最后停止NiTE环境:NiTE::shutdown();

    二、手势探测识别

    2.1 内容介绍

      在NITE中,手势探测识别主要是由HandTracker类提供的,和UserTracker一样,HandTracker还提供的手部位置的跟踪(谈谈NITE 2的第一个程序HandViewer谈谈NITE 2与OpenCV结合的第一个程序,以及谈谈NITE 2与OpenCV结合提取指尖坐标等处都做了介绍了)。根据目前的NITE提供的手势跟踪和之前的版本个人感觉差不多。首先都是不针对指定用户的手势识别(这点和姿势探测识别不一样),而是针对整个界面帧信息进行分析,找到符合的手势;其次探测识别的手势只有三个:”GESTURE_WAVE“(挥手)、”GESTURE_CLICK“(手掌前推在缩回来)和”GESTURE_HAND_RAISE“(手举起)。最后目前都没有提供自制的手势探测(这点和姿势探测一样)。

    2.2 代码说明

    #include "stdafx.h"
    #include <iostream>
    
    // 载入NiTE头文件
    #include <NiTE.h>
    
    // using namespace
    using namespace std;
    using namespace nite;
    
    int main( int argc, char** argv )
    {
        // 初始化NiTE环境
        NiTE::initialize();
    
        // 创建HandTracker跟踪器
        HandTracker mHandTracker;
        mHandTracker.create();
    
        // 设定手势探测(GESTURE_WAVE、GESTURE_CLICK和GESTURE_HAND_RAISE)
        mHandTracker.startGestureDetection( GESTURE_WAVE );
        mHandTracker.startGestureDetection( GESTURE_CLICK );
        mHandTracker.startGestureDetection( GESTURE_HAND_RAISE );
    
        while(true)
        {
            // 读取帧信息
            HandTrackerFrameRef mHandFrame;
            mHandTracker.readFrame( &mHandFrame );
    
            // 整个界面帧信息进行分析,找到符合的手势
            const Array<GestureData>& aGestures = mHandFrame.getGestures();
    
            for( int i = 0; i < aGestures.getSize(); ++ i )
            {
                const GestureData& rGesture = aGestures[i];
    
                // 对找到的手势进行类型判断,并输出类型
                cout << "Detect gesture ";
                switch( rGesture.getType() )
                {
                case GESTURE_WAVE:
                    cout << "摇手手势---“wave”:";
                    break;
    
                case GESTURE_CLICK:
                    cout << "前推并收回手势---“click”";
                    break;
    
                case GESTURE_HAND_RAISE:
                    cout << "举起手势---“hand raise”";
                    break;
                }
    
                // 得到的手势信息中还包含了当前手势的坐标位置
                const Point3f& rPos = rGesture.getCurrentPosition();
                cout << " 手势位置为: (" << rPos.x << ", " << rPos.y << ", " << rPos.z << ")" << endl;
    
                // 以及手势状态,完成状态和进行状态
                if( rGesture.isComplete() )
                    cout << "  手势完成";
                if( rGesture.isInProgress() )
                    cout << "  手势正在进行";
    
                cout << endl;
            }
        }
    
        // 关闭HandTracker跟踪
        mHandTracker.destroy();
    
        // 关闭NITE环境
        NiTE::shutdown();
    
        return 0;
    }

    上图:

      注:三个手势中”举起“手势太好识别了,直接掩盖了其它两个手势,所以在实际的手势识别中,我建议不用检测”举起“这个手势~~~。我把上面代码中mHandTracker.startGestureDetection( GESTURE_HAND_RAISE );给注释了,再看运行结果:

      注:排除了”举起“手势的捣乱之后,发现”前推并收回“手势(click),动作最好掌控,识别过程和效果也是最好(个人觉得);同时我怎么”摇手“(wave),好像都出不了检测结果,具体什么原因现在我也不知道(估计又是我手势做的不对),有知道的烦请教教我,谢谢~~~

    2.3 总结

      具体手势探测识别流程和1.3的相似,看了上面的代码肯定知道,所以这里就不写了。最后我的建议是:如果要进行手势探测识别的话,我提议是探测”click“手势~~~

      写的粗糙~~~

      

  • 相关阅读:
    Struts数据效验
    Struts2中国际化
    ValueStack对象
    Ognl表达式语言
    Struts2拦截器
    ubuntu下tomcat运行不起来解决
    Windows 下的SSH客户端
    远程管理控制ssh
    linux用户和组账户管理
    搭建Java服务器,并且实现远程安全访问linux系统
  • 原文地址:https://www.cnblogs.com/yemeishu/p/2876422.html
Copyright © 2020-2023  润新知