【翻译】Leapmotion-python开发官方文档(3)

翻译 2016年02月20日 11:45:47
(由于本人英语水平有限,翻译有失误之处还望指出)

数据帧(Frames)

    LeapMotion API 将运动追踪的数据作为一系列数据帧(frames)传输到你的程序中。每帧数据都包括位置信息以及LeapMotion捕捉到的其他实体的信息。这篇文章主要探讨从LeapMotion控制器获得的Frame对象的一些具体问题。

概览

    每一Frame对象均包含由LeapMotion记录的现场的实时快照(snapshot)。手、手指、工具是LeapMotion系统追踪到的最基本的物理实体。
    从已连接的Controller对象中获得一个包含追踪信息的Frame对象。你能在你的程序准备好处理数据的时候,用Controller中的frame()方法获得一个数据帧。
if(controller.is_connected): #controller is a Leap.Controller object
    frame = controller.frame() #The latest frame
    previous = controller.frame(1) #The previous frame

   frame()方法有一个history形参,用于指出回溯多少个数据帧(即找出历史数据)。在历史缓冲区中存放着最新的六十个数据帧。(不要依赖这个数值的精确性,在未来这个值可能会发生改变。)
   注意:通常连续的数据帧会有连续的ID值。但是,在某些情况下,数据帧的ID值会有跳跃。在资源有限的电脑上,LeapMotion软件可能会发生丢帧现象。另外,当LeapMotion启动强健模式来补偿红外亮度,那么Frame对象会以二增长。(每个Frame对象需要两个摄像头捕捉的帧生成)。最后,如果你使用Listener对象的回调函数获取数据帧,回调函数直到第一次调用产生返回的时候才会调用第二次。这样,如果你的回调函数需要花很长的时间处理数据,也会发生丢帧的现象。不过在这种情况下,丢失的数据帧会保存在历史缓冲区。

从数据帧获取数据 (Getting Data from a Frame)

    Frame类定义了一些提供访问数据帧中数据的函数。比如,下面的代码就展示了如何获得由LeapMotion系统追踪到的基本对象
controller = Leap.Controller()
# wait until Controller.isConnected() evaluates to true
#...

frame = controller.frame()
hands = frame.hands
pointables = frame.pointables
fingers = frame.fingers
tools = frame.tools
    由Frame对象返回的对象均是只读的。你可以安全的保存他们然后在讲来使用他们。他们都是线程安全的。这些对象的内部实现都使用了C++ Boost 中的shared_ptr模板类。

以轮询的方式获取帧(Getting Frames by Polling)

    当你的程序本身就有帧率的时候(natural frame rate)采用轮询Controller对象获取数据帧是最简单也是最佳的方式。你只需要在你的程序准备好处理一帧数据时调用Controller对象的frame()函数。
    当你使用轮询的方式时,会有可能同样的数据帧被获取了两次。(当你程序的帧率比LeapMotion的帧率快的时候),或者跳过某些帧(当LeapMotion的帧率比你程序的帧率快时)。在许多情况下,丢失和重复数据帧不是很重要。比如,如果你使用屏幕上一个对象作为对手运动的响应。整个过程仍然是很流畅的(假设你程序的所有帧率都足够高)。在这些情况下丢帧和帧重复不是什么要紧的事,你可以使用frame()函数的history形参找回丢失的帧。
    为了判断是否处理过一个数据帧,保存上一已经处理过的数据帧的ID值然后与当前帧进行比较。
    
lastFrameID = 0;
def processFrame(self, frame):
    if(frame.id == self.lastFrameID):
        return
    #...
    self.lastFrameID = frame.id
    如果你的程序已经跳过了某些帧,使用frame()函数的history参数访问那些被跳过的数据帧(要保证不会超过历史缓冲区的长度)
  
lastProcessedFrameID = 0
def nextFrame(self, controller):
    currentID = controller.frame().id;
    for history in range(0, currentID - self.lastProcessedFrameID):
        self.processFrame(controller.frame(history))
        self.lastProcessedFrameID = currentID;

def processNextFrame(self, frame ):
    if(frame.is_valid):
        #...process

使用回调函数获取数据帧(Getting Frames with Callbacks)

    同样的,你也可以使用一个Listener对象在LeapMotion控制器的帧率下获取帧。Controller 对象在新的数据帧准备好时候调用Listener的 on_frame()函数。在on_frame()内部,你可以调用Controller.function()来获得Frame对象。
    使用回调函数会更复杂一些,因为这些回调函数都是多线程的。每一个回调都会启动一个独立的线程。你必须保证参与多线程的程序数据都是线程安全的。即使你从API获得的追踪数据是线程安全的,其他由你程序产生的数据则不一定是线程安全的。一个普遍的问题是,由GUI层组建拥有的对象只能由特定的线程进行修改。在这种情况下,你必须在相应的线程中修改那些非线程安全的部分,而不是在回调函数的线程中。
    下面的例子定义了一个小型Listener的子类用于处理新的数据帧:
class FrameListener(Leap.Listener):

    def onFrame(self, controller):
        frame = controller.frame() #The latest frame
        previous = controller.frame(1) #The previous frame
        #...

    正如你所见,使用Listener获得追踪数据和采用轮询的方式获取数据是一样的。

    注意,在使用Listener的回调函数时仍然有可能发生跳帧现象。如果你的on_frame回调函数花费时间太长,那么接下来的一帧就会放入历史缓冲区但是跳过回调函数读取的过程。少数情况下如果LeapMotion软件无法及时的处理完一个数据帧,这个数据帧就会被丢弃也不会放入到历史缓冲区。当电脑处于过多的计算任务时,这个问题就可能发生。

