Leap Motion追踪手、手指和工具

Leap Motion翻译系列文章http://52coding.com/leap-motion-official-doc-translation

追踪手、手指和工具

手、手指和工具是Leap Motion系统的基本追踪实体。这篇文章将详细讨论如何获取和使用这些实体对象。

概述

Leap的API定义了一个可以表示每个基本追踪到的物体的类。 帧对象提供了一个可以访问手、手指和工具的列表。指尖和工具都是尖端物体,并且他们可以被同时放入尖端列表PointableList中,或者分别使用手指列表FingerList和工具列表类ToolList。手对象提供访问他们的手指和工具的途径(都一起在尖端列表中或者分开)。   手、手指和工具的物体特点在Leap的坐标系统下(以毫米为单位衡量)有报告。Leap的SDK提供了向量类(Vector)来描述点和朝向。向量类提供了一些有用的向量运算的数学函数[这个挺不错,避免自己写了]。

手和尖端列表

列表类都都拥有近似的结构。他们被设计成向量形式矩阵并且支持迭代器。你不能移除或者改变从Leap API接收的列表中的成员变量,但你可以组合列表中的同一个类型的对象。 对某一个列表使用迭代器:

for(HandList::const_iterator hl = handList.begin(); hl != handList.end();)
                std::cout << *hl << std::endl;

手、尖端物体、手指和工具列表基于在Leap坐标系统下的相对位置,定义了额外的函数来获取列表中的成员变量。这些函数包含leftmost(),rightmost(),和frontmost()。接下来的小片段代码说明了使用这些函数的方法:

Leap::Finger farLeft = frame.fingers().leftmost();
Leap::Finger mostForwardOnHand = frame.hands()[0].fingers().frontmost();
Leap::Tool rightTool = frame.tools().rightmost();

一个更复杂的例子是计算一个包含检测到的所有尖端物体箱子的矩形体。因为在API中没有提供,这个例子定义了它自己的函数来获取顶部、底部和后方的尖端。

float left = frame.pointables().leftmost().tipPosition().x;
    float right = frame.pointables().rightmost().tipPosition().x;
    float front = frame.pointables().frontmost().tipPosition().z;

    float back = backmost(frame.pointables()).tipPosition().z;
    float top = topmost(frame.pointables()).tipPosition().y;
    float bottom = bottommost(frame.pointables()).tipPosition().y;

    Leap::Pointable backmost(PointableList pointables)
    {
        if(pointables.count() == 0) return Leap::Pointable::invalid();
        Leap::Pointable backmost = pointables[0];
        for( int p = 1; p < pointables.count(); p++ )
        {
            if( pointables[p].tipPosition().z > backmost.tipPosition().z)
                backmost = pointables[p];
        }
        return backmost;
    }

    Leap::Pointable topmost(PointableList pointables)
    {
        if(pointables.count() == 0) return Leap::Pointable::invalid();
        Leap::Pointable topmost = pointables[0];
        for( int p = 1; p < pointables.count(); p++ )
        {
            if( pointables[p].tipPosition().y > topmost.tipPosition().y)
                topmost = pointables[p];
        }
        return topmost;
    }

    Leap::Pointable bottommost(PointableList pointables)
    {
        if(pointables.count() == 0) return Leap::Pointable::invalid();
        Leap::Pointable bottommost = pointables[0];
        for( int p = 1; p < pointables.count(); p++ )
        {
            if( pointables[p].tipPosition().y < bottommost.tipPosition().y )
                bottommost = pointables[p];
        }
        return bottommost;
    }

  [也就是简单计算下所有物体三维坐标的最小外接矩形,很容易理解~代码如出一辙,看懂一个后面都懂。看了下API,以及我自己猜测,left,front,right这几个方位,Leap Motion是比较关注的,而对于高Leap可能无法准确探测,但对于其它几个方向为什么不直接提供函数呢?]

手类描述了一个被Leap追踪到的物理形式的手。一个手对象提供了访问它自己尖端(手指)的列表,以及一个描述的手的坐标、朝向和运动的属性。从一帧中获取手对象:

Leap::Frame frame = controller.frame(); // controller is a Leap::Controller object
Leap::HandList hands = frame.hands();
Leap::Hand firstHand = hands[0];

或者,如果你从前一帧中已知ID:

Leap::Hand knownHand = frame.hand(handID);

你还可以通过它们在帧中相对位置获取手对象:

Leap::Frame frame = controller.frame(); // controller is a Leap::Controller object
Leap::HandList hands = frame.hands();

Leap::Hand leftmost = hands.leftmost();
Leap::Hand rightmost = hands.rightmost();
Leap::Hand frontmost = hands.frontmost();

