廖書航
(四川大學視覺合成圖形圖像技術國防重點學科實驗室,成都 610065)
目前,市面上的增強現實(AR)應用大致可以分為3類,即基于圖片或二維碼的AR應用,基于人臉特征的AR應用,和基于視覺SLAM的AR應用。基于圖片或二維碼的AR應用將虛擬信息渲染到圖片或二維碼上,一般會要求事先準備一張圖片或者二維碼,并拍攝圖片或二維碼的俯視圖,然后利用對極幾何等知識求解出虛擬物體的渲染位置和角度[1]。基于人臉特征的AR應用提取并跟蹤人臉特征,然后根據人臉特征的位置將虛擬的信息疊加到人臉上。基于視覺SLAM的AR應用則利用視覺SLAM來實時計算真實環境中攝像機的運動,用該運動來控制渲染引擎中相機的位置和角度,并結合SLAM計算出的稀疏點云來放置虛擬物體。
但是,目前大部分基于視覺SLAM的AR應用都只會利用視覺SLAM稀疏點云中一塊屬于平面的點云,并將虛擬物體放置在基于該平面點云擬合的虛擬平面上,一方面是因為對整個稀疏點云做網格重建會非常耗時,一方面是因為視覺SLAM估算出的稀疏點云包含非常多的噪點,對整個稀疏點云做網格重建難度很大。
本文設計了一個基于視覺SLAM稀疏點云的增強現實應用,對視覺SLAM整個稀疏點云做了網格重建,在保證了一定的實時性下,提高了AR應用與真實環境的交互程度和真實感。
SLAM是即時定位與建模(Simultaneous Localiza?tion and Mapping)的縮寫。根據所采用的傳感器,SLAM可以分為基于激光的SLAM,基于攝像頭的SLAM,即視覺SLAM(vSLAM),以及基于攝像頭和慣性測量單元(IMU)融合的視覺慣性導航系統(VINS)等。一個完整的視覺SLAM系統由四部分組成,分別為前端視覺里程計、后端優化、回環檢測和建圖[2]。前端視覺里程計負責估算相鄰圖像間相機的運動以及局部地圖。后端優化負責得到全局一致的攝像頭軌跡和地圖。回環檢測模塊判斷攝像頭是否曾經到達過當前的位置。建圖模塊則維護一個全局的點云地圖。
本文設計的增強現實應用包含4大模塊,分別為渲染模塊、單目視覺SLAM模塊、網格生成模塊,以及重力方向求解模塊,運行流程見圖1。
渲染模塊使用Unity游戲引擎,用C#語言進行開發,主要負責虛擬信息的渲染、使用C#重寫的OpenCV插件獲取攝像頭的圖片、人機交互以及游戲攝像機的控制等。
在本文設計的AR應用中,游戲攝像機將模擬真實場景中攝像機的運動,這與許多基于視覺SLAM的AR應用固定游戲攝像機的方式不同。當啟動該AR應用時,渲染模塊會將采集的圖片傳遞給單目視覺SLAM模塊,SLAM模塊會根據采集的圖片計算出真實場景中攝像機的運動,再將該運動傳回Unity游戲引擎。Unity游戲引擎會用這個運動來設置游戲攝像機的位置和旋轉,從而讓游戲攝像機和真實場景中的攝像機的運動保持一致。而真實攝像機采集的圖片會放置于Unity中的一個面板上,該面板與游戲攝像機固連在一起,跟著游戲攝像機移動,充當著Unity渲染的背景。

