HoloLens 手势识别

作者:追风剑情 发布于:2023-10-18 17:47 分类:Unity3d

示例:手势 OK

using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.Utilities;
/// <summary>
/// 识别OK手势
/// </summary>
public class GestureRecognitionOK : GameEventBehaviour
{
    [SerializeField]
    private GestureRecognitionDebugUI debugUI;
    //true 识别成功
    private bool isHandOK;

    protected override void OnUpdate()
    {
        bool leftHandOK = RecognitionHandOK(Handedness.Left);
        bool rightHandOK = RecognitionHandOK(Handedness.Right);
        bool ok = leftHandOK || rightHandOK;
        debugUI.IsOK = ok;

        //识别成功需要触发一次事件
        if (ok && !isHandOK)
            FireEvent(GameEventType.GESTURE_RECOGNITION_OK);
        isHandOK = ok;
    }

    private bool RecognitionHandOK(Handedness handedness)
    {
        var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
        //判断手是否正在被追踪
        if (!handJointService.IsHandTracked(handedness))
            return false;
        //食指尖与拇指尖的捏合度。取值范围0~1,0表示完全张开,1表示完全捏合。
        float pinch = HandPoseUtils.CalculateIndexPinch(handedness);
        //拇指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float thumbCurl = HandPoseUtils.ThumbFingerCurl(handedness);
        //食指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float indexCurl = HandPoseUtils.IndexFingerCurl(handedness);
        //中指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float middleCurl = HandPoseUtils.MiddleFingerCurl(handedness);
        //无名指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float ringCurl = HandPoseUtils.RingFingerCurl(handedness);
        //小指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float pinkyCurl = HandPoseUtils.PinkyFingerCurl(handedness);
        //获取手掌姿态数据
        MixedRealityPose palmPose;
        HandJointUtils.TryGetJointPose(TrackedHandJoint.Palm, handedness, out palmPose);
        Vector3 palmEuler = palmPose.Rotation.eulerAngles;

        //写入Debug
        debugUI.FingerCurlValue(handedness, pinch, thumbCurl, indexCurl, middleCurl, ringCurl, pinkyCurl, palmPose);

        //判断左手掌无效朝向
        if (handedness == Handedness.Left && (palmEuler.z < 20 || palmEuler.z > 140))
            return false;

        //判断右手掌无效朝向
        if (handedness == Handedness.Right && (palmEuler.z < 230 || palmEuler.z > 330))
            return false;

        //判断无效捏合度
        if (pinch < 0.6f)
            return false;

        //判断无效曲度
        if (thumbCurl < 0.45f || thumbCurl > 0.65f)
            return false;
        if (indexCurl < 0.3f || indexCurl > 0.45f)
            return false;
        if (middleCurl > 0.05f || ringCurl > 0.05f || pinkyCurl > 0.05f)
            return false;

        return true;
    }
}  

示例:手势 ×

using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.Utilities;
/// <summary>
/// 识别NO手势
/// </summary>
public class GestureRecognitionNO : GameEventBehaviour
{
    [SerializeField]
    private GestureRecognitionDebugUI debugUI;
    //true 识别成功
    private bool isHandNO;

    protected override void OnUpdate()
    {
        bool no = RecognitionHandNO();
        debugUI.IsNO = no;

        //识别成功需要触发一次事件
        if (no && !isHandNO)
            FireEvent(GameEventType.GESTURE_RECOGNITION_NO);
        isHandNO = no;
    }

