美文网首页动作抓取
Unity Leapmotion 手势识别

Unity Leapmotion 手势识别

作者: SilenceTT | 来源:发表于2021-12-07 16:43 被阅读0次

Leapmotion 手势识别,支持识别:握拳、抓取、左右上下前后滑动,大拇指上下朝向、放大/缩小、旋转。

使用步骤

1.添加Leapmotion SDK

2.添加LeapServiceProvider.cs 脚本,SDK中自带

3.添加LeapGestures.cs 脚本,在下面提供

作为测试使用,在场景中添加了cube,挂载了这两个脚本,直观又方便...

image.png

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Leap;
using Leap.Unity;

public class LeapGestures : MonoBehaviour
{
    public static bool Gesture_left = false;
    public static bool Gesture_right = false;
    public static bool Gesture_up = false;
    public static bool Gesture_down = false;
    public static bool Gesture_zoom = false;
    public static float movePOs = 0.0f;

    private LeapProvider mProvider;
    private Frame mFrame;
    private Hand mHand;

    private Vector leftPosition;
    private Vector rightPosition;
    public static float zoom = 1.0f;

    //手掌移动的最小速度
    [Tooltip("Velocity (m/s) of Palm ")]
    public float smallestVelocity = 1.45f;

    //单方向上手掌移动的速度
    [Tooltip("Velocity (m/s) of Single Direction ")]
    [Range(0, 1)]
    public float deltaVelocity = 1.0f;

    //旋转灵敏度
    private const float rotate_sensitive = 100f;
    //旋转初始位置值
    private const float rotate_initial_value = 0f;  

    private float deltaAngleThumb = 90;

    void Start()
    {
        mProvider = FindObjectOfType<LeapProvider>() as LeapProvider;
    }

    void Update()
    {
        //获取当前帧
        mFrame = mProvider.CurrentFrame;

        //获得手的个数
        if (mFrame.Hands.Count > 0)
        {
            if (mFrame.Hands.Count == 2)
                zoom = CalcuateDistance(mFrame);

            if (mFrame.Hands.Count == 1)
                LRUDGestures(mFrame, ref movePOs);
        }
    }

    float CalcuateDistance(Frame mFrame)
    {
        Gesture_zoom = true;
        Gesture_left = false;
        Gesture_right = false;

        float distance = 0f;

        foreach (var itemHands in mFrame.Hands)
        {
            if (itemHands.IsLeft)
            {
                leftPosition = itemHands.PalmPosition;
            }
            if (itemHands.IsRight)
            {
                rightPosition = itemHands.PalmPosition;
            }
        }

        if (leftPosition != Vector.Zero && rightPosition != Vector.Zero)
        {
            Vector3 leftPos = new Vector3(leftPosition.x, leftPosition.y, leftPosition.z);
            Vector3 rightPos = new Vector3(rightPosition.x, rightPosition.y, rightPosition.z);

            distance = 10 * Vector3.Distance(leftPos, rightPos);
            print("distance" + distance);
        }

        if (distance != 0)
            return distance;
        else
            return distance = 1;
    }

