• 透過 OpneNI 合併 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 目前簡單的測試看來,應該差異不大就是了,如果有需要的人,可以自己玩看看了~

    trackback: http://kheresy.wordpress.com/2011/01/21/combine_depth_and_image_from_kinect/

  • 相关阅读:
    vue+springboot+element+vue-resource实现文件上传
    使用bfg快速清理git历史大文件
    git clone异常 【fatal: protocol error: bad line length character: Inte】
    excel 一次删除所有空行
    vim编辑器
    prometheus安装
    递归计算分波那契数列和阶乘
    如何理解线程安全?
    创建线程的方式
    为什么说一个对象是线程安全的?
  • 原文地址:https://www.cnblogs.com/JohnShao/p/2046036.html
Copyright © 2020-2023  润新知