kinect筆記 三、識別手型(手部位置和手勢)


在unity中獲取手的位置

創建一個空物體,命名為KinectManager,給該物體綁定上KinectManager 和 InteractionManager腳本

其中InteractionManager腳本上有三個紋理,Grip Hand Texture 是握拳,Release Hand Texture是手攤開的狀態,Normal Hand Texture理論上應該是手呈半握狀態並且其中的個別手指攤開,但是我從沒有觸發過

再新建一個空物體,命名為InteractionListener,新建一個腳本MyInteractionListener,這個腳本需要跟攝像機和InteractionManager相關聯,但是InteractionManager可以用kinect的屬性獲取,所以只需要將攝像機拖拽到腳本上關聯即可

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyInteractionListener : MonoBehaviour ,InteractionListenerInterface{

    [Tooltip("Camera used for screen ray-casting. This is usually the main camera.  用於屏幕光線投射的照相機。這通常是主相機。")]
    public Camera screenCamera;
    
    //[Tooltip("Interaction manager instance, used to detect hand interactions. If left empty, it will be the first interaction manager found in the scene.")]
    [Tooltip("交互管理器實例,用於檢測手交互。如果為空,它將是場景中發現的第一個交互管理器")]
    public InteractionManager interactionManager;
    
    // hand interaction variables   手的交互變量
    private InteractionManager.HandEventType lastHandEvent = InteractionManager.HandEventType.None;

    // normalized and pixel position of the cursor  鼠標光標的統一化和位置
    private Vector3 screenNormalPos = Vector3.zero;
    private Vector3 screenPixelPos = Vector3.zero;
    private Vector3 newObjectPos = Vector3.zero;


    /*[Tooltip("Minimum Z-position of the dragged object, when moving forward and back.")]
    public float minZ = 0f;

    [Tooltip("Maximum Z-position of the dragged object, when moving forward and back.")]
    public float maxZ = 5f;*/


    /// <summary>
    /// UDP客戶端
    /// </summary>
    public UDPClient udpClient;

    // Use this for initialization
    void Start () {
        //默認情況下,將主相機設置為屏幕攝像機
        if (screenCamera == null)
        {
            screenCamera = Camera.main;
        }
        // 獲取交互管理器實例
        if (interactionManager == null)
        {
            interactionManager = InteractionManager.Instance;
        }
    }

    // Update is called once per frame
    void Update () {
        //如果交互管理器不為空,並且已經初始化
        if (interactionManager != null && interactionManager.IsInteractionInited())
        {

            // check if there is an underlying object to be selected    檢查是否存在要選擇的基礎對象
            if (lastHandEvent == InteractionManager.HandEventType.Grip && screenNormalPos != Vector3.zero)
            {
                // convert the normalized screen pos to pixel pos   將標准化屏幕POS轉換為像素POS
                screenNormalPos = interactionManager.IsLeftHandPrimary() ? interactionManager.GetLeftHandScreenPos() : interactionManager.GetRightHandScreenPos();

                screenPixelPos.x = (int)(screenNormalPos.x * (screenCamera ? screenCamera.pixelWidth : Screen.width));
                screenPixelPos.y = (int)(screenNormalPos.y * (screenCamera ? screenCamera.pixelHeight : Screen.height));
                Ray ray = screenCamera ? screenCamera.ScreenPointToRay(screenPixelPos) : new Ray();

                // check if there is an underlying objects  檢查是否存在底層對象
                RaycastHit hit;

                Debug.Log("握拳");
                Debug.Log(screenPixelPos);
                //udpClient.SocketSend(screenPixelPos.x + "," + screenPixelPos.y);
                //udpClient.SocketSend(screenNormalPos.x + "," + screenNormalPos.y);
                //udpClient.SocketSend(screenNormalPos.x.ToString("f2") + "," + screenNormalPos.y.ToString("f2"));//f2保留兩位小數
                //udpClient.SocketSend("anXia");
                if (Physics.Raycast(ray, out hit))
                {
                    Debug.Log("位置");
                    Debug.Log(hit.point);
                    /*foreach (GameObject obj in draggableObjects)
                    {
                        if (hit.collider.gameObject == obj)
                        {
                            // an object was hit by the ray. select it and start drgging
                            draggedObject = obj;
                            draggedObjectOffset = hit.point - draggedObject.transform.position;
                            draggedObjectOffset.z = 0; // don't change z-pos

                            draggedNormalZ = (minZ + screenNormalPos.z * (maxZ - minZ)) -
                                draggedObject.transform.position.z; // start from the initial hand-z

                            // set selection material
                            draggedObjectMaterial = draggedObject.GetComponent<Renderer>().material;
                            draggedObject.GetComponent<Renderer>().material = selectedObjectMaterial;

                            // stop using gravity while dragging object
                            draggedObject.GetComponent<Rigidbody>().useGravity = false;
                            break;
                        }
                    }*/
                }
            }
            else
            {

                // continue dragging the object 繼續拖動對象
                screenNormalPos = interactionManager.IsLeftHandPrimary() ? interactionManager.GetLeftHandScreenPos() : interactionManager.GetRightHandScreenPos();

                // convert the normalized screen pos to 3D-world pos    將標准化的屏幕POS轉換為3D世界POS
                screenPixelPos.x = (int)(screenNormalPos.x * (screenCamera ? screenCamera.pixelWidth : Screen.width));
                screenPixelPos.y = (int)(screenNormalPos.y * (screenCamera ? screenCamera.pixelHeight : Screen.height));
                /*//screenPixelPos.z = screenNormalPos.z + draggedObjectDepth;
                screenPixelPos.z = (minZ + screenNormalPos.z * (maxZ - minZ)) - draggedNormalZ -
                    (screenCamera ? screenCamera.transform.position.z : 0f);*/


                //Debug.Log("手掌");
                //Debug.Log(screenPixelPos);
                //udpClient.SocketSend(screenPixelPos.x + "," + screenPixelPos.y);
                //udpClient.SocketSend(screenNormalPos.x + "," + screenNormalPos.y);
                //udpClient.SocketSend(screenNormalPos.x.ToString("f2") + "," + screenNormalPos.y.ToString("f2"));
                //udpClient.SocketSend("taiQi");
                //newObjectPos = screenCamera.ScreenToWorldPoint(screenPixelPos) - draggedObjectOffset;

                // check if the object (hand grip) was released
                /*bool isReleased = lastHandEvent == InteractionManager.HandEventType.Release;

                if (isReleased)
                {
                    // restore the object's material and stop dragging the object
                    draggedObject.GetComponent<Renderer>().material = draggedObjectMaterial;

                    if (useGravity)
                    {
                        // add gravity to the object
                        draggedObject.GetComponent<Rigidbody>().useGravity = true;
                    }

                    draggedObject = null;
                }*/
            }
        }

    }
    public void HandGripDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos)
    {
        if (!isHandInteracting || !interactionManager)
            return;
        if (userId != interactionManager.GetUserID())
            return;

        lastHandEvent = InteractionManager.HandEventType.Grip;
        //isLeftHandDrag = !isRightHand;
        screenNormalPos = handScreenPos;
    }

    public void HandReleaseDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos)
    {
        if (!isHandInteracting || !interactionManager)
            return;
        if (userId != interactionManager.GetUserID())
            return;

        lastHandEvent = InteractionManager.HandEventType.Release;
        //isLeftHandDrag = !isRightHand;
        screenNormalPos = handScreenPos;
    }
    public bool HandClickDetected(long userId, int userIndex, bool isRightHand, Vector3 handScreenPos)
    {
        return true;
    }
}

 

需要注意的是,獲取到的手的坐標是屏幕坐標,就是0---1的范圍,如果想要應用,還需要轉換成世界坐標,另外注意unity中的坐標軸,跟其他程序或軟件的坐標軸可能會不同


免責聲明!

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



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