    void LRUDGestures(Frame mFrame, ref float movePOs)
    {
        Gesture_zoom = false;
        foreach (var item in mFrame.Hands)
        {
            int numFinger = item.Fingers.Count;

            if (item.GrabStrength == 1)
            {
                //...
            }
            else if (item.GrabStrength == 0)
            {
                movePOs = item.PalmPosition.x;

                if (isMoveLeft(item))
                {
                    Gesture_left = true;
                    Gesture_right = false;
                    print("move left");
                }
                else if (isMoveRight(item))
                {
                    Gesture_left = false;
                    Gesture_right = true;
                    print("move Right");
                }
                else if (isMoveUp(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move Up");
                }
                else if (isMoveDown(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move Down");

                }
                else if (isMoveForward(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move Forward");

                }
                else if (isMoveBack(item))
                {
                    Gesture_left = false;
                    Gesture_right = false;
                    print("move back");

                }
                else if (isStationary(item))
                {
                    print("is Stationary");
                }
                else if (isOpenFullHand(item))
                {
                    print("is Open Full Hand");
                }
                else if (isCloseFullHand(item))
                {
                    print("is Close Full Hand");
                }

                isRotation(item);
            }
        }
    }

    // 是否握拳
    private bool isStone(Hand hand)
    {
        return hand.GrabAngle > 2.0f;
    }

    // 是否抓取
    public bool isGrabHand(Hand hand)
    {
        return hand.GrabStrength > 0.8f;        //抓取力 
    }

    // 手划向右边
    public bool isMoveRight(Hand hand)
    {

        return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand);
    }

    // 手划向左边
    public bool isMoveLeft(Hand hand)
    {
        return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand);
    }

    // 手划向上方
    public bool isMoveUp(Hand hand)
    {
        return hand.PalmVelocity.y > deltaVelocity && !isStationary(hand);
    }

    // 手划向下方
    public bool isMoveDown(Hand hand)
    {
        return hand.PalmVelocity.y < -deltaVelocity && !isStationary(hand);
    }

    // 手划向前方
    public bool isMoveForward(Hand hand)
    {
        return hand.PalmVelocity.z > deltaVelocity && !isStationary(hand);
    }

    // 手划向后方
    public bool isMoveBack(Hand hand)
    {
        return hand.PalmVelocity.z < -deltaVelocity && !isStationary(hand);
    }

    // 固定不动的
    public bool isStationary(Hand hand)
    {
        return hand.PalmVelocity.Magnitude < smallestVelocity;      //Vector3.Magnitude返回向量的长度
    }

    // 判断大拇指是否竖直或者向下
    protected bool isThumbDirection(Hand hand)
    {
        Vector3 dir = hand.GetPinchPosition();

        List<Finger> listOfFingers = hand.Fingers;
        for (int f = 0; f < listOfFingers.Count; f++)
        {
            Finger finger = listOfFingers[f];
            if (finger.Type == Finger.FingerType.TYPE_THUMB)
            {
                float angleThumbFinger = angle2LeapVectors(finger.Direction,
                                            UnityVectorExtension.ToVector(dir));

                float angleThumbFinger2 = angle2LeapVectors(
                                             finger.TipPosition - hand.PalmPosition, UnityVectorExtension.ToVector(dir));
                
                if (angleThumbFinger < deltaAngleThumb
                   || angleThumbFinger2 < deltaAngleThumb)
                    return true;
                else
                    return false;
            }
        }
        return false;
    }

    // 放大手势,手掌全展开
    protected bool isOpenFullHand(Hand hand)
    {
        return hand.GrabStrength == 0;
    }

    // 缩小手势,手掌握拳
    protected bool isCloseFullHand(Hand hand)
    {
        return hand.GrabAngle > 2.0f;
    }

    // 旋转
    protected void isRotation(Hand hand)
    {
        if (hand.IsLeft || hand.IsRight)
        {
            Vector3 value = transform.localEulerAngles;
            value = new Vector3(hand.PalmPosition.y * rotate_sensitive + rotate_initial_value, hand.PalmPosition.x * rotate_sensitive + rotate_initial_value, 0);
            transform.localEulerAngles = value;
        }
        else
        {
            hand.PalmPosition.y = transform.localEulerAngles.x;
            hand.PalmPosition.x = transform.localEulerAngles.y;
        }
    }

    // 向量转化成 角度
    protected float angle2LeapVectors(Leap.Vector a, Leap.Vector b)
    {
        return Vector3.Angle(UnityVectorExtension.ToVector3(a), UnityVectorExtension.ToVector3(b));
    }
}

测试后有些手势识别仍需要优化,后续持续更新...

相关文章

网友评论

    本文标题:Unity Leapmotion 手势识别

    本文链接:https://www.haomeiwen.com/subject/txkaxrtx.html