姜子鵬,卜凡亮,秦 靜
(中國人民公安大學 信息技術與網絡安全學院,北京 100038)
在虛擬環境中,三維重建是處理、分析和操作模型的基礎[1]。根據獲取場景的不同可將其分為基于紋理信息和基于深度信息的三維重建[2]。基于深度信息的重建可分為接觸式和非接觸式,非接觸式技術又有主動和被動掃描的區別。常見飛行時間(time of flight,ToF) 相機、激光系統、結構光系統和 Kinect 深度傳感器等[3]均使用了非接觸式主動掃描技術。
現有三維重建技術可分為實時和非實時技術。非實時技術主要有雙目視差法、明暗恢復形狀法等。因存在計算復雜、操作繁瑣等問題,以上方法并不能實時應用于三維場景重建。實時三維重建技術依靠設備發出光線與物體發生反射后,通過設備接收深度信息以完成重建。目前實時三維重建技術主要有: 單激光線掃描法[4]、傅里葉變換輪廓法、彩色條紋結構光法等。實時三維重建算法效率高,處理數據量小,能有效處理噪聲。目前能用于實時三維重建的設備有基于結構光的 Kinect[5]、基于Time of Flight的Camcube[6]和 Mesa Imaging Swiss Ranger 4000[7]。
針對三維重建的技術方法,國內外學者進行了大量研究。劉利剛等[8]采用一種實用性方法對不同視角下的不同身體部位進行配準,利用多個外設協調工作實現對動態和靜態人體三維重建。劉鑫等[9]給出一種物體快速重建方法,借助圖形顯卡GPU,提出一種簡單易用的粗標定方法和全自動快速物體重建方法。針對Kinect Fusion 需要大量 GPU存儲空間的問題,曾鳴[10]提出一種基于八叉樹的數據結構,并在數據節點存儲符號距離函數,在八叉樹結構的基礎上,重建更新和表面預測,從而高效利用 GPU 的并行計算能力。Rushmeier等[11]將基于深度圖像的三維重建過程分為幾何處理和面的表示。Peter Henry等[12]利用SIFT特征匹配定位和TORO優化算法,設計了一種實時視覺SLAM系統。Fiorairo等[13]提出了RGB-D SLAM算法,使用 Hogman優化算法和SURF特征匹配搭建實時性高、魯棒性強的重建系統。Harris 等[14]首次提出角點的定義。Shi等[15]在此基礎上進行改進,提出一種效果更好的角度提取方法。目前使用比較廣泛的特征點提取和匹配方法是SIFT(scale-invariant feature transform)方法[16]。
本文結合現有研究課題,聚焦于PCL環境搭建過程及點云庫在三維重建中的應用,以SIFT算法為基礎,結合FLANN算法,對圖像進行特征提取與匹配,以提高特征匹配效率。
點云庫,全稱Point Cloud Library (PCL)[17],是一個既可以單獨使用又可以作為輔助工具的工程,本質是一個開源C++編程庫,可以在Windows和Linux等操作系統上運行。點云庫常被用于處理點云數據和二維或三維圖像。建立點云庫的最初目的是為三維點云數據處理和ROS[18]研究及應用建立一個基礎架構。PCL第一個基礎算法是由Dr. Rusu開發,于2009年由Willow Garage公司進一步開發完成。若OpenCV[19]是二維信息獲取與處理的結晶,則點云庫在三維信息獲取與處理上具有同等地位。
PCL將三維重建和點云數據處理中所有常見功能整合在一起,保證了算法緊湊性和結構清晰性,提高了算法代碼簡潔性[20]。PCL功能如圖1所示。

圖1 PCL功能模塊
PCL模塊功能[21]包括:① Common模塊包含常用庫,提供常用函數;②Filters模塊,去除噪音點,為特征提取等過程提供過濾器;③Features模塊,實現邊界點估計, 計算NARF描述子等;④ Keypoints模塊,實現關鍵點提取,決定在何處提取特征描述符;⑤Registration模塊,實現點云的配準方法;⑥Kd-tree模塊,實現基于FLANN的KD樹最近鄰搜索;⑦Oc-tree模塊,實現基于八叉樹最近鄰搜索;⑧Segmentation模塊,實現點云分割提取;⑨ Sample Consensus模塊,對點云進行擬合;⑩Surface模塊,實現表面重建技術;Range Image模塊,深度圖,由Kinect獲取后可轉換為點云;IO模塊,實現PCD (Point Cloud Data) 文件的讀寫和數據輸入輸出;Visualization模塊, 實現基于VTK依賴庫的三維可視化。
本文編譯環境為Microsoft Visual Studio 2010,操作系統分別是32位Windows 7和64位 Windows 10,不適用于其它編譯環境。
2.1.1 預編譯包介紹
預編譯包是一個集成了PCL中第三方依賴庫的安裝包,因依賴庫被提前編譯過,安裝后即可直接使用。
為方便初學者在最短時間內體驗到PCL的強大功能,PCL官方網站為Windows用戶提供了經典PCL 1.6.0版本及其相應PDB(程序數據庫)文件下載。適合該版本PCL的運行系統是編程兼容性最強的Windows7(32位)操作系統。PCL預編譯包如圖2所示。

