Kinect for Windows SDK開發入門(十九):Kinect Fusion


轉自:http://www.cnblogs.com/yangecnu/p/3428647.html

Kinect for Windows SDK1.7中引入了Kinect Fusion功能。在1.8的SDK中對該功能進行了改進和強化,Kinect Fusion能夠使得我們使用Kinect for Windows 傳感器來進行真實場景的三維幾何重建,目前已支持導出.obj及.stl等三維數據格式。Kinect Fusion技術在支持GPU加速的機器上能夠對物體進行實時的三維建模。和傳統的三維建模方式相比,Kinect Fusion最大的優勢是快速便捷。

    Kinect Fusion可以用於工業設計,3D打印,遊戲製作,醫療教育等領域。

    下圖是Kinect Fusion的工作流程。Kinect傳感器獲取的深度影像數據在剛開始的時候有很多數據丟失,通過移動Kinect傳感器對物體進行掃描,幾秒鐘過後就能夠創建足夠平滑的重建的靜態場景,產生點陣雲以及3D表面模型。

Figure 1

一 硬件要求

    Kinect Fusion對計算機的硬件條件要求較高,Kinect Fusion能夠使用C++ AMP技術在DirectX11兼容的GPU上處理數據,也可以在CPU上處理數據,可以在重建立方體構建的時候,通過設置重建的類型來確定。CPU處理模式適合離線處理,只有最新的兼容DirectX 11的GPU才支持實時、交互性的重建。

    基於GPU的重建的最低配置要求系統支持DirectX 11的顯卡,如果達不到要求,Kinect Fusion就運行不起來。目前NVIDIA GeForce GTX560,AMD Radeon 6950,同類型或者比該類型顯卡配置更高的硬件能夠實現實時交互三維重建。

    官方推薦配置是,臺式機CPU主頻3GH或以上,多核處理器,擁有2G內存的獨立顯卡。當然也可以使用配置有支持DirectX11 技術的顯卡的筆記本, 但是運行速度比同類型的臺式機會慢的多。通常支持每秒處理30幀圖像就可以實現非常流暢的追蹤和建模。

二 Kinect Fusion的工作原理

    Kinect Fusion通過對從多個角度獲取到的深度影像數據進行融合,來重建物體的單幀光滑表面模型。當傳感器移動的時候,照相機的位置以及姿勢信息被記錄下來,這些信息包括位置和朝向。由於我們知道了每一幀圖像的姿勢以及幀與幀之間的關聯,多幀從不同角度採集的數據能夠融合成單幀重建好的定點立方體。我們可以想象下在空間中的一個巨大的虛擬立方體,裏面是我們現實世界的場景,當我們移動傳感器的時候,深度數據信息被不斷加入。

    下圖是從Kinect Fusion的處理流程。

Figure 2 Kinect fusion Pipeline

  • 第一步是深度影像數據的轉換。SDK將Kinect中獲取的原始深度幀數據轉換爲以米爲單位的浮點數據,緊接着對該數據進行優化,通過獲取攝像頭的座標信息,將這些浮點數據轉換爲和Kinect攝像頭朝向一致的點雲數據。這些點的表面情況通過使用AlignPointClouds函數獲取。
  • 第二步是計算全局的攝像頭的姿勢信息,包括攝像頭的位置和朝向,通過使用交互型的配准算法在攝像頭移動時不斷獲取其姿勢,這樣系統始終知道當前攝像頭相對於起始幀時攝像頭的相對姿勢。Kinect Fusion中有兩種配准算法。第一種叫NuiFusionAlignPointClouds,他用來將從重建對象計算得來的點雲與從Kinect深度影像數據中獲取的點雲進行配準。或者單獨的使用比如對同一場景的不同視場角的數據進行配準;第二種叫AlignDepthToReconstruction,該算法在對重建立方體進行處理時能夠獲得更高精度的追蹤結果。但是對於場景內移動的物體該算法可能不夠健壯。如果場景中的追蹤被中斷,那麼需要將攝像頭的位置和上一次的攝像頭位置對齊才能繼續進行追蹤。
  • 第三步是將從已知姿勢攝像頭產生的深度影像數據融合爲代表攝像頭視野範圍內的景物的立方體。這種對深度數據的融合是逐幀,連續進行的,同時通過平滑算法進行了去噪,也處理了某些場景內的動態變化,比如場景內添加或者移除了小的物體等。隨着傳感器的移動從不同的視場角度觀察物體表面。原始影像中沒有表現出來的任何隔斷或者空也會被填充,隨着攝像頭更接近物體,通過使用新的更高精度的數據,物體表面會被持續優化
  • 最後,從傳感器視點位置對重建立方體進行光線投射,重建的點陣雲能夠產生渲染了的三維重建立方體。

    Kinect Fusion對物體的追蹤僅僅使用Kinect 傳感器產生的深度數據流。這種追蹤主要依賴深度影像數據中不同位置深度數據有足夠的深度差異。因此它能夠將看到的數據融合起來以及計算傳感器的不同位置差異。如果將Kinect對準一個平整的牆面或者又很少起伏變化的物體,那麼追蹤可能不會成功。場景中物體分散時效果最好,所以在使用Kinect Fusion對場景進行追蹤時如果出現追蹤失敗的情況,不防試着對場景內的物體進行追蹤。

    Kinect Fusion中的追蹤有兩種算法,他們分別通過AlignDepthFloatToReconstruction和 AlignPointClouds 函數實現,他們都可以用於攝像頭位置的追蹤,但是,如果我們使用AlignDepthFloatToReconstruction 函數來創建一個重建立方體,可能會有更好的追蹤精度。相比,AlignPointClouds 方法可以用於單獨的,不需要重建立方體就可以將兩個點雲進行對齊。

