透過 OpneNI 合併 Kinect 深度以及彩色影像資料


在前一篇的《透過 OpneNI 讀取 Kinect 深度影像資料》裡,已經解釋過如何在 PC 上透過 OpenNI 來讀取 Kinect 的深度圖了。而這一篇,則是進一步、同時讀取它的深度圖,以及一般的彩色影像、並將之做位置上的校正、合併。為了做到這個目的,除了上一篇有用到的 xn::DepthGenerator 外,這一篇還會用到 xn::ImageGenerator 來讀取 Kinect 的彩色影像資料;而另外為了修正兩個攝影機的視角不同,也會用到 xn::AlternativeViewPointCapability 這個特別的 Capability。

而由於這邊的程式碼是基於上一個程式所修改的,所以在重複的地方,Heresy 不打算重複說明了,請自行回去參考上一篇文章的部分。而接下來,就直接先看程式碼的內容:

#include <stdlib.h>
#include <iostream>
#include <string>
 
#include <XnCppWrapper.h>
  
using namespace std;
 
void CheckOpenNIError( XnStatus eResult, string sStatus )
{
  if( eResult != XN_STATUS_OK )
    cerr << sStatus << " Error : " << xnGetStatusString( eResult ) << endl;
}
 
int main( int argc, char** argv )
{
  XnStatus eResult = XN_STATUS_OK;
 
  // 2. initial context
  xn::Context mContext;
  eResult = mContext.Init();
  CheckOpenNIError( eResult, "initialize context" );
 
  // 3. create depth generator
  xn::DepthGenerator mDepthGenerator;
  eResult = mDepthGenerator.Create( mContext );
  CheckOpenNIError( eResult, "Create depth generator" );

  // 4. create image generator
  xn::ImageGenerator mImageGenerator;
  eResult = mImageGenerator.Create( mContext );
  CheckOpenNIError( eResult, "Create image generator" );

  // 5. set map mode
  XnMapOutputMode mapMode;
  mapMode.nXRes = 640;
  mapMode.nYRes = 480;
  mapMode.nFPS = 30;
  eResult = mDepthGenerator.SetMapOutputMode( mapMode );
  eResult = mImageGenerator.SetMapOutputMode( mapMode );
 
  // 6. correct view port
  mDepthGenerator.GetAlternativeViewPointCap().SetViewPoint( mImageGenerator );
 
  // 7. tart generate data
  eResult = mContext.StartGeneratingAll();
 
  // 8. read data
  eResult = mContext.WaitNoneUpdateAll();
  if( eResult == XN_STATUS_OK )
  {
    // 9a. get the depth map
    const XnDepthPixel*  pDepthMap = mDepthGenerator.GetDepthMap();
    // 9b. get the image map
    const XnUInt8*    pImageMap = mImageGenerator.GetImageMap();
  }
  
  // 10. stop
  mContext.StopGeneratingAll();
  mContext.Shutdown();
 
  return 0;
}
Image Generator

基本上,這邊的程式架構和之前單純讀取深度影像的範例是相同的。不同的地方在於,這邊除了建立用來讀取深度的 xn::DepthGenerator 這個 node、mDepthGenerator 外,也另外建立了一個用來讀取彩色影像用的 node,也就是形別是 xn::ImageGenerator 的物件 mImageGenerator。而它的使用方法基本上和 xn::DepthGenerator 是相同的,一樣是先宣告出他的物件後,再透過 Create() 這個成員函式來建立;程式寫法的部分,可以參考上方「4. create image generator」的部分。

而同樣的,在這邊 Heresy 也是把彩色影像的輸出模式,設定為 640 x480 @ 30FPS;而 xn::ImageGenerator 設定輸出模式的方法和 xn::DepthGenerator 一樣,也是呼叫 SetMapOutputMode() 做設定就可以了。(上方「5. set map mode」的部分。)

 

取得影像資料

相較於 xn::DepthGenerator 是透過 GetDepthMap() 這個函式來取得深度的影像,xn::ImageGenerator 則是透過 GetImageMap() 這個函式來取得彩色的影像資料。而在預設的情況下,這樣取得的影像資料會是一個型別是 XnUInt8(實際上就是 unsigned char)的 const 指標,指向一個一維陣列。而這個陣列的大小會是 640 x 480 x 3,每三個為一組、分別代表他的 RGB 的值。

另外,也可以透過 GetRGB24ImageMap() 這個函式,來取得 XnRGB24Pixel 這種封裝好的格式,不過實際使用上差異不大就是了。而如果有需要的話,image generator 也可以透過 SetPixelFormat(),來修改每一個像素的資料形式,不過在這邊就不細提。

 

視角修正

