手是 LeapMotion 控制器追踪的主要实体。控制器维护了一个人手和数据验证内建模型,控制器的传感器也依赖此模型。则允许控制器能追踪手指的位置,甚至当一个手指处于完全不可见状态。请注意,当一个手指不可见或者在手的背后时,移动或者改变位置是有可能失去目标。LeapMotion 软件匹配了内部模型和现有的数据。在某些情况下,软件会出现错误匹配的情况 - 比如讲一个右手识别为一个左手。

Hand 类表示了一个 Leap 检测到的物理手。一个 Hand 对象提供访问了它的可形象列表,以及描述手的位置、方向和运动属性。

Hand 可以识别分别识别左手和右手。此外,每个手都会在被检测到后分配一个 ID 值。如果你从 LeapMotion 视野中移除在重新插入一个手时会重新分配一个 ID(可以使用 timeVisible 属性来设置一个手是否被重新检测)。如果 LeapMotion 软件认为它误判了一只手的类型并要做改变时,还是会重新非配一个新的手 ID。

获取手

从一个 Frame 中获取 Hand 对象:

  1. frame = controller.frame() # controller is a Leap.Controller object
  2. hands = frame.hands
  3. first_hand = hands[0]

如果你知道手的 ID 也可以:

  1. know_hand = frame.hand(hand_ID)

你还可以利用帧中的相对位置获取手:

  1. frame = controller.frame() # 控制器是一个 Leap.Controller 对象
  2. hands = frame.hands
  3. leftmost = hands.leftmost
  4. rightmost = hands.rightmost
  5. frontmost = hands.frontmost

注意,leftmost()rightmost()函数只能识别哪只手是最远的。使用 isLeft或者isRight属性来判断一只手是左手还是右手。

获取手的特征

一只手描述了它自身的类型、位置、方向、姿势以及动作:

  • isRightisLeft ——一只手是左手还是右手。
  • Palm Position——从 LeapMotion 原点以毫米为单位的手掌的中心点。
  • Palm Velocity ——以毫米为单位的手掌的移动速度和方向。
  • Palm Normal ——垂直于手掌平面的向量,向量从手掌向外。
  • Direction ——从掌心指向手指的向量。
  • grabStrength, pinchStrength ——描述了手的姿势
  • Motion factors ——提供了两帧之间的相关缩放、旋转、平移的因子。

手的位置通过其手掌的位置属性给出,提供包含以毫米为单位的 LeapMotion 原点的三维坐标。手的方向通过两种向量给出:从掌心指向手指的方向向量,以及垂直于手掌平面向外的法向量。

手的移动给出了速度的属性,一个向量提供了以 mm/s 为单位的手的瞬间移动。你也可以获取一直手在两帧之间的平移、旋转、缩放的运动因子的值。

下面的代码段展示了如何从一个帧中获取手的基本属性:

  1. hand = frame.hands.rightmost
  2. position = hand.palm_position
  3. velocity = hand.palm_velocity
  4. direction = hand.direction

获取手指

你可以获取与手关联的手指作为一个列表,或单独的使用在前一帧中获取的 ID。

通过列表:

  1. # hand 是一个 Leap.Hand 对象
  2. pointables = hand.pointables
  3. fingers = hand.fingers

通过前一帧中的 ID:

  1. known_pointable = hand.pointable(pointable_ID)

若需获取 Leap 视野内的手指相对位置,请使用匹配列表类的 rightmost, leftmost 和 fontmost 函数:

  1. # hand 是一个 Leap.Hand 对象
  2. left_pointable = hand.pointables.leftmost
  3. right_finger = hand.fingers.rightmost
  4. front_finger = hand.fingers.frontmost

请注意,这些函数都是相对 LeapMotion 原点而不是手本身的。为获得手相关的手指,你可以使用 Leap Matrix 类来平移手指位置到参考系手所在帧中。

计算手的方向

你可以使用Hand的方向和法向量计算手的方向角。

法向量从手掌垂直引出;方向向量则指向前方

Vector定义pitch, yaw, roll 三个角度,他们分别是绕 x, y, z 三轴所成夹角。

  1. pitch = hand.direction.pitch
  2. yaw = hand.direction.yaw
  3. roll = hand.palm_normal.roll

注意, roll 仅在同时使用法向量时才提供预期的角度。

将手指坐标平移到手的参考帧

有时候获取手所在帧参考系中手指的坐标很有用。则使你可以对手进行空间排序,还能够简化分析手的位置。你可以创建一个平移矩阵通过使用 Leap Matrix 类来平移手指位置和方向坐标。手的参考帧可以有效的定义手的 basis 以及 palm_position。basis 将 x 轴设置为手的侧向,z 轴则指向前方,而 y 轴则平行于手掌的法向量。palm_position 为平移原点。

  1. frame = controller.frame()
  2. for hand in frame.hands:
  3. hand_x_basis = hand.basis.x_basis
  4. hand_y_basis = hand.basis.y_basis
  5. hand_z_basis = hand.basis.z_basis
  6. hand_origin = hand.palm_position
  7. hand_transform = Leap.Matrix(hand_x_basis, hand_y_basis, hand_z_basis, hand_origin)
  8. hand_transform = hand_transform.rigid_inverse()
  9. for finger in hand.fingers:
  10. transformed_position = hand_transform.transform_point(finger.tip_position)
  11. transformed_direction = hand_transform.transform_direction(finger.direction)
  12. # Do something with the transformed fingers

手序列

HandList 类的行为如同一个向量形式的数组且支持迭代器。你不能够从 LeapMotion API 来删除或修改手列表的成员对象,但你可以组合相同对象类型作为一个新的列表。

迭代器的使用方法:

  1. for hand in handList:
  2. print hand

HandList 类定义了一个附加的函数从 Leap 坐标系统中的相对位置来获取列表成员。这些函数包括 leftmost(), rightmost() 和 frontmost()。下面的代码段展示了如何获取一个最右边的一个手对象:

  1. furthest_right = frame.hands.rightmost