三 相關API

    前面講解了Kinect Fusion的工作原理,通過SDK中的相關API,我們可以使用Kinect Fusion來對真是場景進行三維重建,下圖是Kinect Fusion相關的處理流程:

KF modeling pipeline

    首先,需要進行初始化,在初始化階段,Kinect Fusion會確定建模過程中的世界座標系,並會構造一個帶掃描的真實場景的靜態的虛擬的立方體,在建模過程中,我們只關心在該虛擬立方體中的真實場景。

    緊接着第一步是對每一幀深度影像數據進行如上圖所示的處理。下面就簡單介紹下上圖中涉及Kinect Fusion的相關函數。

DepthToDepthFloatFrame 函數

    該函數的簽名如下:

public void DepthToDepthFloatFrame(DepthImagePixel[] depthImageData, FusionFloatImageFrame depthFloatFrame,float minDepthClip, float maxDepthClip, bool mirrorDepth)

    該方法將無符號短型深度影像數據幀格式轉換爲浮點型深度影像數據楨格式,它代表物體距離Kinect傳感器的距離,處理好的數據存儲在預分配的depthFloatFrame中,參數中depthImageData 和 depthFloatFrame 的大小必須一致,該函數在GPU上運行。

    depthImageData 是從Kinect傳感器獲取的深度影像原始數據。minDepthClip 表示最小深度閾值,小於該值得都會設置爲0,maxDepthClip 爲最大深度閾值,大於該值得都被設置爲1000,最後一個布爾型的mirrorDepth表示是否對深度數據進行鏡像處理。

    最小最大深度閾值可以用來對輸入的數據進行處理,比如說可以排除某些特殊的物體,將這些物體排除在三維重建之外。

ProcessFrame 函數

    接下來可以調用ProcessFrame函數,該函數在內部其實是先後調用了AlignDepthFloatToReconstruction 和 IntegrateFrame 這兩個函數,這裏先介紹ProcessFrame函數。

public bool ProcessFrame(FusionFloatImageFrame depthFloatFrame, int maxAlignIterationCount, int maxIntegrationWeight,Matrix4 worldToCameraTransform)

    該函數用來對每一幀經過DepthToDepthFloatFrame處理後的深度影像數據進行進一步處理。如果在AlignDepthFloatToReconstruction階段追蹤產生錯誤,那麼接下來的IntegrateFrame階段就不會進行處理,相機的姿勢也保持不變。該函數支持的最大圖像分辨率爲640*480。

    maxAlignIterationCount參數爲配準過程中的迭代次數,該參數用來表示對齊相機追蹤算法的迭代次數,最小值爲1,值越小的計算速度更快,但是設置過小會導致配準過程不收斂,從而得不到正確的轉換。

    maxIntegrationWeight 參數用來控制深度影像融合的平滑參數,值過小會使得的圖像具有更多的噪點,但是物體的移動顯示的更快,消失的也更快,因此比較適合動態場景建模。大的值使得物體融合的更慢,但是會保有更多的細節,噪點更少。

    WorldToCameralTransoform,參數爲最新的相機位置。

    如果該方法返回true,則表示處理成功,如果返回false,則表示算法在對深度影像數據對齊的時候遇到問題,不能夠計算出正確的變換。

    我們一般的可以分別調用AlignDepthFloatToReconstruction 和 IntegrateFrame 這兩個函數,從而可以對更多的細節進行控制,但是,ProcessFrame速度可能更快,該方法處理成功之後,如果需要輸出重構圖像,則只需要調用CalculatePointCloud方法,然後調用FusionDepthProcessor.ShadePointCloud即可。

