Kinect for Windows SDK開發入門:Kinect Fusion

查志強發表於2016-09-22

【原文: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應該會有所幫助。


相關文章