圖2 PCL預編譯包
2.1.2 預編譯包安裝
安裝預編譯包時,需要注意運行版本的選擇,否則安裝時系統可能因不兼容而報錯。因為預編譯包中的OpenNI版本老舊,所以為保證能在PCL配置完成后,順利通過外接設備(Kinect)獲得包含點距離信息的深度圖像,需要另外安裝最新的OpenNI(開放式自然交互)相關組件。本文選擇安裝的32位PCL1.6.0版本安裝包以及OpenNI相關組件如下所示:
PCL-1.6.0-AllInOne-msvc2010-win32.exe
OpenNI-Win32-1.5.4-Dev.msi
Sensor-Win-OpenSource32-5.1.0.msi
安裝預編譯包時選好安裝路徑,推薦選擇默認的3個安裝包安裝目錄,以便系統自動設置環境變量及安裝路徑,然后按照指示完成安裝。預編譯包及相關組件安裝完成后,手動下載圖2顯示的PDB(程序數據庫)文件,再解壓到預編譯包安裝目錄的“bin”文件夾下。
完成以上操作后,需要對OpenNI進行運行測試。運行安裝目錄中的測試程序Ni- Viewer(64).exe,看到圖3所示的影像后,說明OpenNI安裝成功,能夠被PCL調用,可進行下一步工作。

圖3 OpenNI運行示例
2.1.3 環境變量設置
一般情況下,預編譯包安裝完成后,系統變量會被自動設置,如果沒有,可以手動添加。在系統變量里添加“PCL_ROOT:(你的PCL的安裝路徑)”,在系統變量Path里加入:%PCL_ROOT%in。
2.1.4 包含目錄設置
本文PCL安裝在C盤。首先,在VS新建一個項目,在屬性管理器中找到VC++的包含目錄,添加第三方依賴庫頭文件夾路徑。第三方依賴庫“include”頭文件夾可在PCL安裝目錄中“3rdParty”文件夾中找到,見圖4。

圖4 頭文件路徑添加
2.1.5 庫目錄設置
在新建項目的屬性管理器中找到VC++選項,在其庫目錄中添加 C:Program Files PCL 1.6.0lib等第三方依賴庫靜態鏈接庫的路徑。第三方依賴庫“lib”庫文件夾也可在PCL安裝目錄的“3rdParty”文件夾中找到,見圖5。

圖5 庫文件路徑添加
2.1.6 附加依賴項設置
添加附加依賴項,將本文安裝的幾個第三方依賴庫靜態鏈接庫名稱全部添加到“工程屬性頁→鏈接器→輸入項”中,見圖6。第三方依賴庫靜態庫可以在相應安裝目錄下的“lib”文件夾中找到。

圖6 靜態庫添加
由于需要添加靜態鏈接庫的數量過多,所以無法一一列舉,只能以截圖的方式顯示部分添加的靜態鏈接庫,見圖7。需要添加的靜態鏈接庫數量為199個,圖7展示的只是其中的22個,其余靜態庫未被展示。

圖7 部分靜態鏈接庫
本文推薦利用第三方庫編譯包從源碼搭建PCL,雖然沒有利用PCL預編譯包直接安裝的便捷,但比手動編譯第三方依賴庫和源代碼簡單、省時。這種配置方法一方面繼承了源碼搭建的優點——既可了解源代碼編譯工作原理和過程,另一方面又克服了預編譯包只能安裝特定PCL版本的缺點,能夠在允許范圍內隨意切換PCL源代碼版本進行編譯,隨時補充和更新PCL功能。
2.2.1 第三方依賴庫安裝
搭建過程必備的第三方依賴庫有:用于共享指針和線程的Boost(C++半標準庫)[22];用作SSE優化數學的矩陣后端Eigen(矩陣類庫)[23];基于KD樹中的快速近似最近鄰搜索的FLANN(近似最近鄰搜索庫);用于三維點云渲染和可視化的VTK(可視化工具包)[24]。
另外,可以選擇性安裝的依賴庫有:用于曲面上凸凹殼分解的QHull(計算幾何庫);OpenNI (RGB-D傳感器庫);具有圖形用戶界面的應用程序Qt。
第三方依賴庫有多個版本,需要選擇跟操作系統、編譯環境和PCL相匹配的版本,才能保證PCL順利配置。本文系統環境參數包括:①操作系統,64位Windows 10;②編譯環境包括Microsoft Visual Studio 2010(提供Kinfu模塊);③第三方依賴庫,如圖8所示。

