廖書航
(四川大學(xué)視覺合成圖形圖像技術(shù)國防重點(diǎn)學(xué)科實(shí)驗(yàn)室,成都 610065)
目前,市面上的增強(qiáng)現(xiàn)實(shí)(AR)應(yīng)用大致可以分為3類,即基于圖片或二維碼的AR應(yīng)用,基于人臉特征的AR應(yīng)用,和基于視覺SLAM的AR應(yīng)用?;趫D片或二維碼的AR應(yīng)用將虛擬信息渲染到圖片或二維碼上,一般會(huì)要求事先準(zhǔn)備一張圖片或者二維碼,并拍攝圖片或二維碼的俯視圖,然后利用對(duì)極幾何等知識(shí)求解出虛擬物體的渲染位置和角度[1]?;谌四樚卣鞯腁R應(yīng)用提取并跟蹤人臉特征,然后根據(jù)人臉特征的位置將虛擬的信息疊加到人臉上。基于視覺SLAM的AR應(yīng)用則利用視覺SLAM來實(shí)時(shí)計(jì)算真實(shí)環(huán)境中攝像機(jī)的運(yùn)動(dòng),用該運(yùn)動(dòng)來控制渲染引擎中相機(jī)的位置和角度,并結(jié)合SLAM計(jì)算出的稀疏點(diǎn)云來放置虛擬物體。
但是,目前大部分基于視覺SLAM的AR應(yīng)用都只會(huì)利用視覺SLAM稀疏點(diǎn)云中一塊屬于平面的點(diǎn)云,并將虛擬物體放置在基于該平面點(diǎn)云擬合的虛擬平面上,一方面是因?yàn)閷?duì)整個(gè)稀疏點(diǎn)云做網(wǎng)格重建會(huì)非常耗時(shí),一方面是因?yàn)橐曈XSLAM估算出的稀疏點(diǎn)云包含非常多的噪點(diǎn),對(duì)整個(gè)稀疏點(diǎn)云做網(wǎng)格重建難度很大。
本文設(shè)計(jì)了一個(gè)基于視覺SLAM稀疏點(diǎn)云的增強(qiáng)現(xiàn)實(shí)應(yīng)用,對(duì)視覺SLAM整個(gè)稀疏點(diǎn)云做了網(wǎng)格重建,在保證了一定的實(shí)時(shí)性下,提高了AR應(yīng)用與真實(shí)環(huán)境的交互程度和真實(shí)感。
SLAM是即時(shí)定位與建模(Simultaneous Localiza?tion and Mapping)的縮寫。根據(jù)所采用的傳感器,SLAM可以分為基于激光的SLAM,基于攝像頭的SLAM,即視覺SLAM(vSLAM),以及基于攝像頭和慣性測量單元(IMU)融合的視覺慣性導(dǎo)航系統(tǒng)(VINS)等。一個(gè)完整的視覺SLAM系統(tǒng)由四部分組成,分別為前端視覺里程計(jì)、后端優(yōu)化、回環(huán)檢測和建圖[2]。前端視覺里程計(jì)負(fù)責(zé)估算相鄰圖像間相機(jī)的運(yùn)動(dòng)以及局部地圖。后端優(yōu)化負(fù)責(zé)得到全局一致的攝像頭軌跡和地圖。回環(huán)檢測模塊判斷攝像頭是否曾經(jīng)到達(dá)過當(dāng)前的位置。建圖模塊則維護(hù)一個(gè)全局的點(diǎn)云地圖。
本文設(shè)計(jì)的增強(qiáng)現(xiàn)實(shí)應(yīng)用包含4大模塊,分別為渲染模塊、單目視覺SLAM模塊、網(wǎng)格生成模塊,以及重力方向求解模塊,運(yùn)行流程見圖1。
渲染模塊使用Unity游戲引擎,用C#語言進(jìn)行開發(fā),主要負(fù)責(zé)虛擬信息的渲染、使用C#重寫的OpenCV插件獲取攝像頭的圖片、人機(jī)交互以及游戲攝像機(jī)的控制等。
在本文設(shè)計(jì)的AR應(yīng)用中,游戲攝像機(jī)將模擬真實(shí)場景中攝像機(jī)的運(yùn)動(dòng),這與許多基于視覺SLAM的AR應(yīng)用固定游戲攝像機(jī)的方式不同。當(dāng)啟動(dòng)該AR應(yīng)用時(shí),渲染模塊會(huì)將采集的圖片傳遞給單目視覺SLAM模塊,SLAM模塊會(huì)根據(jù)采集的圖片計(jì)算出真實(shí)場景中攝像機(jī)的運(yùn)動(dòng),再將該運(yùn)動(dòng)傳回Unity游戲引擎。Unity游戲引擎會(huì)用這個(gè)運(yùn)動(dòng)來設(shè)置游戲攝像機(jī)的位置和旋轉(zhuǎn),從而讓游戲攝像機(jī)和真實(shí)場景中的攝像機(jī)的運(yùn)動(dòng)保持一致。而真實(shí)攝像機(jī)采集的圖片會(huì)放置于Unity中的一個(gè)面板上,該面板與游戲攝像機(jī)固連在一起,跟著游戲攝像機(jī)移動(dòng),充當(dāng)著Unity渲染的背景。
圖1 本文AR應(yīng)用的流程圖
隨著LSDSLAM以及ORBSLAM等開源庫出現(xiàn),單目視覺SLAM的研究也變得火熱起來。單目視覺SLAM可以分為直接法以及間接法,直接法以優(yōu)化光度誤差來求解攝像機(jī)的運(yùn)動(dòng),可以在一定程度上應(yīng)對(duì)紋理缺失的場景。間接法計(jì)算特征點(diǎn)描述子并用描述子來做特征點(diǎn)跟蹤,并通過特征點(diǎn)匹配對(duì)求解攝像機(jī)運(yùn)動(dòng),具有更高的魯棒性。
本文的單目視覺SLAM模塊使用ORBSLAM這一個(gè)間接法視覺SLAM開源庫,用C++語言開發(fā)。ORB?SLAM是一個(gè)多功能且較為魯棒的SLAM系統(tǒng),支持單目、雙目和RGBD視覺傳感器。由于ORBSLAM的原生環(huán)境是Linux,而本文設(shè)計(jì)的應(yīng)用是在Windows 7上開發(fā)的,所以需要做ORBSLAM的代碼移植,并與網(wǎng)格生成模塊以及重力方向求解模塊一同封裝成C++語言動(dòng)態(tài)鏈接庫(DLL),供Unity游戲引擎調(diào)用。需要注意的是,ORBSLAM采用右手坐標(biāo)系,而Unity游戲引擎則使用左手坐標(biāo)系,那么需要一個(gè)坐標(biāo)變換矩陣將ORBSLAM計(jì)算出攝像機(jī)運(yùn)動(dòng)變換到Unity坐標(biāo)系下。
單目視覺SLAM計(jì)算出的關(guān)于周圍場景的點(diǎn)云非常稀疏,在紋理缺失的地方往往沒有點(diǎn)云對(duì)應(yīng),例如桌子的表面。如果直接使用點(diǎn)云庫(PCL)中的泊松重建或貪婪三角等算法對(duì)上述稀疏點(diǎn)云進(jìn)行網(wǎng)格重建,則會(huì)發(fā)現(xiàn)在紋理缺失的地方會(huì)出很大的洞。另外,單目視覺SLAM計(jì)算出的點(diǎn)云還帶有許多噪點(diǎn),這加大了網(wǎng)格生成的難度。
本文的網(wǎng)格生成模塊使用開源庫OpenMVS,用C++語言開發(fā)。OpenMVS是一個(gè)功能非常強(qiáng)大的三維重建開源庫,以稀疏點(diǎn)云、攝像機(jī)的初始姿態(tài)以及圖片為輸入,通過重新提取、匹配圖片中高質(zhì)量的特征點(diǎn)以及塊匹配,可以對(duì)稀疏點(diǎn)云進(jìn)行去噪和補(bǔ)洞,最終生成稠密點(diǎn)云、網(wǎng)格以及紋理網(wǎng)格,被廣泛運(yùn)用在測繪以及高精度建模。但OpenMVS的網(wǎng)格重建往往非常耗時(shí),所以本文對(duì)OpenMVS的代碼和參數(shù)設(shè)置進(jìn)行了一定的優(yōu)化,并將網(wǎng)格生成模塊放置于一個(gè)額外的線程,用于提高整個(gè)AR應(yīng)用的人機(jī)交互體驗(yàn)。
需要注意的是,由于網(wǎng)格生成模塊以O(shè)RBSLAM生成的稀疏點(diǎn)云為輸入,并輸出三角網(wǎng)格,所以最終生成的網(wǎng)格定義于右手坐標(biāo)系,導(dǎo)致三角網(wǎng)格三個(gè)頂點(diǎn)的索引順序在Unity游戲引擎的攝像機(jī)下為逆時(shí)針方向。Unity游戲引擎為了提高渲染性能,只會(huì)渲染順時(shí)針頂點(diǎn)索引的三角網(wǎng)格,即三角網(wǎng)格只會(huì)顯示一面[3]。此處需要交換三角網(wǎng)格中第一個(gè)頂點(diǎn)和第三個(gè)頂點(diǎn)的索引。
重力方向求解模塊負(fù)責(zé)計(jì)算出真實(shí)環(huán)境中重力的方向,供Unity游戲引擎使用,采用C++語言開發(fā)。由于本文設(shè)計(jì)的AR應(yīng)用僅使用了一個(gè)攝像頭,所以無法直接測量出真實(shí)環(huán)境中的重力方向。當(dāng)攝像機(jī)對(duì)準(zhǔn)真實(shí)環(huán)境中的一塊水平平面時(shí),點(diǎn)擊Unity中的重力方向求解按鈕,重力方向求解模塊便會(huì)對(duì)屬于該水平平面的稀疏點(diǎn)云做平面擬合,并求解出擬合平面的法向量。
具體做法為:
(1)累加點(diǎn)云平面中所有的三維點(diǎn)的坐標(biāo),求解坐標(biāo)平均值,該坐標(biāo)平均值為點(diǎn)云平面的幾何中心點(diǎn)O,點(diǎn)O應(yīng)位于擬合平面上。
(2)將點(diǎn)云平面中的三維點(diǎn)變換到以幾何中心點(diǎn)O為原點(diǎn)的坐標(biāo)系下,并由變換后的點(diǎn)云建立矩陣A。矩陣A的列為三維點(diǎn)的坐標(biāo)分量,行數(shù)為點(diǎn)云中點(diǎn)的個(gè)數(shù)。
(3)設(shè)擬合平面的法向量為X,利用奇異值分解(SVD)解超定方程組AX=0便可以求出法向量[4]。該法向量的反方向便是真實(shí)環(huán)境中的重力方向。最后,將該法向量的反方向設(shè)置為Unity游戲引擎中的重力方向。
本文AR應(yīng)用的開發(fā)環(huán)境為Windows 7系統(tǒng),CPU為Intel i7-3600QM 2.30GHz,在不使用GPU加速的情況下運(yùn)行幀率可以達(dá)到10Hz以上,多線程下網(wǎng)格的生成大概會(huì)耗時(shí)3秒。在網(wǎng)格生成期間,AR應(yīng)用可以與用戶進(jìn)行正常交互。AR應(yīng)用測試的場景包含兩個(gè)紙盒以及一張紋理豐富的背景圖,具體的效果可以參考圖2。從圖2可以出,虛擬的石頭可以與兩個(gè)木盒進(jìn)行碰撞,并且虛擬石頭的陰影可以顯示在盒子上,這是因?yàn)锳R應(yīng)用的虛擬網(wǎng)格是基于整個(gè)視覺SLAM的稀疏點(diǎn)云來生成的,而不是僅僅對(duì)屬于平面的點(diǎn)云進(jìn)行了網(wǎng)格重建。本文AR應(yīng)用生成的網(wǎng)格可以參考圖3。
圖2 本文AR應(yīng)用的演示圖
圖3 本文AR應(yīng)用生成的網(wǎng)格
總的來說,本文提出的基于視覺SLAM稀疏點(diǎn)云的增強(qiáng)現(xiàn)實(shí)應(yīng)用在一定程度上提高AR應(yīng)用與真實(shí)場景的交互程度以及真實(shí)感,但魯棒性還不夠高。
當(dāng)攝像機(jī)劇烈運(yùn)動(dòng)或者大角度移動(dòng)時(shí),比如從桌子上方的俯視視角移動(dòng)到與桌子平行的視角,虛擬物體可能會(huì)偏離真實(shí)環(huán)境的對(duì)應(yīng)位置。這是因?yàn)镺RB?SLAM中前端里程計(jì)是基于特征點(diǎn)的。要想計(jì)算出兩幀圖片間準(zhǔn)確的攝像機(jī)運(yùn)動(dòng),ORBSLAM需要較多的、正確的特征點(diǎn)匹配對(duì)。然而,當(dāng)攝像機(jī)劇烈運(yùn)動(dòng)時(shí),連續(xù)圖片幀的視差很大,正確有效的特征點(diǎn)匹配對(duì)的數(shù)量往往不足,最終導(dǎo)致無法計(jì)算出攝像機(jī)運(yùn)動(dòng)或者計(jì)算出誤差很大的攝像機(jī)運(yùn)動(dòng)。
可以通過將單個(gè)攝像頭與慣性測量單元(IMU)融合來一定程度上解決上述問題。攝像頭與慣性測量單元是互補(bǔ)的。攝像頭可以提供豐富的信息,而慣性測量單元?jiǎng)t可以在劇烈運(yùn)動(dòng)下提供較好的相機(jī)運(yùn)動(dòng)初值。另外,慣性測量單元中的加速度計(jì)可以測出真實(shí)尺度的平移以及重力方向,這樣就不用去擬合一個(gè)點(diǎn)云平面來求解重力方向了。