OpenNI 2 的資料錄製與重播


基本上,之前的文章裡,Heresy 已經大致把 OpenNI 2 的使用都講過了。而這一篇,則是來講一下,怎麼透過 OpenNI 2.x 的介面,來把資料錄製下來、之後再拿來使用。

基本上,OpenNI 的資料的錄製,主要是可以把原始的資料,例如深度影像、彩色影像,以 OpenNI 自己定義的檔案格式、ONI 的形式儲存下來,方便之後再使用。而使用的時候,主要是用來給 middleware library 用來分析,方便用來偵錯、開發程式,避免在開發階段要不停地走到感應器前、做出同樣的動作。

在錄製的部分,它的使用方法,大致是透過 OpenNI 2 提供的 Recorder 這個類別(官方文件),來做錄製的控制。它的使用方法,基本上如下:

  1. Recorder 在使用的時候,一樣也是先宣告出 Recorder 的物件後,再呼叫他的 create() 這個函式,來完成這個物件的建置;而在呼叫 create() 的時候,則需要把檔案名稱當作參數傳進去,如此一來,Recorder 就會把指定檔案建立出來,並把資料寫進去。

  2. 在建立完成 Recorder 的物件後,則是透過 attach() 這個函式,來指定要錄製的 VideoStream
    而除了指定 VideoStream 外,呼叫這個函式的時候,也可以決定這組資料,是否允許失真壓縮;如果允許失真壓縮的話,錄製出來的檔案大小會小很多,但是資料可能會失去一部分的準確度,所以是否要允許,就是看應用了。

  3. 接下來,就是透過 start()stop() 這兩個函式,來控制資料的錄製與否了~

  4. 最後,都結束後,呼叫 destory() 把自己摧毀掉。

下面就算是一段比較完整的範例:

  // Initial OpenNI
  OpenNI::initialize();
 
  // Open Device
  Device  devDevice;
  devDevice.open( ANY_DEVICE );
 
  // Create depth stream
  VideoStream vsDepth;
  vsDepth.create( devDevice, SENSOR_DEPTH );
 
  // create recorder
  Recorder recRecorder;
  recRecorder.create( "d:\\test.oni" );
  recRecorder.attach( vsDepth );
 
  // start
  vsDepth.start();
  recRecorder.start();
 
  // main loop
  //....

如此一來,程式就會把深度影像錄到 d:\test.oni 這個檔案裡了~


接下來,要怎麼使用錄製好的 ONI 檔案呢?基本上,OpenNI 2 的 Device 在透過 open() 這個函式來開啟裝置的時候,是需要透過給一個 URI 的字串,來決定要開啟哪個裝置的;而在一般的狀況下,是可以給定義好的 ANY_DEVICE,來讓 OpenNI 去找任何一個可以用來使用的實體裝置。

如果要開啟錄製好的 ONI 檔的話,也相當簡單,只要把 ANY_DEVICE 改成檔案名稱傳進 open() 就可以了~而之後,這個 Device 就可以和一般使用一樣進行操作了~下面就是一個簡單的例子:

Device  devDevice;
devDevice.open( "d:\\test.oni" );

而如果想讓 NiTE 2 去使用錄製下來的資料的話,也就只需要像《使用 OpenCV 畫出 NiTE2 的人體骨架》一文裡的範例一樣,在建立 UserTrackerHandTracker 的時候,去指定使用 ONI 檔案的 Device 就可以了~

不過可能要注意的是,在使用錄製下來的 ONI 檔的時候,有的功能是無法使用的。像是 VideoMode 的變更、Image Registration Mode 的設定,以及 CoordinateConverterconvertDepthToColor(),似乎都是無法使用的。

而除了單純地使用錄製好的 ONI 檔之外,OpenNI 2 也有提供一個 PlaybackControl 的類別(官方文件),可以再使用 ONI 檔時,進行一定程度的控制;包括了是否要重播、撥放速度、總共的畫面數、跳到特定的時間…

這個物件可以透過 DevicegetPlaybackControl() 這個函式來取得,並進行操作,基本上就是:

PlaybackControl* pController = devDevice.getPlaybackControl();

而他提供的介面裡,setRepeatEnabled() 就是用來控制是否要自動重播的,setSpeed() 則是給一個浮點數、來控制撥放的速度(1.0 是正常速度);這兩者基本上都是針對整個對應到 ONI 檔案的 Device 作用的。

