三維場景重建整合筆記

近年來,隨着智能手機、頭盔立體顯示等技術的發展和 普及,虛擬現實技術取得了飛速發展。在 VR 技術中場景建 模是最關鍵的一步。3D 遊戲通常採用專業三維建模軟件, 如 Autodesk Maya、Autodesk 3ds Max 等進行建模,此方法 耗時耗力,所建模型爲虛擬場景。對真實場景一般需要藉助 專業三維掃描設備,此方法測量精度高,但設備價格昂貴, 不利於大範圍推廣。爲此本文將多視圖三維重建技術應用於 VR,實現真實場景的建模。該方法直接從多個視角的 2D 圖 像提取場景的三維信息,數據採集簡單快捷,成本低廉,但 由於遮擋、光照變化、特徵弱等各種因素,建模過程會出現 噪聲、空洞等各種瑕疵。 目前基於多視角圖像的三維重建算法主要有三類: ①基於體像素的三維重建算法;②基於深度圖的三維重建算法;③基於特徵點生長的三維重建算法。基於特徵點生長的三維重建技術,通過對現實場景進項圖像採集,然後對多幅圖像進行特徵點檢測、匹配,生成稀疏種子點雲, 並在此基礎上增加生長點有條件的初值矯正優化等措施,提高重建的精確性,降低噪聲、空洞等引起的重建錯誤。

 

三維場景渲染與重建是利用場景的圖形或圖像等信息渲染出特定觀測視點的場景圖像和重建出三維場景的結構模型,它是計算機視覺中的一個重要的研究課題,開展該方面的研宄對於模式識別、虛擬現實、探險救援、軍事偵察等都具有非常重要的意義。經典的三維場景渲染與重建方法按照基本處理單位的不同分爲:

以像素點作爲基本處理單位逐點進行渲染與重建,該方法獲得的渲染圖像和重建模型比較真實,但是速度較慢

以網格作爲基本處理單位進行渲染與重建,該計算速度較快,基本能滿足實時渲染的要求,但是當網格內包含目標邊界時導致渲染圖像和重建模型失真

 

另外,現有的諸多渲染與重建算法均要求已知不同觀測視點的座標,而現實情況下並不一定能精確獲得視點的座標,例如水下機器人受水流衝擊影響,在拍照時座標很難確定。本文是以圖像粒(即連通區域)作爲基本處理單位,研究基於空間多視點圖像的三維場景渲染與重建技術。主要研宄內容包括:

(1)基於形態學連通性理論的粒化研究

考慮到圖像的色相、亮度和紋理等特性,提出了利用形態學屬性連通算子研宄彩色圖像的粒化方法,每個粒代表了一個不規則形狀的連通區域。同一粒的內部像素點具有同質性或相同的紋理結構,不同粒中像素點的值具有不同的特性。探討了基於隱馬爾科夫模型的粒邊界確定方法,降低了視角、光照對彩色圖像粒化的影響。

(2)基於空間拓撲結構的圖像配準研究

建立了基於有向圖的圖像粒(連通區域)空間拓撲結構關係,引入可達矩陣分析拓撲結構圖中有向樹和有向迴路(即廣義頂點)的特點。將圖像粒進行模糊化,探討了基於模糊推理的不同視點間圖像粒的全局最佳匹配問題,在圖像粒匹配的基礎上,分析粒內特徵點匹配關係,建立了匹配粒內像素點的單應映射。該方法消除了具有自相似結構的不同視點圖像間錯誤匹配問題。

(3)在未知多視點相機位置關係的前提下,實現三維場景渲染與重建。

針對相機徑向畸變等因素的影響,提出了基於加權Sampson近似的不同視點相機間

相對位置計算方法。提出了基於視圖張力漂移的場景深度估計方法,並且研宄了基於圖像粒的空間變換與場景深度圖相結合的三維場景渲染方法,研宄了模型表面擬合與點雲模型修正相結合的三維模型重建技術。上述方法在未知多視點相對位置關係的前提下,降低了累積誤差的影響,能夠比較真實的實現三維場景的渲染與重建。

 

基於RGBD的三維重建:

https://www.gameres.com/676770.html