    private bool RecognitionHandNO()
    {
        var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
        //判断双手是否正在被追踪
        if (!handJointService.IsHandTracked(Handedness.Left) || !handJointService.IsHandTracked(Handedness.Right))
            return false;

        //食指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float indexCurlLeft = HandPoseUtils.IndexFingerCurl(Handedness.Left);
        float indexCurlRight = HandPoseUtils.IndexFingerCurl(Handedness.Right);
        //中指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float middleCurlLeft = HandPoseUtils.MiddleFingerCurl(Handedness.Left);
        float middleCurlRight = HandPoseUtils.MiddleFingerCurl(Handedness.Right);
        //无名指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float ringCurlLeft = HandPoseUtils.RingFingerCurl(Handedness.Left);
        float ringCurlRight = HandPoseUtils.RingFingerCurl(Handedness.Right);
        //小指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float pinkyCurlLeft = HandPoseUtils.PinkyFingerCurl(Handedness.Left);
        float pinkyCurlRight = HandPoseUtils.PinkyFingerCurl(Handedness.Right);

        //获取食指中关节姿态数据
        MixedRealityPose indexMiddlePoseLeft, indexMiddlePoseRight;
        HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexMiddleJoint, Handedness.Left, out indexMiddlePoseLeft);
        HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexMiddleJoint, Handedness.Right, out indexMiddlePoseRight);
        //两食指中关节之间的距离
        float indexMiddleDistance = Vector3.Distance(indexMiddlePoseLeft.Position, indexMiddlePoseRight.Position);

        //写入Debug
        debugUI.BetweenIndexMiddleDistance(indexMiddleDistance);

        //判断左右食指无效曲度
        if (indexCurlLeft > 0.1 || indexCurlRight > 0.1)
            return false;
        //判断左右中指无效曲度
        if (middleCurlLeft < 0.5 || middleCurlRight < 0.5)
            return false;
        //判断左右无名指无效曲度
        if (ringCurlLeft < 0.5 || ringCurlRight < 0.5)
            return false;
        //判断左右小指无效曲度
        if (pinkyCurlLeft < 0.5 || pinkyCurlRight < 0.5)
            return false;
        //判断左右食指中关节无效距离
        if (indexMiddleDistance > 0.025f)
            return false;

        return true;
    }
}  

示例:手势 Yes

using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.Utilities;
/// <summary>
/// 识别Yes手势
/// </summary>
public class GestureRecognitionYes : GameEventBehaviour
{
    [SerializeField]
    private GestureRecognitionDebugUI debugUI;
    //true 识别成功
    private bool isHandYes;

    protected override void OnUpdate()
    {
        bool leftHandYes = RecognitionHandYes(Handedness.Left);
        bool rightHandYes = RecognitionHandYes(Handedness.Right);
        bool yes = leftHandYes || rightHandYes;
        debugUI.IsYes = yes;

        //识别成功需要触发一次事件
        if (yes && !isHandYes)
            FireEvent(GameEventType.GESTURE_RECOGNITION, GestureType.YES);
        isHandYes = yes;
    }

    private bool RecognitionHandYes(Handedness handedness)
    {
        var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
        //判断手是否正在被追踪
        if (!handJointService.IsHandTracked(handedness))
            return false;

        //食指尖与拇指尖的捏合度。取值范围0~1,0表示完全张开,1表示完全捏合。
        float pinch = HandPoseUtils.CalculateIndexPinch(handedness);
        //拇指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float thumbCurl = HandPoseUtils.ThumbFingerCurl(handedness);
        //食指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float indexCurl = HandPoseUtils.IndexFingerCurl(handedness);
        //中指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float middleCurl = HandPoseUtils.MiddleFingerCurl(handedness);
        //无名指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float ringCurl = HandPoseUtils.RingFingerCurl(handedness);
        //小指卷曲度。取值范围0~1,0表示完全伸直,1表示完全卷曲。
        float pinkyCurl = HandPoseUtils.PinkyFingerCurl(handedness);

        //写入Debug
        debugUI.FingerCurlValue(handedness, thumbCurl, indexCurl, middleCurl, ringCurl, pinkyCurl);

        //判断手势无效曲度
        if (thumbCurl < 0.5f) return false;
        if (indexCurl > 0.03f) return false;
        if (middleCurl > 0.1f) return false;
        if (ringCurl < 0.1f) return false;
        if (pinkyCurl < 0.1f) return false;

        return true;
    }
} 

示例:接口定义

/// <summary>
/// 需要手势操作的界面实现此接口
/// </summary>
public interface IGestureInteractable
{
    void OnGestureRecognition(GestureType type);
}


//手势类别
public enum GestureType
{
    OK,
    NO,
    YES
}
 

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号