注意,rightmost()和rightmost()函数仅仅区分哪只手是最右侧或者最左侧。这个方法不区分这只手是左手还是右手。

     获取手特征

一只手被通过它的坐标、朝向和运动得以描述。   手的坐标是通过手掌坐标属性得到的,提供了一个以Leap Motion为原点,毫米为单位的手掌中心三维坐标的向量。手的朝向由2个向量给出:方向---从手掌中心指向手指方向,手掌垂直面---指向手掌外侧,垂直于手的平面。   手的运动通过运动速度属性给出,它是一个描述手在毫米每秒瞬时运动的向量。你还可以获得运动因子,它可以描述一只手在两帧时的位移、旋转和缩放值的变化。 下面的代码块描述了如何在一帧中获取一个手对象和它的基本属性:

    Leap::Hand hand = frame.hands().rightmost();
    Leap::Vector position = hand.palmPosition();
    Leap::Vector velocity = hand.palmVelocity();
    Leap::Vector direction = hand.direction();

    获取指尖和工具

你可以通过列表或仅仅通过之前帧的ID两种方式,获取与手关联的手指和工具。 通过列表方法:

    // hand is a Leap::Hand object
    Leap::PointableList pointables = hand.pointables(); // Both fingers and tools
    Leap::FingerList fingers = hand.fingers();
    Leap::ToolList tools = hand.tools();

通过之前帧ID方法: Leap::Pointable knownPointable = hand.pointable(pointableID);   为了获取手指或者工具在Leap视野的相对位置,可以使用匹配列表类中right-,left-和frontmost函数。

    // hand is a Leap::Hand object
    Leap::Pointable leftPointable = hand.pointables().leftmost();
    Leap::Finger rightFinger = hand.fingers().rightmost();
    Leap::Tool frontTool = hand.tools().frontmost();

注意,这些函数都是相对于Leap Motion原点位置的,而不是手它自己的。为了获取相对于手的手指,你可以使用Leap矩阵类来讲手指坐标转换到参考帧的手。[不太懂]

     计算手的朝向

使用手的方向和垂直向量,你可以计算出手的朝向角度(相对于东方)。向量类定义了俯仰Pitch旋转(围绕x轴旋转)、左右Yaw旋转(围绕y轴的旋转)和平面Roll旋转(围绕z轴旋转):

    float pitch = hand.direction().pitch();
    float yaw = hand.direction().yaw();
    float roll = hand.palmNormal().roll();

注意,roll函数仅仅提供使用垂直向量时的预判的角度。[看来roll判断比较困难吧]

     将手指坐标变换到手的参照帧(以手为参照对象)

有时,通过手的参照帧获取在手上的手指坐标是常用的方法。这种方法可以让你对手指在空间上进行排序,并且可以简单的分析手指的坐标[很有用啊]。你可以使用Leap矩阵类构建一个转换矩阵来转换手指坐标和方向坐标。参照中的手帧可以通过手的朝向和手掌的垂直向量(由与两个坐标轴正交的第三个坐标轴)被有效的定义。这种方法使得x轴沿着手侧面,而z轴指向前方,y轴与手掌平面平行。

    Leap::Frame frame = leap.frame();
    for( int h = 0; h < frame.hands().count(); h++ )
    {
        Leap::Hand leapHand = frame.hands()[h];

        Leap::Vector handXBasis =  leapHand.palmNormal().cross(leapHand.direction()).normalized();
        Leap::Vector handYBasis = -leapHand.palmNormal();
        Leap::Vector handZBasis = -leapHand.direction();
        Leap::Vector handOrigin =  leapHand.palmPosition();
        Leap::Matrix handTransform = Leap::Matrix(handXBasis, handYBasis, handZBasis, handOrigin);
        handTransform = handTransform.rigidInverse();

        for( int f = 0; f < leapHand.fingers().count(); f++ )
        {
            Leap::Finger leapFinger = leapHand.fingers()[f];
            Leap::Vector transformedPosition = handTransform.transformPoint(leapFinger.tipPosition());
            Leap::Vector transformedDirection = handTransform.transformDirection(leapFinger.direction());
            // Do something with the transformed fingers
        }
    }

 

尖端

尖端对象可以被表示为手指和工具 ---- 也就是可以指出方向的东西。 你可以通过手对象中特定的手,获取与手关联的手指和工具。尖端未必要和手对象关联 --- 物理上的手也许不在视野中或者被另一只手挡住了。因此帧中尖端列表可以包含哪些和手不关联的手指和工具[即增加了适用性,同时也引入了复杂性呀]。   尖端对象有着许多描述手指和工具的属性: #尖端坐标 --- 在Leap Motion坐标系下以毫米为单位的瞬时的坐标。 #尖端速度 --- 以毫米每秒为单位的瞬时速度。 #指向 --- 当前的指向朝向向量。 #长度 --- 手指和工具显现的长度。 #宽度 --- 平均宽度。 #触摸距离 --- 在虚拟触摸平面中归一后的距离。 #触摸区域 --- 当前尖端和虚拟触摸平面的关系。   下面的例子说明如何从帧中获取简短对象和基本访问属性的方法:

    Leap::Pointable pointable = frame.pointables().frontmost();
    Leap::Vector direction = pointable.direction();
    float length = pointable.length();
    float width = pointable.width();
    Leap::Vector stabilizedPosition = pointable.stabilizedTipPosition();
    Leap::Vector position = pointable.tipPosition();
    Leap::Vector speed = pointable.tipVelocity();
    float touchDistance = pointable.touchDistance();
    Leap::Pointable::Zone zone = pointable.touchZone();

 

     将尖端对象转化成手指或者工具

为了将尖端对象转化到合适的手指和工具子类,需要使用合适的手指和工具构造函数(某些时候你应该使用Leap类的构造函数)[不太明白]。

 if (pointable.isTool()) {
        Leap::Tool tool = Leap::Tool(pointable);
    } else {
        Leap::Finger finger = Leap::Finger(pointable);
    }

 

     计算手指基本位置

如果你需要计算手指的基本位置,你可以如下使用手指尖位置和朝向:

    Leap::Vector basePosition = -pointable.direction() * pointable.length();
    basePosition += pointable.tipPosition();

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
### 回答1: Leap Motion是一种能够识别势的硬件设备,它可以通过高精度的摄像机和红外线传感器来捕捉手指掌的动作并将其转化为计算机可识别的指令。其中之一就是能够识别手指画圆。 Leap Motion可以识别手指画圆的方法是通过对手指的运动轨迹做出实时分析和判断。当手指Leap Motion摄像头扫描区域内运动时,它会捕捉到手指的位置和运动轨迹,并将其转化为数字信号。然后通过算法分析信号,检测出手指的运动是否符合画圆的规律,如果符合规律则解析成计算机可识别的指令。因此,只需手指Leap Motion摄像头的扫描区域内画圆旋转,即可完成指令的转化。 这种技术可以应用于各种场景,例如游戏、工程设计、医疗保健等。在游戏中,可以通过手指画圆来控制游戏内的角色和操作。在工程设计中,可以通过手指画圆来控制建模软件的视角和尺寸。在医疗保健领域中,可以通过手指画圆来控制术、治疗等过程,提高治疗效率。 总之,Leap Motion通过高精度的摄像机和红外线传感器可以无缝地实现手指画圆的识别,为各种领域的应用提供了更加便捷、高效的操作方式。 ### 回答2: Leap Motion是一款基于势识别技术的设备,可以捕捉部和手指的运动轨迹,并识别出势动作。Leap Motion可以通过手指画圈的动作,实现对应的操作功能。 在使用Leap Motion时,用户可以将部放置在设备上方约10厘米的位置,然后使用手指进行控制。当用户画圈时,Leap Motion会捕捉手指的运动轨迹,将其转化为数字化的数据,并通过内置的算法进行处理和分析。 根据用户势的不同,Leap Motion可以识别出手指画圈的动作,从而实现对应的操作。例如,用户可以通过手指画圈的方式,控制计算机屏幕上的光标移动或配合其他势实现更复杂的操作。 对于Leap Motion来说,识别手指画圈是一项比较简单的动作。因为手指画圈的动作相对固定,其运动轨迹和时间序列有一定的规律性,可以通过算法进行有效的识别和处理。 总之,Leap Motion可以通过识别手指画圈的动作,实现对应的控制功能,为用户提供更加便捷和自然的交互体验。 ### 回答3: Leap Motion是一种运动感知设备,能够通过感应用户的部动作实现交互操作。它可以精准地识别手指的运动,能够识别用户的手指画圈的动作。 Leap Motion势识别技术非常精准,它能够在几毫秒之内将用户部动作的细节传递给计算机,并通过算法分析用户的势,从而识别手指画圈的动作。通过该技术,用户可以通过势来控制计算机界面的操作,不需要使用物理设备。 手指画圈是一种常见的势,它在交互系统中被广泛使用。例如,当用户需要切换桌面的工作区域时,可以通过手指画圈来实现。在Leap Motion中,用户可以通过手指画圈的动作来控制应用程序、游戏和虚拟现实等领域的交互操作。 总之,Leap Motion能够识别手指画圈的动作,并将其转化为电脑界面上的具体操作,为交互操作带来了全新的体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值