圖1 本文AR應用的流程圖
隨著LSDSLAM以及ORBSLAM等開源庫出現,單目視覺SLAM的研究也變得火熱起來。單目視覺SLAM可以分為直接法以及間接法,直接法以優化光度誤差來求解攝像機的運動,可以在一定程度上應對紋理缺失的場景。間接法計算特征點描述子并用描述子來做特征點跟蹤,并通過特征點匹配對求解攝像機運動,具有更高的魯棒性。
本文的單目視覺SLAM模塊使用ORBSLAM這一個間接法視覺SLAM開源庫,用C++語言開發。ORB?SLAM是一個多功能且較為魯棒的SLAM系統,支持單目、雙目和RGBD視覺傳感器。由于ORBSLAM的原生環境是Linux,而本文設計的應用是在Windows 7上開發的,所以需要做ORBSLAM的代碼移植,并與網格生成模塊以及重力方向求解模塊一同封裝成C++語言動態鏈接庫(DLL),供Unity游戲引擎調用。需要注意的是,ORBSLAM采用右手坐標系,而Unity游戲引擎則使用左手坐標系,那么需要一個坐標變換矩陣將ORBSLAM計算出攝像機運動變換到Unity坐標系下。
單目視覺SLAM計算出的關于周圍場景的點云非常稀疏,在紋理缺失的地方往往沒有點云對應,例如桌子的表面。如果直接使用點云庫(PCL)中的泊松重建或貪婪三角等算法對上述稀疏點云進行網格重建,則會發現在紋理缺失的地方會出很大的洞。另外,單目視覺SLAM計算出的點云還帶有許多噪點,這加大了網格生成的難度。
本文的網格生成模塊使用開源庫OpenMVS,用C++語言開發。OpenMVS是一個功能非常強大的三維重建開源庫,以稀疏點云、攝像機的初始姿態以及圖片為輸入,通過重新提取、匹配圖片中高質量的特征點以及塊匹配,可以對稀疏點云進行去噪和補洞,最終生成稠密點云、網格以及紋理網格,被廣泛運用在測繪以及高精度建模。但OpenMVS的網格重建往往非常耗時,所以本文對OpenMVS的代碼和參數設置進行了一定的優化,并將網格生成模塊放置于一個額外的線程,用于提高整個AR應用的人機交互體驗。
需要注意的是,由于網格生成模塊以ORBSLAM生成的稀疏點云為輸入,并輸出三角網格,所以最終生成的網格定義于右手坐標系,導致三角網格三個頂點的索引順序在Unity游戲引擎的攝像機下為逆時針方向。Unity游戲引擎為了提高渲染性能,只會渲染順時針頂點索引的三角網格,即三角網格只會顯示一面[3]。此處需要交換三角網格中第一個頂點和第三個頂點的索引。
重力方向求解模塊負責計算出真實環境中重力的方向,供Unity游戲引擎使用,采用C++語言開發。由于本文設計的AR應用僅使用了一個攝像頭,所以無法直接測量出真實環境中的重力方向。當攝像機對準真實環境中的一塊水平平面時,點擊Unity中的重力方向求解按鈕,重力方向求解模塊便會對屬于該水平平面的稀疏點云做平面擬合,并求解出擬合平面的法向量。
具體做法為:
(1)累加點云平面中所有的三維點的坐標,求解坐標平均值,該坐標平均值為點云平面的幾何中心點O,點O應位于擬合平面上。
(2)將點云平面中的三維點變換到以幾何中心點O為原點的坐標系下,并由變換后的點云建立矩陣A。矩陣A的列為三維點的坐標分量,行數為點云中點的個數。
(3)設擬合平面的法向量為X,利用奇異值分解(SVD)解超定方程組AX=0便可以求出法向量[4]。該法向量的反方向便是真實環境中的重力方向。最后,將該法向量的反方向設置為Unity游戲引擎中的重力方向。
本文AR應用的開發環境為Windows 7系統,CPU為Intel i7-3600QM 2.30GHz,在不使用GPU加速的情況下運行幀率可以達到10Hz以上,多線程下網格的生成大概會耗時3秒。在網格生成期間,AR應用可以與用戶進行正常交互。AR應用測試的場景包含兩個紙盒以及一張紋理豐富的背景圖,具體的效果可以參考圖2。從圖2可以出,虛擬的石頭可以與兩個木盒進行碰撞,并且虛擬石頭的陰影可以顯示在盒子上,這是因為AR應用的虛擬網格是基于整個視覺SLAM的稀疏點云來生成的,而不是僅僅對屬于平面的點云進行了網格重建。本文AR應用生成的網格可以參考圖3。

圖2 本文AR應用的演示圖

圖3 本文AR應用生成的網格
總的來說,本文提出的基于視覺SLAM稀疏點云的增強現實應用在一定程度上提高AR應用與真實場景的交互程度以及真實感,但魯棒性還不夠高。
當攝像機劇烈運動或者大角度移動時,比如從桌子上方的俯視視角移動到與桌子平行的視角,虛擬物體可能會偏離真實環境的對應位置。這是因為ORB?SLAM中前端里程計是基于特征點的。要想計算出兩幀圖片間準確的攝像機運動,ORBSLAM需要較多的、正確的特征點匹配對。然而,當攝像機劇烈運動時,連續圖片幀的視差很大,正確有效的特征點匹配對的數量往往不足,最終導致無法計算出攝像機運動或者計算出誤差很大的攝像機運動。
可以通過將單個攝像頭與慣性測量單元(IMU)融合來一定程度上解決上述問題。攝像頭與慣性測量單元是互補的。攝像頭可以提供豐富的信息,而慣性測量單元則可以在劇烈運動下提供較好的相機運動初值。另外,慣性測量單元中的加速度計可以測出真實尺度的平移以及重力方向,這樣就不用去擬合一個點云平面來求解重力方向了。