圖8 第三方依賴庫
2.2.2 源代碼編譯
首先獲取PCL源代碼。源代碼版本眾多,到目前為止已經更新到PCL 1.8.1,源代碼可從GitHub官方網站下載。圖9為本文下載到的多個PCL版本。

圖9 源代碼的幾個不同版本
運行CMake - GUI(見圖10)應用程序,點擊“Configure(配置)”按鈕。

圖10 CMake - GUI用戶界面
本文使用Microsoft Visual C++ 2010編譯器,構建32位PCL,可選擇“Visual Studio 10”生成器;構建64位PCL,可選擇“Visual Studio 10 Win64”。本文選用64位PCL。
選擇生成器后,點擊Finish關閉對話框窗口。CMake將開始配置PCL并查找其依賴庫。CMake在尋找依賴庫時會出現多種找不到路徑的情況,需人工幫助尋找。
對PCL源代碼進行Configure和 Generate,然后打開CMake生成的VS2010解決方案進行編譯即可,對ALL-BUILD和INSTALL各Debug和Release編譯一次。Debug生成的是調試版本的程序,使用者可隨時對程序代碼進行調試修改;Release生成的是完美編譯后封裝好的程序,無法進行調試。建議后續使用過程中使用Release版,在使用過程中不會影響程序代碼。對所有項目進行編譯需約半小時的時間消耗。
2.2.3 環境變量設置
在操作系統環境變量里添加系統變量。添加過程與預編譯包系統變量添加過程相同。
2.2.4 工程目錄及依賴項添加
在VS2010新建項目中的屬性管理器里添加包含目錄、庫目錄和依賴項,添加過程同預編譯包工程目錄和依賴項的添加過程。
本文選擇Linux運行平臺版本為Ubuntu16.04。
首先,打開Ubuntu終端,下載第三方依賴庫,命令行代碼見圖11。

圖11 安裝第三方庫命令行代碼
在Ubuntu終端逐行輸入圖11中的命令并運行,在保證每一個依賴庫安裝成功后,才可進行后續操作。
從Linux社區下載源代碼,其命令行代碼見圖12。

圖12 源代碼下載命令
源代碼文件218.43M,包含106 789個子文件。下載過程耗時較長,見圖13。

圖13 源代碼下載
完成安裝依賴庫和下載源代碼兩個準備工作后,可開展編譯源代碼。按照圖14中的5句命令逐一輸入終端并運行,即可進行源代碼編譯。

圖14 編譯源代碼
經過安裝依賴庫、下載源代碼和編譯源碼步驟后,Linux平臺PCL安裝成功,如圖15、圖16所示。

圖15 安裝好的PCL模塊