接下來比較特別的地方,則是「6. correct view port 」的部分。這邊程式的目的,是要修正兩個感應器取得的畫面座標,讓兩者畫面的視角一致。為什麼要做這件事呢?因為 Kinect 的深度攝影機和彩色攝影機是在不同的位置,而且鏡頭本身的參數也不完全相同,所以其實兩個攝影機所取得的畫面,是會有些微的差異的。下面就是在不修正的情況下,所抓到的畫面(左邊是彩色、右邊是深度):

 

直接看的話感覺好像差不多?不過仔細看的話,是可以發現兩張圖的可視範圍是不一樣的~彩色攝影機的可視範圍,基本上是比深度攝影機大一些的;而如果把兩張圖重疊在一起,看起來會更明顯。右邊的圖就是直接把兩張圖重疊在一起的結果,可以很明顯地看出來,有很多地方都沒有辦法對應得很好,像是天花板上的日光燈罩和機櫃上的東西,都很明顯地看的出來有出入。

為了解決這個問題,OpenNI 有提供一個名為「Alternative View」的 Capability,可以幫助使用 OpenNI 的程式開發者,快速地修正這種視角上的不同;不過這項功能,基本上是要有支援的 production node 才可以用的就是了。

Alternative View 這個 capability 的型別是 xn::AlternativeViewPointCapability,可以直接透過呼叫 Production Node 的「GetAlternativeViewPointCap()」來取得用來操作這項 capability 的物件;基本上 OpenNI 的所有 capability,都是以這樣的形式來使用的。而以 xn::AlternativeViewPointCapability 來說,他有提供 SetViewPoint() 這個函式,可以把其他的 production node 傳進去、把目前這個 node 的視角改為指定 node 的視角。

而 Heresy 這邊實際寫成程式碼,就是:

mDepthGenerator.GetAlternativeViewPointCap().SetViewPoint( mImageGenerator );

這樣寫的意思,就是把 mDepthGenerator 這個 depth generator 的視角、設定成和 mImageGenerator 一樣了。(註:反過來想讓 image generator 根據 depth generator 調整的話,OpenNI 會當掉…)

而加上這一行後, depth generator 所抓到的畫面,就會變成左下方這樣的圖。如果和之前沒有執行過視角調整的結果相比,可以發現調整過後的結果周圍的黑邊明顯地比較大,同時也有一些幾何上的修正(四邊有稍微內凹);而這樣取得的結果再和彩色影像重疊在一起(右下圖),則可以發現位置變得相當一致,不會有之前畫面內東西不一致的問題了!

 

所以如果有需要要將深度和彩色影像做整合的話,應該就要記得做視角修正的動作,以避免對應的位置出錯。

這一篇文章大概就先寫到這裡了。基本上,這邊主要應該算是在講 Alternative View 這個 capability 了~而實際上,如果有需要的話,可能也可以考慮使用 Frame-Sync 這個 capability,來讓深度影像與彩色影像之間的時間差更小;不過就 Heresy 目前簡單的測試看來,應該差異不大就是了,如果有需要的人,可以自己玩看看了~


OpenNI / Kinect 相關文章目錄

About these ads

關於 Heresy
http://kheresy.wordpress.com