簡單地說,三維重建就是從輸入數據中建立3D模型。其中,在面向消費者層面的深度相機出現以前,三維重建技術的輸入數據通常只有RGB圖像(圖1左)。通過對物體的不同角度拍攝的RGB圖像,使用相關的計算機圖形學和視覺技術,我們便可以重建出該物體的三維模型。不過,早期的三維重建技術得到的模型精度往往較低,且技術的適用範圍有限。消費者層面的深度相機的出現爲三維重建技術提供了深度圖像(depth image)數據,大大降低了重建的難度,並使得三維重建技術可以應用到幾乎任何現實場景中(圖1右)。由於基於深度相機的三維重建技術所使用的數據是RGB圖像和深度圖像,因此,這類技術通常也被稱爲基於RGBD數據的三維重建技術(D指代depth)。

https://di.gameres.com/attachment/forum/201608/18/161629ohjpz06dd6i5miqg.jpg

深度值和三維數據

在介紹基於深度相機的三維重建技術之前,首先需要了解深度圖像中的數據的具體含義。對於現實場景中的點,深度相機掃描得到的每一幀數據不僅包括了場景中的點的彩色RGB圖像,還包括每個點到深度相機所在的垂直平面的距離值。這個距離值被稱爲深度值(depth),這些深度值共同組成了這一幀的深度圖像(圖1右)。也就是說,深度圖像可以看做是一副灰度圖像,其中圖像中每個點的灰度值代表了這個點的深度值,即該點在現實中的位置到相機所在垂直平面的真實距離。圖2簡單說明了RGB圖像和深度圖像的關係。

https://di.gameres.com/attachment/forum/201608/18/16162922uprnzu7q9dje4m.jpg


如圖所示,對於現實場景中點M,深度相機能夠獲取其在RGB圖像中的成像點XM,以及M到相機所在的垂直平面(即XY平面)的距離,這個距離便是M的深度值。以相機位置爲原點,相機所朝方向爲Z軸,相機的垂直平面的兩個軸向爲X、Y軸,可以建立相機的局部三維座標系。另外,RGB圖像到相機位置的距離正是相機的焦距。通過這些數據並使用簡單的三角幾何公式,我們很容易得到M在相機的局部座標系中的三維座標。於是,RGB圖像中的每個點,都會對應一個在相機的局部座標系中的三維點。因此,深度相機的每一幀的深度圖像就相當於一個在相機的局部三維座標系中的點雲模型。

基於深度相機的三維重建的核心問題

如果輸入的RGBD數據只有一幀,那麼只需要把這一幀對應的點雲模型作爲重建的模型輸出即可。不過,通常的深度相機的幀率(FPS)普遍較高,所帶來的數據量是非常龐大的。以微軟的Kinect v1爲例,其FPS=30,即1秒鐘掃描30幀,也就是1秒鐘便可得到30張RGB圖像和30張深度圖像。每一幀圖像的分辨率通常是640x480,那麼在短短的1秒鐘,深度相機得到的點雲的點的個數是640x480x30=9216000。那麼,如何在重建過程中處理如此龐大的數據?另外,深度相機所得到的深度數據是存在誤差的,即使相機位置固定,現實場景中的點在不同幀中的深度值也會有區別 。也即是說,對於每一個現實中的點,在掃描過程中會得到衆多「測量值」位置。那麼,如何估計點的最終位置?這個問題可以被稱爲「從大數據中建立模型」問題(圖3)

https://di.gameres.com/attachment/forum/201608/18/16163052cvcyncshx6g9lu.jpg

除了上述問題外,重建過程中還有一個關鍵性問題——相機位置的估計。首先,爲什麼需要估計相機位置?通過本文之前內容講述的深度值的原理可知,每一幀深度圖像對應的點雲模型是在相機的局部三維座標系中。因此,不同的相機位置(即不同幀)便對應着不同的局部三維座標系(local space/coordinate frame)。然而,重建後的模型需要坐落在一個座標系,即世界座標系或全局座標系(world/global space/coordinate frame)中。於是,我們需要找到每一幀的相機局部座標系同世界座標系的位置關係,也就是確定每一幀中相機在世界座標系中的位置(圖4)。在計算機視覺和智能機器人領域,這個問題是經典的「同步定位與地圖構建」(Simultaneous localization and mapping,簡稱SLAM)中的定位問題:機器人在未知環境中,如何通過獲取的周圍環境的數據來確定自己所在的位置。

https://di.gameres.com/attachment/forum/201608/18/1616305j9g6degfcfc95gi.jpg相機位置的估計

給定每一幀輸入的RGBD數據,我們需要估計相機在世界座標系中的位置。通常我們會把第一幀的相機位置當做是世界座標系的原點,於是,我們需要估計的便是相機在此後每一幀相對於第一幀的位置的轉移矩陣(transformation matrix)。使用數學語言描述是:在給定了第k-1幀重建的模型以及轉移矩陣Tw,k-1,還有第k幀的輸入RGBD數據,估計出第k幀的轉移矩陣Tw,k(圖5)。這裏的w下標指代世界座標系world,k是幀的編號,k>1。

https://di.gameres.com/attachment/forum/201608/18/161630ozwqossdlwoqoqfh.jpg

Newcombe 等人於2011年提出的三維重建的經典方法KinectFusion[1] 使用了迭代最近點(Iterative closest point,簡稱ICP)方法來解決以上問題。給定輸入的原始數據(source)和目標數據(target),以及兩者的數據點之間的對應關係(correspondence),ICP計算得到原始數據和目標數據之間的轉移矩陣,該矩陣使得所有的目標數據點到其對應的原始數據點所在的切平面的距離之和最小(圖6)。使用數學公式這個目標函數是:

https://di.gameres.com/attachment/forum/201608/18/16163039nfimciissnh9ci.jpg

這裏的si和di是原始數據點和對應的目標數據點,ni是si所在的切平面的法向量(圖6右)。

https://di.gameres.com/attachment/forum/201608/18/161631ull39zrhl1uh3zfv.jpg

爲了給ICP算法找到合適的對應點,KinectFusion方法簡單的將目標數據點——第k幀的數據點(圖5中的黃色點)——通過轉移矩陣Tw,k-1投影到原始數據點——第k-1幀的點(圖5中的紅色點),然後將兩者作爲對應相互對應的點。依照這種對應關係的ICP算法的最大優點是速度快,並且在掃描幀率較大,相鄰兩幀差別很小的情況下的精度很高。在估計了第k幀的轉移矩陣後,將其作用到第k幀的在相機的局部座標系的數據中,便可得到在全局座標系中的數據。圖7展示了典型的從輸入數據(a),到估計相機位置並作用到數據上(b),然後到最終的優化之後的重建模型(c)的流程

https://di.gameres.com/attachment/forum/201608/18/1616316zb1o2xqbkyhbiku.jpg

KinectFusion中的ICP方法僅僅使用了三維空間中的數據,並未考慮到RGB數據信息。另外,ICP必須要建立在掃描幀率較大,相鄰兩幀差別很小的前提下。因此,這種估計相機位置的方法存在較大的侷限性,尤其是對存在較大平面的場景(如牆面、天花板和地板等)時,這種估計方法會帶來很大的誤差。KinectFusion之後的科研工作者們也提出了一些改進方法。例如,在估計相機位置時,同時考慮RGB信息和三維信息,並建立新的目標函數來進行優化[2]。另外,使用已定義好的模型來模擬代替較大平面的物體[3],可以很好的排除掉這類物體所帶來的擾動。不過,考慮到實時性和穩定性,這種基於ICP的框架依然是非常經典且最常見的估計相機位置的方法。

從大數據中建立模型

從上文以及圖7(c)可以看出,在估計了相機位置後,我們需要把新一幀第k幀的數據同已有的第k-1幀的模型數據結合起來,以輸出優化後的模型。這其實就是本文在前面介紹的問題:對於每個現實場景中的點,如何從該點的衆多「測量值」位置中估計出最終位置?

這裏繼續講述經典的KinectFusion中所採用的方法。KinectFusion在世界座標系中定義了一個立方體,並把該立方體按照一定的分辨率切割成小立方體(voxel)。以圖8上爲例所示,圖中定義了一個3x3x3米的立方體,並把立方體分爲不同分辨率的小立方體網格。也就是說,這個大立方體限制了經過掃描重建的模型的體積。然後,KinectFusion使用了一種稱爲「截斷有符號距離函數」(truncated signed distance function,簡稱TSDF)的方法來更新每個小網格中的一個數值,該數值代表了該網格到模型表面的最近距離,也稱爲TSDF值(圖8下)。對於每個網格,在每一幀都會更新並記錄TSDF的值,然後再通過TSDF值還原出重建模型。例如,通過圖8下兩幅圖中的網格的TSDF數值分佈,我們可以很快還原出模型表面的形狀和位置。這種方法通常被稱爲基於體數據的方法(Volumetric-based method)。該方法的核心思想是,通過不斷更新並「融合」(fusion)TSDF這種類型的測量值,我們能夠 越來越接近所需要的真實值。

https://di.gameres.com/attachment/forum/201608/18/161631pt1jt851q55tq877.jpg

KinectFusion中TSDF的更新方法核心思想就是簡單的對所有的測量值加權平均的過程。這種更新方式效率高,對於保證實時三維重建非常有必要。基於體數據的方法簡單直觀,而且容易使用並行計算實現,因此可以極大的增加掃描和重建效率。另外, 使用計算機圖形學中的網格生成相關方法(例如MarchingCubes),我們可以很容易從這種體數據的結構中生成三角網格模型,這對於進一步的研究和渲染非常重要。不過,這種方法也有很大缺點。例如,KinectFusion這種基於體數據的方法提前已經限定了掃描空間(例如圖8上的3x3x3米),超過這個空間的顯示場景的物體將無法重建,這是因爲定義立方體和網格需要的內存空間非常大 。這就意味着,KinectFusion無法用來掃描大範圍空間。另外,立方體中的所有的網格中的TSDF都需要記錄,即便這個網格在現實場景中根本沒有點,這就造成了極大的內存空間的浪費,並限制了掃描範圍。針對這些問題,KinectFusion之後的科研工作者們也提出了一些改進方法。例如,一種移動式的體數據網格(moving volume)方法可以不斷移動定義好的網格模型到新的場景中,並不斷輸出已經重建好的模型到本地空間中,從而能夠無限擴展掃描空間[4](圖9)。另外,一些重建方法使用了點雲的數據結構來代替體數據結構,在重建過程中不斷把密集的點雲數據融合成一定密度的點雲[5]。這種方式不需要存儲場景中的並不存在的點,因此能夠節省大量空間以擴大掃描範圍。

https://di.gameres.com/attachment/forum/201608/18/161632ccv3b1m1c65yh5x5.jpg

渲染

  vr的性能瓶頸來源

1.vr需要至少同時渲染2 張50fps的圖像,比常規的pc渲染量都要大。

2.vr對輸入延遲性要求很高,因爲對輸入超過20ms的延遲都會引起用戶的不適。

VR WORKS的優化

1.vr sli 多顯卡支持

通過增加顯卡,增加渲染性能。

常規的多顯卡渲染是這樣的,

https://img-blog.csdn.net/20160323210415898?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

即顯卡0和顯卡1輪流渲染第n幀和第n1幀,但是要求cpu要提交的足夠快,因爲cpu還是要提交兩份drawcall,cpu不能成爲瓶頸,這種方式從繪製n到n繪製出來的延時如圖。

vrworks 做了改進,如圖

https://img-blog.csdn.net/20160323210625133?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

https://img-blog.csdn.net/20160323211045588?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

讓顯卡0和顯卡1負責繪製左右兩眼,而cpu爲兩個顯卡提供一模一樣的drawcall,因爲zaivr的兩眼繪製的東西基本是一樣的,除了perspective矩陣不一樣。而vrworks通過其api,實現了一組draw call 對多個顯卡的廣播,並可以爲不同顯卡設置不同的perspective(常量)。這樣cpu一份drawcall對於兩眼,而兩眼的繪製在兩個cpu並行,延遲大大節省。當然這裏還有一些可能可以優化的,比如很多東西,例如shadow map,基於gpu的一些物理可能不需要在兩個gpu都做一遍,可以優化一下。

 

2.Multy Resolution Rendering 多分辨率渲染

這個在vr領域算是經典的優化了,很多vr設備都做了這個,原理來源於,vr的圖像爲了適應眼鏡的變形要做捲曲(wrap),如圖

https://img-blog.csdn.net/20160323211736168?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

我們需要得到的是右邊的圖,但是渲染出來的都是左圖,所以一般都是在最後將左圖在圖像上做處理,變成右圖,這樣我們可以看到其實左圖在邊緣處很多像素在捲曲後被浪費了,於是人們就像我們是不是可以對vr的圖像做不同分辨率的渲染,即中心區域用比較高的分辨率,而邊緣位置用較低的分辨率,極限情況下,將大部分邊緣降低分辨率,可以減少50%的pixel的渲染,提高一倍的效率。

https://img-blog.csdn.net/20160323212119764?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

但是常規的渲染管線,要這樣做,得不償失,因爲你要切分這個區域,定義多個不同大小的viewport,然後將物體依次渲染到多個viewport上,當然你可能會想到對不同的viewport可以剪裁掉不同的物體。

但是nvidia的maxwell架構的芯片,即GTX900以上(也就是爲什麼做vr要用好的顯卡)支持了一種叫做multi-projection的技術,即在顯卡層面,支持同時運行多個視口和投影,他不同於常規管線,他在管線中並行了多個投影,同時渲染到多個viewport,pipeline還是一次,只是在後面將這些像素繪製到多個viewport,這就是硬件層面的多適口多分辨率。

3.asyncchronous timewarp 異步時間捲曲

timewarp也是vr很經典的優化,在occlus等早已使用,如果沒有timewarp,我們會感覺很大的延時和眩暈。因爲就算幀率再高,我們看到影響的那一剎那,渲染的也是過去某個時刻的圖像,和我們當時所處的位置是不一樣的,這種不一致隨着幀渲染耗時的增長而增長,這種timewarp的做法是,在gpu繪製結束,掃描給顯示屏前,將這個圖像做一個圖像空間的位移,以校準我們當前的位置,也就是說處於p0位置渲染的圖像,在p1位置繪製好給我們,我們需要將其校準成p1位置的樣子,這種校準有很多算法,都是在圖像處理上做的平移,這樣我們會感覺到看見的和我們的位置是同步的。

但是在傳統的渲染中,這些工作是在一個流水線上的,也就是同步的,當某一幀很耗時很卡時,用戶會遲遲收不到當前位置校準的圖片,一直停留在上一幀的圖片,因爲gpu卡住了,後面的校準(timewarp)也不能進行,用戶會感覺強烈的卡和眩暈。

這裏就提出了一個異步 timewarp的概念,即在gpu上有一個獨立的線程做這個warp,即不管你主線程渲染卡成什麼樣,我這個獨立的線程會按照幀率給你每個位置的warp,給你最新的基於你位置的圖像,這能解決很卡很卡時我們依然能夠得到模擬的圖像。但是傳統的gpu不支持這種獨立的線程。nvdia的vrworks加入了這個。他加入了一個high-priority context的概念,允許用戶啓動一個優先級最高的線程最warp,獨立於你的渲染線程。

4. direct mode

傳統的渲染,pc的顯示器會把vr眼鏡作爲顯示器的一個顯示擴展,vr眼鏡和gpu是沒有直接交互的,而vrwroks裏可以開啓vr headset的直接模式,讓gpui直接將圖像掃描到vr設備。

5.Front Buffer Rendering

 

 

  1. 預測渲染:因爲vr對渲染的延遲特別敏感,vr設備可能每時每刻都在動,而正常來說gpu上渲染出來的結果一定都會比cpu計算提交的時候玩,看到的總是和當前所處位置不一致的圖像,延遲越大就越會頭暈,valve解決的思路是大量應用了預測,等於在在T0時刻就預測T1時刻應該所處的位置,計算T1的渲染結果,這樣提交後,GPU在T1時刻渲染出來恰好敢上正處於T1的位置,因爲這種T0到T1的提前量都是在幾十ms的範圍內,所以預測的誤差不會很大,可以說爲了減少延遲一定要「」預測「」,而具體這個提前量是多少,其實文章也是用nvsight或者gpuview這種大量的progile得到的經驗值,這種預測渲染的CPU和GPU工作的流程是這樣的,等於在GPU渲染本幀的時候,CPU已經在同時計算和提交「預測的」下一幀

  1. 因爲vr渲染的圖像是要wrapped,所以一些邊緣的像素是不用渲染的,可以提前做個stencil mask,可以減少17%渲染量。
  2. MSAA(多重採樣抗鋸齒)在vr渲染是可用的且是必要的

 

幾何模型

移除你的幾何體中的任何用VR永遠看不到的面。我們不想要渲染永遠不會被看見的東西。舉個例子,如果用戶永遠不會看見一個碗櫃的背面因爲它靠着牆的原因,那麼我們在模型中不需要任何那樣的面。

儘可能簡化模型設計。根據你的目標平臺,你可能想嘗試通過貼圖增加細節,潛在的視差映射貼圖以及曲面細分,這可能影響性能,也許對於你的目標平臺也不適合、有效。

Overdraw

Overdraw可以讓你查看有哪些對象繪製在了其他對象的前面,而這是在浪費GPU時間。儘可能考慮減少使用overdraw。通過使用場景視圖控制欄(Scene View Control Bar),你能查看場景視圖中的overdraw。