圖16 PCL配置成功
4.1.1 FLANN 特征緊鄰像素匹配
近鄰搜索問題在圖像識別和數據分析等各種應用中具有重要意義。但是,沒有一種算法比標準的蠻力搜索能更好地在高維度空間中解決該問題。Muja & Lowe[25]于2009年提出了基于K均值樹[26]或KD樹[27]搜索的FLANN算法,該算法可以根據數據集或點云分布特點推薦建立索引類型。FLANN (近似最近鄰快速庫)是用C++編程語言編寫、用于執行快速近似最近鄰搜索的庫。同時,FLANN算法在高維空間最近鄰查找中不會受到局部敏感哈希[28]影響。該算法運用的特征空間是向量空間Rn(n維),其重點在于使用歐幾里得距離[29]找到目標點鄰近點。特征點g和特征點k的特征分向量可以分別記為Dg和Dk,歐氏距離d(g,k) 可以表示為:
d(g,k) =
(1)
本文首先利用 KD樹將二維圖像數據點劃分為幾個特定部分,目的是在KD樹結構中尋找與目標點距離最近的歐氏距離。將所有檢索到的歐氏距離d(g,k)通過KD樹存儲,然后可有效搜索到與目標點距離最近的點。整個搜索過程是一個自上而下的遞歸過程,將查詢點和分割點的值進行循環比較,判別查詢點在左區域還是右區域,再進行循環和對應分割點比較,直到搜索成功為止。
4.1.2 SIFT匹配算法
Lowe[[30]于2004年提出了一種具有劃時代意義的高效局部特征算法—SIFT(Scale Invariant Feature Transform)算法。在不同尺度空間中尋找特征點進行描述,最后進入算法核心的匹配環節。因此可以將SIFT算法概括成以下步驟(見圖17):

圖17 SIFT算法流程
(1)搜索特征點。根據尺度空間理論[[31],在圖像多尺度空間中尋找并確認每一個尺度空間里對應極值點,獲得極值點所在位置的像素坐標,這些坐標包含備選特征點位置信息。剔除低對比度的極值點和易受噪聲干擾的備選特征點,得到被篩選過的特征點集。
(2)詳細描述提取的特征點。對特征點的鄰域進行梯度加權計算,得到對應的鄰域梯度幅度值和方向,利用直方圖方法獲取每個鄰域梯度主幅度值和主方向;然后再通過計算得到以該特征點為中心像素點的梯度主幅度值和主方向,利用特征描述向量描述該特征點。
(3)關鍵點匹配。對于兩個匹配特征點存在最鄰近匹配對與次鄰近匹配對,將最鄰近歐式距離與次鄰近歐式距離進行相比,若比值小于某一設定閾值則為正確匹配。最后采用RANSAC算法[ [32]對點對進行進一步優化。
4.1.3 實驗過程
利用Kinect獲取兩張RGB圖像(見圖18、圖19),作為初始輸入圖像。

圖18 RGB1

圖19 RGB2
圖19是彩色攝像機在圖18的視角基礎上向右平移后拍攝的圖像。
首先,使用SIFT算法,利用關鍵點周圍的像素,計算關鍵點描述子以便對關鍵點進行描述,計算參數為關鍵點半徑及角度。特征描述子不是單純的標量,還是一個矩陣,一個特征向量為一行。當兩個特征點越相似,其描述子也越相似。圖20是對初始RGB1圖像進行特征描述子計算后的輸出圖像。

圖20 RGB1特征描述子選取

圖21 特征描述子粗匹配
然后,使用FLANN搜索匹配算法對已經計算出來的特征描述子進行匹配(見圖21)。經過對關鍵點特征描述子粗匹配后,總共得到620對匹配點對。從結果可以看出,僅依靠描述子匹配得到的結果繁多,且把許多并不相似的點對也進行了匹配。
針對不相似點對過多的問題,本文首先進行一次篩選,去除第一類誤匹配情況,即去掉相距距離太大的點對。篩選原則是去掉大于4倍最小距離的點對。經過一次剔除處理,錯誤的匹配對明顯減少(見圖22),與圖21特征描述子粗匹配相比,輸出的圖像干凈整潔了許多,處理后的關鍵點特征匹配點對驟降為128對。第一次篩選處理剔除了492對無關匹配,降低了后續處理的工作量,節約了時間。

圖22 一次處理后匹配點對

圖23 二次處理得到的特征點對
通過細致觀察可以發現,兩個RGB源圖像之間只發生了水平方向旋轉,所以正確的匹配線應該是水平的,非水平匹配線為誤匹配。圖22顯示出匹配點對存在個別錯誤的匹配。針對出現的第二類誤匹配情況,可以利用PCL的RANSAC算法進行二次篩選處理(見圖23)。
經過二次處理,得到圖23的結果。剔除了第二類誤匹配情況后,得到了一幅含有16對特征匹配點對的圖像,二次處理去掉了112對誤匹配點對。通過觀察表1以及圖23可以發現,利用PCL的RANSAC算法可以得到一個數量適中且較為準確的關鍵點特征匹配結果,并且極大降低了誤匹配率。

表1 匹配點對處理結果對比
但在圖23中,特征點對仍有2對誤匹配,這是由于兩幅RGB源圖中的關鍵點特征描述子過于相似導致的。針對圖23中出現的第三類誤匹配情況,還需要后續通過調整關鍵點搜索匹配算法、細化篩選處理標準以及相關參數解決該問題,以得到更好的匹配結果。
4.2.1 點云實時抓取
通過調用PCL中輸入輸出模塊(IO)的抓取函數和可視化模塊(Visualization)的點云查看函數,實現外接設備通過第三方接口與編譯環境的連通,完成對空間物體的實時點云化處理與顯示(見圖24)。

圖24 點云實時顯示

圖25 PCD文件讀取
4.2.2 點云文件讀取與初步重建
點云數據以PCD(Point Cloud Data)文件(見圖25)為常用載體進行儲存,PCD的內容以ASCII碼的形式展現,方便計算機寫入與讀取。
由未經后期處理的原始點云數據重建成的三維空間圖像如圖26所示。從圖中可以看出,重建的空間模型大致輪廓存在,但是紋理信息缺失,而且還有嚴重的數據丟失,導致重建模型圖并不完整。

圖26 三維重建圖像
本文在Windows及Linux系統下完成了PCL搭建,指出了配置過程中應注意的多個事項,為尚在PCL環境搭建初學者提供了有效參考。同時,在采用傳統SIFT特征點提取算法的基礎上,結合FLANN搜索匹配算法對特征點進行匹配,降低了誤匹配率,取得了很好的實驗結果,但是仍存在數量較小的誤匹配,這也是今后研究中需要解決的問題。另外,重建模型紋理細節還不夠明顯,需要后期進一步優化。