AlignDepthFloatToReconstruction 函數

public bool AlignDepthFloatToReconstruction(FusionFloatImageFrame depthFloatFrame,int maxAlignIterationCount,FusionFloatImageFrame deltaFromReferenceFrame, out float alignmentEnergy, Matrix4 worldToCameraTransform)

    該方法用來將深度影像數據楨匹配到重構立方體空間,並由此計算出當前深度數據幀的攝像頭的空間相對位置。相機追蹤算法需要重構立方體,如果追蹤成功,會更新相機的內部位置。該方法支持的最大分辨率爲 640*480。

    maxAlignIterationCount 參數和ProcessFrame方法中的參數含義相同。

    deltaFromReferenceFrame 表示配準誤差數據楨, 是一個預先分配的浮點影像幀,通常存儲每一個觀測到的像素與之前的參考影像幀的對齊程度。通常可以用來產生彩色渲染或者用來作爲其他視覺處理算法的參數,比如對象分割算法的參數。這些殘差值被歸一化到-1 ~1 的範圍內,代表每一個像素的配準誤差程度。如果合法的深度值存在,但是沒有重構立方體,那麼該值就爲0 表示完美的對齊到重構立方體上了。如果深度值不合法,就爲返回1。如果不需要這個返回信息,直接傳入null即可。

    alignmentEnergy 表示配準精確程度 ,0表示完美匹配

    worldToCameraTransform 表示此刻計算得到的相機位置,通常該變量通過調用FusionDepthProcessor.AlignPointClouds 或者 AlignDepthFloatToReconstruction這兩個方法獲得。

    該函數如果返回true則表示對齊成功,返回false表示則表示算法在對深度影像數據對齊的時候遇到問題,不能夠計算出正確的變換。

IntegrateFrame 函數

public void IntegrateFrame(FusionFloatImageFrame depthFloatFrame,int maxIntegrationWeight, Matrix4 worldToCameraTransform)

    用於融合深度數據楨到重構場景中maxIntegrationWeight,控制融合的平滑程度 。

worldToCameraTransform 表示此時深度數據幀的相機位置,他可以由配準API計算返回。

CalculatePointCloud 函數

public void CalculatePointCloud(FusionPointCloudImageFrame pointCloudFrame,Matrix4 worldToCameraTransform)

    通過光線跟蹤算法計算出某視點下的點雲數據。

    這些點雲信息可以被用作 FusionDepthProcessor.AlignPointClouds或者FusionDepthProcessor.ShadePointCloud函數的參數。從而來產生可視化的圖像輸出。

    pointCloudFrame參數是一個固定的圖像大小,比如說,你可以窗體大小範圍內的點雲數據,然後放置一個image控件,通過調用FusionDepthProcessor.ShadePointCloud來填充這個image控件,但是需要注意的是,圖像越大,計算所耗費的資源就越多。

    pointCloudFrame 參數是一個預先分配的點雲數據楨,他會被通過對重建立方體進行光線投射得到的點雲數據進行填充,通常通過調用FusionDepthProcessor.AlignPointClouds 或者FusionDepthProcessor.ShadePointCloud.函數產生。

    worldToCameraTransform參數表示相機視點的位置,用來表示光線投射的位置。

CalculateMesh 函數

public Mesh CalculateMesh(int voxelStep)

    用於返回重構場景的幾何網絡模型。該函數從重建立方體輸出一個多邊形立體表面模型。voxelStep 描述了採樣步長,採樣步長設置的越小,返回的模型就越精緻。

四 結語

    理解了這幾個函數,那麼就應該差不多能夠使用Kinect Fusion提供的功能了,最好的學習方式就是直接查看Kinect Developer Toolkit中提供的示例程序的代碼,相信理解了上面的函數,看起來應該不會太吃力。

    由於本人筆記本配置達不到要求,所以沒有辦法演示,不過相信通過上面的介紹,對您瞭解和使用Kinect Fusion應該會有所幫助。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章