从数据帧中获取实体(Following entities across frames)

    如果你从另外一个数据帧中得到了一个实体的ID,你可以利用ID在当前帧中获得代表这个实体的对象。通过将ID值传入Frame的适当函数。

<span style="font-weight: normal;">hand = frame.hand(handID)
pointable = frame.pointable(pointableID)
finger = frame.finger(fingerID)
</span><p><span style="font-weight: normal;">tool = frame.tool(toolID)</span></p>

    如果同样的ID无法找到,有可能是这个手移出了LeapMotion的可视范围。然后返回一个特殊的,无效的对象。无效对象是相应的类的实例,但是所有成员都返回0值,0向量,或其他无效对象。这种技术方便了一起调用的连锁方法。比如,下面的代码段用来在一系列数据帧中求出平均的指尖位置。

#Average a finger position for the last 10 frames
count = 0
average = Leap.Vector()
finger_to_average = frame.fingers[0]
for i in range(0,9):
    finger_from_frame = controller.frame(i).finger(finger_to_average.id)
    if(finger_from_frame.is_valid):
        average = average + finger_from_frame.tip_position
        count += 1
average = average/count

    没有无效对象,这代码就必须在检查返回的Finger对象前检查每个Frame对象。无效对象减少了当获取LeapMotion的追踪数据时你不得不去做的大量无效检查(null checking)

序列化(Serialization)

    Frame对象提供serialize和deserialize()函数使你能够存储从数据帧中获得的数据和将其重构成有效的Frame对象。

【翻译】Leapmotion-python开发官方文档(9)

坐标系统 在使用LeapMotion控制器控制一个程序时一个基本的工作就是将从控制器获得的坐标值转换到程序的坐标系统。 LeapMotion坐标系统 LeapMotion控制器在每一个数据帧中提供的坐...
  • qq_27582707
  • qq_27582707
  • 2016年03月15日 14:51
  • 549

【翻译】Leapmotion-python开发官方文档(8)

运动 LeapMotion软件分析所有在先前数据帧发生过的运动,基本运动类型有:平移,旋转,缩放。比如,如果你把你两只手移向LeapMotion视野中的左边,那么得到的数据帧中就会包含平移。如果你扭...
  • qq_27582707
  • qq_27582707
  • 2016年03月11日 09:53
  • 448

【翻译】Leapmotion-python开发官方文档(5)

手指 手指和工具——有尖头的东西——由Pointable对象描述。此外,从Pointable类转换到Finger和Tool类,能提供更多特定的信息。 获得Pointable对象 你能个从Hand...
  • qq_27582707
  • qq_27582707
  • 2016年02月25日 19:45
  • 706

【翻译】Leapmotion-python开发官方文档(7)

触摸仿真 LeapMotion的通用接口提供了一些功能使你能够在你的应用中实现触摸仿真。触摸仿真相关功能可以在Pointable类中找到。 概览 LeapMotion定义了一个自适应触摸面使你能...
  • qq_27582707
  • qq_27582707
  • 2016年03月09日 15:12
  • 834

【翻译】Leapmotion-python开发官方文档(1)

连接控制器(Connecting to the Controller) (本人第一次写技术类博客,如有什么地方不妥请轻喷)       英文链接地址:https://developer.leapmot...
  • qq_27582707
  • qq_27582707
  • 2016年02月17日 18:41
  • 1186

【翻译】Leapmotion-python开发官方文档(4)

Hands 手是LeapMotion控制器所追踪的最基本的实体。控制器内部保持着一个手部模型,以此来验证从其传感器收集到的数据。这就能够使得即使一个手指没有完全可见,控制器仍能追踪到其位置。注意,当...
  • qq_27582707
  • qq_27582707
  • 2016年02月24日 15:01
  • 807

【翻译】Leapmotion-python开发官方文档(6)

手势 LeapMotion软件将一些特定的能够表明使用者的命令或要求的运动模式认定为手势。LeapMotion软件将帧中的手势反馈与其反馈其他的跟踪数据如手指和手是一样的。对于每一个追踪到的手势,Le...
  • qq_27582707
  • qq_27582707
  • 2016年03月08日 09:22
  • 516

【翻译】Leapmotion-python开发官方文档(2)

(介于本人翻译能力有限,如有错误,望指出) 跟踪模式(tracking model) LeapMotion API 定义了一个类来表示各种基本的被跟踪对象。 Frame     F...
  • qq_27582707
  • qq_27582707
  • 2016年02月18日 15:47
  • 487

【翻译】Leapmotion-python开发官方文档(10)

相机图像 LeapMotion控制器采用双目红外相机作为跟踪传感器。你可以使用Controller.images或者Frame.images来访问由相机采集到的图像。这些函数提供ImageList对象...
  • qq_27582707
  • qq_27582707
  • 2016年03月22日 14:01
  • 696

Spring官方文档翻译(1~6章)

Spring官方文档翻译
  • tangtong1
  • tangtong1
  • 2016年05月05日 22:26
  • 25988
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【翻译】Leapmotion-python开发官方文档(3)
举报原因:
原因补充:

(最多只允许输入30个字)