談談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“手勢~~~

  寫的粗糙~~~

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM