結構化的室內場景建模_輸入數據

  • 2019 年 10 月 7 日
  • 筆記

上篇文章對 Structured Indoor Modeling 這篇論文做了介紹。該文章在學術上和工業上都有充分的應用,而且這也是我的博士課題,我對這一領域了解非常充分。所以在後續的文章中,我將極其詳細的講解這篇論文。

對於任何一個演算法,我們首先應該知道該演算法的輸入是什麼。Structured Indoor Modeling 輸入一個場景的全部點雲。該論文網站開放了部分數據,我也下載下來了。看一下其中一組數據。

畫面右端輸入的是使用 Matterport 設備拍攝的 全景 RGB-D 影像。可以看到畫面左端把點雲逐個拼起來的過程,在我的程式中處理的就是這組數據。

Matterport 拍攝的過程如下。

客戶在一個三腳架上架上 Matterport 這個設備。然後 Matterport 原地旋轉 360 度,拍攝一張 全景 RGB-D 圖片。

我們可以看到 Matterport 的構造,由三個深度攝影機組成,關於深度攝影機的介紹,我在之前的文章中介紹了目前最好的深度攝影機 Azure Kinect

深度攝影機 Azure Kinect 介紹 無雨森,公眾號:無雨森的技術分享KinectAzureDK編程實戰_用OpenCV、PCL操作和可視化Kinect數據

這三個攝影機分別拍攝上中下的場景,讓每次拍攝都能覆蓋到整個場景。

如上Gif,這是一張 全景 RGB-D 圖片轉成的點雲。

類似於這種多個深度攝影機構成的模組,我們需要標定這幾個攝影機之間的相對姿態。每次拍攝,只需要把這三個深度攝影機的點雲拼接起來即可。關於如何標定相對姿態,請看我之前發表的文章。

標定多組深度攝影機 無雨森,公眾號:無雨森的技術分享KinectAzureDK編程實戰_實時雙Kinect標定

該論文開放的數據是用文本格式保存的 ply 文件。

ply  format ascii 1.0  comment created by MATLAB plywrite  element vertex 309156  property int height  property int width  property float x  property float y  property float z  property uchar red  property uchar green  property uchar blue  property float nx  property float ny  property float nz  property uchar intensity  end_header  0 0 0 0 0 0 0 0 0 0 0 0 [The camera position (XYZ in the global coordinate system)]  1 1 -22.3002 6.98361 1148.76 0 0 0 -0.0305268 0.09118 -0.995366 135 [1x2 u-v pixel index on the panorama] [1x3 3-d coordinate] [1x3 RGB color] [1x1 sensir intensity]  2 1 -20.0256 2.51624 1148.82 0 0 0 0.0422516 -0.0506529 -0.997822 135 [same as above]  3 1 -17.7198 -1.94781 1146.86 0 0 0 0.0557792 -0.0773581 -0.995442 136  4 1 -15.4755 -6.41863 1148.88 0 0 0 0.0735129 -0.112192 -0.990964 137  .....

如上為 ply 中保存的格式。我們一行一行的看。

ply  format ascii 1.0  comment created by MATLAB plywrite

這幾行表示這裡的 ply 文件是用文本格式保存的,而且是由 Matlab 的 plywrite 函數輸出的。

element vertex 309156

這一行表示該 ply 文件中包含 309156 個點。

property int height  property int width  property float x  property float y  property float z  property uchar red  property uchar green  property uchar blue  property float nx  property float ny  property float nz  property uchar intensity

這裡說明的是 ply 中保存的每一行數據包含的內容。每一行表示每一個三維點。每個三維點包含如上這些資訊:全景 RGB-D 中的像素位置 (px, py),三維坐標 (x, y z),顏色資訊 (red, green, blue),法向量資訊 (nx, ny, nz),光亮強度值 intensity(深度攝影機需要發出紅外光斑,這是紅外接收器捕捉到的場景的紅外光亮強度)。

0 0 0 0 0 0 0 0 0 0 0 0 [The camera position (XYZ in the global coordinate system)]  1 1 -22.3002 6.98361 1148.76 0 0 0 -0.0305268 0.09118 -0.995366 135 [1x2 u-v pixel index on the panorama] [1x3 3-d coordinate] [1x3 RGB color] [1x1 sensir intensity]  2 1 -20.0256 2.51624 1148.82 0 0 0 0.0422516 -0.0506529 -0.997822 135 [same as above]  3 1 -17.7198 -1.94781 1146.86 0 0 0 0.0557792 -0.0773581 -0.995442 136  4 1 -15.4755 -6.41863 1148.88 0 0 0 0.0735129 -0.112192 -0.990964 137  .....

這裡是最開始的那幾個點。最重要的是,第一個點表示這個 ply 標識的點雲獲取設備所在的世界坐標系的位置,這裡是 (0, 0, 0)。不要誤以為這裡沒有標定好,其實別的點雲的第一行數據可能是。

0 0 -1003.92 1635.75 -4.43258 0 0 0 0 0 0 0

另外,還需要說的是。Matterport 拍攝的點雲是可以映射為一張 2D 的 全景 RGB-D 影像。

這是其中一個點雲映射回全景彩色影像。剛才我們說到每一行數據都包含全景 RGB-D 中的像素位置 (px, py),根據這個像素位置就可以將點雲映射回全景彩色影像。

熟悉 PCL 的小夥伴一定想到這不就是一個 organized 點雲嗎?關於 organized 點雲,不熟悉的小夥伴可以看這篇 PCL 的官方文章。

Introduction to the organized point cloud http://pointclouds.org/documentation/tutorials/basic_structures.php#id11

organized 點雲是可以映射為一張 2D 影像的點雲。常見於深度攝影機的點雲,每一張 RGB-D 影像都對應一個點雲。這樣的點雲就是 organized。

在 PCL 中,organized 點雲可以用更多更好的演算法來處理。比如用 Bilateral Filter 對點雲做過濾。

在我對這篇論文的實現過程,我使用 PCL 來處理點雲。雖然 PCL 支援很多點雲格式,但像這樣包含這麼多資訊的數據格式,PCL 還無法支援。其實我們只需要按照 PCL 的程式碼自己聲明一個數據格式即可。詳情請見這篇文章。

Adding your own custom PointT type http://pointclouds.org/documentation/tutorials/adding_custom_ptype.php#adding-custom-ptype

namespace pcl  {      struct PointXYZRGBINormal;  }  #include "PointXYZRGBINormal.hpp"    POINT_CLOUD_REGISTER_POINT_STRUCT(pcl::PointXYZRGBINormal,      (float, x, x)      (float, y, y)      (float, z, z)      (float, normal_x, normal_x)      (float, normal_y, normal_y)      (float, normal_z, normal_z)      (uint32_t, rgba, rgba)      (float, intensity, intensity)      (float, curvature, curvature)  )

這是我聲明的僅適用於這樣格式的點雲的數據類型。

PCL 的類、函數都是用 C++ 模板寫的,我們只需要用這個數據格式,就可以使用絕大部分 PCL 函數來處理該點雲。

但是,每次調試程式,都要把文本格式的點雲輸入到記憶體中,像我用的這組數據每次都要載入到記憶體中需要耗時 20 秒 左右。這對經常調試演算法的我來說是無法忍受的。

為了加快載入速度。我對這些文本格式的點雲做預處理。把文本格式的點雲 ply 文件,轉換為 PCL 獨有的 PCD 格式,並且壓縮為二進位格式的 pcd 文件。經過我的測試,每次載入這接近 1 G 的點雲文件只需要 2~3 秒即可。而且這 2~ 3秒包含了 「提取文件」,「解壓文件」兩個過程。

後續文章,還要對這組數據進行初步的過濾,按照論文提供的過濾方法,我寫了幾個繼承於 PCL 的 Filter 的點雲過濾工具類。