70 Responses to 透過 OpneNI 合併 Kinect 深度以及彩色影像資料

  1. Tony 說道:

    Heresy 老師
    我現在照著你上面的作法後
    buliding
    就會出現
    0xC0000008: An invalid handle was specified
    如何解決?
    謝謝

    喜歡

    • Heresy 說道:

      可以先麻煩你確認一下你的環境嗎?
      OpenNI 官方的 NiViewer 等程式是否可以正確執行?

      喜歡

  2. titif 說道:

    Heresy 您好
    我用VS 2012 編譯您的程序 得到以下錯誤訊息 請問是怎麼回事
    謝謝

    2 IntelliSense : directive #error : Xiron Platform Abstraction Layer – Win32 – Microsoft Visual Studio versions above 2010 (10.0) are not supported!

    喜歡

    • Heresy 說道:

      錯誤訊息應該算寫得很清楚了?
      OpenNI 1.x 不支援 VisualStudio 2010 以後的版本(2012)

      喜歡

  3. 引用通告: OpenNI 2 VideoStream 與 Device 的設定與使用 « Heresy's Space

  4. windspeed80kmh 說道:

    我想問如何直接顯示深度和彩色影像重疊的效果, 就像你所提供的圖片?

    喜歡

    • Heresy 說道:

      OpenNI 本身沒有提供顯示/繪圖功能,你必須要使用其他函式庫。

      請參考:使用 Qt GraphicsView 顯示 OpenNI 影像資料

      http://kheresy.wordpress.com/2011/08/18/show_maps_of_openni_via_qt_graphicsview/

      喜歡

      • windspeed80kmh 說道:

        謝謝你的解答
        如果我用OpenCV, 可以顯示兩個影像重疊的效果嗎? 如果可以的話, 可以提供參考嗎?

        喜歡

        • Heresy 說道:

          可以,只是和 Qt 一樣,影像都要處理過

          http://kheresy.wordpress.com/2012/07/25/openni-and-opencv/

          喜歡

  5. 台北人 說道:

    請問一下heresy大
    我用的是kinect for windows
    使用 unstable 版的 OpenNI 1.5.4.0和 avin2 的 SensorKinect 0.93
    VS2010
    屬性也都設定了

    按F5出現很多無法開啟BDP
    找了一些方法改按ctrl+F5
    卻出現了這段
    c:\program files\openni\include\xncppwrapper.h(5): fatal error C1014: Include 檔太多 : 深度 = 1024

    請問是哪邊出了差錯?
    感激不禁 謝謝

    喜歡

  6. justin 說道:

    Hi Heresy,
    有個問題想請問一下
    就是現在好像買不到asus的xtion pro Live 只買的到xtion pro
    但是他缺少了rgb的鏡頭
    我想請問一下 缺少rgb的鏡頭是不是很多應用上會有問題?
    以您這個範例來說 他就無法得到imageMap 對嗎?
    如果只有depth map 可以偵測到如身體或是手的動作嗎?
    我要猶豫要不要先買pro 就好 因為pro live好像都買不到阿

    謝謝

    喜歡

    • Heresy 說道:

      如果只是要抓人體動作的話,Xtion Pro 的確就可以了~
      因為 OpenNI / NITE 的人體動作追蹤,基本上都只有用到深度感應器。

      喜歡

  7. SPEC 說道:

    請問一下…….
    depth image 經過視角修正後,整個視野大小很明顯的比color image來的小
    假設我在depth image 中擷取其pixel(x,y)所代表的深度值
    跟在color image中相同的pixel(x,y)所代表的深度值會一樣嗎?
    兩者之間的投影坐標系會不會因為深度影像做完視角修正後,而不一致?
    謝謝..

    喜歡

    • Heresy 說道:

      基本上,Color Image 裡面沒有深度值,所以你所說的「在color image中相同的pixel(x,y)所代表的深度值」是不存在的。

      而以 OpenNI 的設計,是要做完修正後,兩邊才會正確對應!
      如果沒有使用 Alternative View Capability 的話,就會有上述的彩色影像和深度影像位置不一致的問題。

      喜歡

      • SPEC 說道:

        恩….
        很謝謝你的回覆
        我懂了..

        喜歡

  8. SS 說道:

    請教Heresy一個很基本的問題
    照理來說執行程式應該會顯示IMAGE FRAME才對
    可是它什麼都沒做就結束程式了
    請問這樣是正常反應嗎…?

    喜歡

    • Heresy 說道:

      您好,
      如果有看原始碼的內容的話,應該可以發現:
      這個範例程式本來就是為了簡單化,所以只有針對 OpenNI 的部分做說明,所以沒有做任何圖形介面的部分!理所當然的看不到任何畫面。
      如果是想要有圖形顯示的範例,請參考:http://kheresy.wordpress.com/2011/08/18/show_maps_of_openni_via_qt_graphicsview/

      喜歡

  9. JU 說道:

    請問一下Heresy 大大
    此校正方法 是用什麼方法來讓 深度和彩色影像校正

    還有user generator 是用什麼演算法 來框出人
    此方法可以套用在彩色影像嗎

    喜歡

    • Heresy 說道:

      1. 基本上,這是根據裝置本身的性質進行校正的。
      像 Xtion Pro Live 和 Kinect 校正的結果,深度所佔的區域就不相同。

      2. 如果只是框出人的部分,應該是用動作偵測之類的演算法,再加上用深度差異做區隔;而人體骨架分析的部分,則更為複雜。
      以動作偵測的演算法來說,也有不少是用在彩色影像上的,但是結果的效果應該和用深度來做有相當的差異。

      喜歡

  10. Lucien 說道:

    請教一下Heresy 大大
    關於 const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap();
    您是用這樣方式去取得XnDepthPixel的數值,
    我有看過別人使用XnDepthPixel* pDepth = DepthMetaData.Data();來取得這個值,
    請問這兩種有什麼差別嗎?

    因為我看官方的文件,好像沒特別介紹,所以才到這邊來請教大大您了,
    能為我解惑一下嗎?謝謝。

    喜歡

    • Heresy 說道:

      基本上,OpenNI 在 Map Generator 上有提供好幾種可以用來讀取資料的方法,雖然用法不大一樣,但是得到的結果都是相同的。
      像你提的方法,就是先透過 GetMetaData() 取得 xn::DepthMetaData,並透過他取得資料的一種方法。

      喜歡

      • Lucien 說道:

        謝謝Heresy,感謝解惑。

        喜歡

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s

關注

Get every new post delivered to your Inbox.

Join 436 other followers

%d bloggers like this: