Leap Motion擷取幀資料Getting Frame Data

來源:互聯網
上載者:User

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

擷取幀資料Getting Frame Data

 Leap Motion的API為你的程式提供以一系列被稱為幀對象的快照的運動追蹤資料。追蹤資料的每一幀都包含度量位置和其它在快照中關於檢測到的實體的資訊。這篇文章詳細討論從Leap Motion控制器中捕獲幀物體(Frame objects)。

概述

從連結好的控制器擷取一幀包含追蹤資訊的對象。無論什麼時候,只要你的應用程式準備使用控制器(Controller)類中的frame()方法來操作,就可以擷取一個幀對象:

if( controller.isConnected()) //controller is a Controller object{Frame frame = controller.frame(); //The latest frameFrame previous = controller.frame(1); //The previous frame}

frame()方法輸入一個曆史(history)參數標示可以重新得到多少以前的幀。[應該就是緩衝空間大小吧]一般的,過去的60幀內容都儲存在這個曆史緩衝中。

通過輪詢擷取幀

通過對控制器物體的輪詢獲得幀對象的方式,是當你應用運行在自然幀率下最簡單以及往往最好的策略。當你裝置處理一幀資料時,你只需要調用一下控制器的frame()函數。

但你使用輪詢方法,有一定機率你會在同一行內(如果應用個幀率快於Leap的幀率)擷取同一幀的內容,又或者跳過一幀(當Leap幀率快於你應用的幀率)。在大部分情況下,丟失或者重複的幀對象都是不重要的。比如,如果你在螢幕前用手移動物體,物體的運動依舊是平滑的(假設你應用的總體幀率是足夠高的)。[不知道它表達的什麼意思,我覺得只要它資料是平滑變化的就好]

為了檢測你是否正在處理了一個已經處理過的幀對象了,將已儲存最後處理過幀的ID數值與當前幀進行比較:

int64_t lastFrameID = 0;void processFrame( Leap::Frame frame ){if( frame.id() == lastFrameID ) return;//...lastFrameID = frame.id();}

如果你的應用丟失了一些幀,你可以使用frame()函數裡的曆史參數來訪問丟失的幀(只要這個幀對象還在曆史緩衝中):

int64_t lastProcessedFrameID = 0;void nextFrame( Leap::Controller controller ){int64_t currentID = controller.frame().id();for( int history = 0; history < currentID - lastProcessedFrameID; history++){processFrame( controller.frame(history) );}lastProcessedFrameID = currentID;}void processNextFrame( Leap::Frame frame ){if( frame.isValid() ){//...}}
通過回呼函數擷取幀

同樣的,你還可以使用一個監聽(Listener)對象來擷取Leap Motion控制器的幀對象。只要一個新的幀到來,這個控制器對象就會調用監聽者的onFrame()函數。在onFrame處理中,你可以調用控制器(Controller)的frame()函數來擷取他自己的幀(Frame)對象。

 

使用監聽者回呼函數比較複雜,因為回調是多線程的。每個回調都來自一個獨立的線程。你必須保證來自多線程中的資料都是以安全執行緒方式擷取的。

接下來的例子定義了一個最小的監聽子類,它可以擷取新的資料幀:

class FrameListener : Leap::Listener{void onFrame(Controller &controller){Frame frame = controller.frame(); //The latest frameFrame previous = controller.frame(1); //The previous frame//...}};

正如你所見,通過一個監聽對象擷取追蹤資料和輪詢模式幾乎一樣。

注意,跳過一幀是很必要的,即使當我們使用監聽回呼函數。如果你的onFrame回呼函數用了過多的時間才執行完畢,那麼下一幀被被添加到記錄中,但是onFrame回呼函數跳過去了。不太相同的,如果一個Leap軟體不能及時處理一幀資料,那個幀會被拋棄,並且不會被加入到曆史中。當電腦由於需要運行太多任務導致停滯,就會導致這個問題。

從幀中擷取資料

幀類定義了一些如何訪問幀中資料的函數。例如,下面的代碼描述了如何擷取Leap Motion系統追蹤到的基本對象。

Leap::Controller controller = Leap::Controller();// wait until Controller.isConnected() evaluates to true//...Leap::Frame frame = controller.frame();Leap::HandList hands = frame.hands();Leap::PointableList pointables = frame.pointables();Leap::FingerList fingers = frame.fingers();Leap::ToolList tools = frame.tools();

 

這個從幀對象中返回的對象都是唯讀。你可以安全的儲存它們並在未來使用它們。它們是安全執行緒的。內部的,這些對象使用C++ Boost程式庫共用指標類。

使用IDs來追蹤幀間實體

如果你擷取到了一個來自不同幀下實體的ID,你可以擷取對象在當前幀的描述資訊。將ID傳遞給合適類型的幀函數:

Hand hand = frame.hand(handID);Pointable pointable = frame.pointable(pointableID);Finger finger = frame.finger(fingerID);Tool tool = frame.tool(toolID);

如果具有相同ID的對象無法被找到----也許一隻手或者手指移出了Leap的視野。----那麼,取而代之,會返回一個特別的無效對象。無效對象也是類的執行個體,但是他們所有的成員都返回0數值、0數組或者其他的無效對象。這個技術使得將方法串連在一起調用更方便。例如,下列的代碼計算多幀下指尖的平均位置。

int count = 0;Leap::Vector average = Leap::Vector();Leap::Finger fingerToAverage = frame.fingers()[0];for( int i = 0; i < 10; i++ ){Leap::Finger fingerFromFrame = controller.frame(i).finger(fingerToAverage.id());if( fingerFromFrame.isValid() ){average += fingerFromFrame.tipPosition();count++;}}average /= count;

如果沒有無效的對象,那麼這段代碼需要每次在返回手指對象時檢測這個幀對象。

 

更多相關內容,請訪問http://52coding.com/category/leap-motion

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.