另外,像是 getNumberOfFrames() 則是用來針對個別的 VideoStream,取得他的所有的畫面數(時間長度)。而 seek() 的話,則是用來針對指定的 VideoStream,要求他直接跳到特定的時間點(透過 frame index 來指定);不過要注意的是,雖然是針對單一 VideoStream 做控制,但是在呼叫之後,其他 VideoStream 也會議起跳到對應的時間位置去。


OpenNI / Kinect 相關文章目錄

對「OpenNI 2 的資料錄製與重播」的想法

  1. 请问,我用上面的方法保存了一段深度视频,然后用网上找的代码可以打开这段深度视频,并且按帧保存图片。但是我改写了上面的代码,保存了一段彩色视频,也改写了打开彩色视频的代码,但是似乎就会卡在 streamColor.readFrame(&frameColor); 这里,我不清楚是为什么

    然后您上面的main loop没给出具体代码,我就仿照您之前的博客里的读取彩色和深度影像中心点那段代码写的

      • 我似乎知道为什么了,我查看了videomode,发现kinect V2彩色视频的分辨率有两种:1920*1080和512*424。然后我把分辨率改为了512*424,使用相同的打开oni文件并保存图片的程序就可以了。
        所以我想知道为什么1920*1080就不可以?

        • 抱歉,個人沒這樣使用過,所以也不能確定問題是什麼。
          實務上,個人也沒打算用 OpenNI 去存取 Kinect v2 的資料,所以應該不會去測試這部分的問題。

          • 如果只用openni2获取彩色视频,我把分辨率改了512*424后,它显示的是原来1920*1080画面的一个边角部分,而不是把原来的影响整体缩小。请问有什么办法吗?

          • 前面已經說過了,個人沒打算用 OpenNI 去存取 Kinect v2 的資料,所以應該不會去測試這部分的東西。

      • 请问能给我一个你的联系方式嘛?邮箱、QQ、wechat之类的,我想请教一些问题。

  2. 請問在重播時要如何讓兩個oni檔可以同步呢?因為record的兩個oni檔(color & depth)在重播時後要用到兩個device去開啟,可是openni::Device::setDepthColorSyncEnabled()這個function好像是對單一的device去做synchronized,所以這方面有點困惑。又或者說是否有方法讓record兩個oni的total frame數相同呢??(color.oni的frame數會少於 depth.oni的frame數)

    • OpenNI 的設計的確只能針對單一感應器做同步,沒辦法針對兩個不同的裝置做處理。
      所以如果是要讓輛個裝置的畫面同時撥放的話,應該是得自己想辦法去控制他的更新了。

        • OpenNI 的介面似乎沒有辦法直接做到這件事。
          個人是建議,可能要試試看是否有辦法在撥放的時候,透過 PlaybackControl 來自己控制更新的形式了。

  3. 請問在錄製好的資料或者現場採集時,能否截取連續的幀,然後在對其進行convertDepthToWorld處理?因為進行convertDepthToWorld時需要用到const VideoStream &depthStream這個參數,如果不是採用當時截取這幀時的depthStream會有什麼問題嗎?怎麼解決?(之所以先截取連續幀,再進行處理是為了採集加快速度,獲取連續的實時幀,以便進行融合。之前我這樣做的時候,不曉得是不是因為depthStream不是實時的問題,輸出的點雲都是亂碼)

    • 可以,但是請使用 OpenNI 本身的功能來做操做。
      以本文的例子來說,在建立 ONI 的 device,以繼續建立出 depth 的 VideoStream,並以此來做操作。

      • 請問官方文件這句是什麼意思?"To use, simply create your file device, create a PlaybackControl, and then attach the PlaybackControl to the file device."
        和Heresy 提供的這段 PlaybackControl* pController = devDevice.getPlaybackControl(); 有關係嗎?謝謝

  4. 請問執行大大提供的範例時顯示
    “Please give a filename for recording"
    filename該怎麼設定?又設定於何處?

    • 我將if(argc!=2)
      mark掉才能順利執行並存取。
      請問有辦法將自定義的彩色與深度video轉成oni檔嗎?

      • 你要在執行程式的時候,透過額外的參數指定要錄的檔案。
        例如: a.exe test.oni

        另外,目前應該沒有現成的軟體可以達成你的目的。

發表留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料