Leapmotion 手势识别,支持识别:握拳、抓取、左右上下前后滑动,大拇指上下朝向、放大/缩小、旋转。
使用步骤
1.添加Leapmotion SDK
2.添加LeapServiceProvider.cs 脚本,SDK中自带
3.添加LeapGestures.cs 脚本,在下面提供
作为测试使用,在场景中添加了cube,挂载了这两个脚本,直观又方便...
代码如下:
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));
}
}
测试后有些手势识别仍需要优化,后续持续更新...
网友评论