本文提綱

先熱熱身

點雲是啥

你知道點雲優缺點嗎?

點雲庫PCL:開發者的福音

PCL安裝指北

炒雞簡單的PCL實踐

留個作業再走

先熱熱身

小白:hi,師兄,好久不見

師兄:師妹好,上週單應矩陣作業做了嗎?小白:嗯,做了,這個單應矩陣真的挺有意思的。作業之外,我發現了一個新技能。。。師兄:什麼技能?小白:我發現很多網上流傳的圖片都可以用上次我學過的單應矩陣實現,你看這張圖,我第一次看到還以為是真的

現在知道這不就是我們上節課講的單應矩陣的變換嗎?

果然我在網上找到了原圖

現在我也會用OpenCV裏的單應函數做這樣的圖了~

師兄:哈哈,厲害了,會學以致用了。話說回來,今天有啥想問的?

小白:嗯,最近在看點雲相關的,師兄要不給我掃掃盲吧?師兄:這個我也有些瞭解,就把我知道的給你說說吧小白:yeah,師兄最棒!

點雲是啥

師兄:那我就當你是個小白吧,從點雲的定義說起。點雲的英文是「point cloud」,點雲的意思和它的名字一樣,就是一堆點的集合,看起來像是一坨「雲」。

小白:一坨。。。

師兄:哦,一坨不太文雅,應該是像一片「雲」一樣。上面只是一種形象的說法,其實點雲在編程實現的時候是一種數據結構,用來表達多維空間中點的集合,這個多維空間一般對我們來說是三維空間。

小白:哦,原來如此,也就是我們所在的 XYZ 空間咯

師兄:對,因此點雲在三維相關的領域內用的很多,比如三維掃描,三維重建、三維感知等方面。

小白:那點雲是怎麼得到的啊?師兄:一般是通過三維成像感測器得到的,比如雙目相機、三維掃描儀、RGB-D相機等,除了可以用這種特殊的硬體得到,也可以用計算機合成。

小白:嗯嗯,師兄說了這麼多,還是沒有一個直觀的印象,這個點雲到底長什麼樣?

師兄:想要直觀一點的話,我直接給你看點雲圖吧,你看下面就是室外一個街道的點雲圖,遠看能看清房子,樹木的輪廓啊

小白:嗯嗯,確實能看出輪廓出來,不過不像是我們平時拍的照片,這個點雲好像看著不是很清楚哎!

你知道點雲優缺點嗎?

師兄:確實是這樣的,這也是點雲的一個缺點吧

小白:那師兄能否順便說說,這個點雲的表達有啥優缺點呢?師兄:這個問題問的有水平,額,我想想,我先說說優點吧。

第一個優點就是可以表達物體的空間輪廓和具體位置,比如上面這個圖,我們能看出來街道的樣子,房屋的形狀,距離攝像機的距離也是知道的。

第二個優點我覺得就是,點雲本身和視角無關,也就是你可以任意旋轉,可以從不同角度和方向觀察一個點雲,而且不同的點雲只要在同一個坐標系下就可以直接融合,還是很方便的。

至於缺點嘛,我們先來放大一下點雲看看。如下圖所示,如果拉近一直放大最後看到的就是一個個的點。也就是空間中成千上萬的點組成了一個點的集合,他們構成了上面的街道房屋等。

小白:這個點雲放大了啥都看不出來啊

師兄:對,這個是點雲的其中一個缺點,那我想想點雲還有哪些缺點哈!

第一個缺點就是點雲並不是稠密的表達,一般比較稀疏,你放大了看,會看到一個個孤立的點。它的周圍是黑的,也就是沒有信息。所以在空間很多位置其實沒有點雲,這部分的信息是缺失的。

第二個缺點嘛,就是點雲的解析度和離相機的距離有關。你離近了看是看不清是個什麼東西的,只能拉的很遠才能看個大概。

點雲庫PCL:開發者的福音

小白:嗯,瞭解了,好像缺點也沒啥影響哈。再問個問題,那這些點雲怎麼顯示和保存啊,感覺點雲很多的話,好像很複雜的樣子。。。

師兄:的確,比如一張 640 x 480 尺寸的深度圖就可以轉換為擁有三十萬個空間點的點雲,大的點雲可能有百萬千萬以上,不過,不用擔心,有一個開源的點雲庫,英文名為Point Cloud Library ,簡稱PCL ,專門用來進行點雲的讀寫,處理等各種操作。

小白:那太好了,這個PCL是誰做的啊?好用嗎?

師兄:這個PCL是由一大批世界範圍內的名校和科技公司合作開發的,你看下面是他們的名字

小白:哇塞,好多不認識啊!不過我看到了ETH,也就是蘇黎世聯邦理工大學,還有TUM,也就是德國慕尼黑工業大學,我看論文經常看到他們學校的,他們都是SLAM領域非常頂級的研究機構呢

師兄:嗯,看來你論文看了不少啊,哈哈。我們繼續說PCL,PCL真的挺方便,支持跨平臺,可以在Windows,Linux,macOS,iOS,Android上部署,可以說非常全了,而且PCL可以分為很多小的庫文件,在非常適合於計算資源有限或者內存有限的應用場景,非常方便移動端開發。

小白:那可以說很通用了哈!對了師兄,那這個PCL都有啥功能?

師兄:功能很豐富了,基本PCL的操作都有,比如讀寫、濾波、特徵估計、表面重建、配準、分割等等,你看這個圖就是PCL的功能啦

小白:嗯嗯,那是不是平時我們操作點雲,調PCL的函數就行了?

師兄:怎麼說呢,其實PCL類似於OpenCV那樣,有很多功能模塊,每個模塊裏有封裝好的函數,你可以調這些函數進行基本處理,但是有些功能PCL裏可能沒有,這時候需要自己寫一些代碼實現。

小白:嗯,師兄,總之就是要多編程實踐啦

PCL安裝指北

師兄:對,那我們開始實踐環節吧,帶著你做一些PCL的基礎編程實現

小白:太好啦!

師兄:首先,我們先來看看點雲庫,也就是PCL的安裝方法,推薦用Linux環節哈,安裝很方便

小白:嗯,我之前聽師兄說Linux環境配置比較簡單,就開始學Linux了,確實,比Windows方便多啦,就是剛開始用命令行不太習慣,好多命令記不住。。。

師兄:沒事的,命令行不用刻意去記,忘記了就去查一下,用多了自然知道了

小白:知道啦!師兄:PCL在Linux下安裝有兩種方式,一種是安裝編譯好的庫,一種是從源碼編譯。你看這個是PCL GitHub上的安裝包,前面幾種是不同環境下的編譯好的庫了,最後的source code就是源碼安裝

小白:那這兩種方式有什麼不一樣的?

師兄:第一種方式比較簡單,幾行命令就可以搞定,比如如果你用的是Ubuntu 16.04版本的Linux系統的話,只需要打開一個終端,輸入

sudo apt-get install libpcl-dev pcl-tools

就可以自動安裝啦,優點是安裝的版本都是穩定版本(當然也比較舊一點),不需要處理依賴關係,安裝非常方便,不過這種安裝方式也有一些缺點。一個是一般安裝的都不是最新的,二是安裝的都是別人已經編譯好的通用的二進位庫,所以不能根據自己的需求進行調整

小白:只要一行代碼確實方便啊!那第二種從源碼安裝的優缺點呢?

師兄:第二種從源碼編譯安裝也沒有麻煩多少,它是把所有的源代碼都下載了下來,所以會佔用較多的存儲空間。但好處很多,比如可以下載最新的版本或者指定的版本,可以根據自己的需求在編譯時進行選擇,可以查看甚至修改某個函數的源代碼等等

小白:感覺都挺好,選擇恐懼症了,不知道該選哪個了。。。

師兄:推薦用第二種吧,從源碼自己編譯安裝,更方便一些小白:好,具體如何操作呢?師兄:首先打開PCL GitHub的網址:github.com/PointCloudLi然後選擇你需要的版本號,如下圖所示

如果沒什麼特殊需要可以不選擇,我們打開一個終端,輸入下面一行代碼

git clone https://github.com/PointCloudLibrary/pcl pcl-trunk

然後PCL 源代碼就 clone 到你的電腦上了

下一步就是Ubuntu下安裝的老一套了,進入目錄,新建一個build文件夾存放編譯的文件,然後進入build文件夾,cmake一下,然後make,最後install,這一系列流程就是下面這段代碼了

cd pcl-trunk && mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
make -j2
sudo make -j2 install

靜靜的等待編譯結束就好啦!

炒雞簡單的PCL實踐

小白:嗯嗯,我照著做一下。。。嗯,編譯好啦,我們開始用PCL寫代碼吧

師兄:那我們來寫一個讀取RGB-D相機的一幀圖像並用PCL轉化為點雲的代碼吧

首先,我們需要定義點雲的結構,我們這裡使用typedef來定義兩個常用的類型

typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloud;

這裡的 pcl::PointXYZRGB 就是我們定義的空間點,它包括空間坐標XYZ以及顏色信息RGB,此外常用的點的 類型還有

pcl::PointXYZRGBA ( 多了一個alpha通道), pcl::PointXYZ (只有空間位置,不包含顏色信息),pcl::PointXYZHSV (空間位置 + HSV顏色空間表示的顏色)等,總之,我們這裡輸入的 RGB-D 圖像就定義為pcl::PointXYZRGB。

小白:師兄,為什麼這裡要用typedef 啊?我看好多地方都這樣寫的

師兄:這樣是為了把那麼長的一個類型用一個簡單的別名 PointT 來代替,不至於代碼顯得特別冗長

小白:這樣啊,懂了,那麼 pcl::PointCloud就是點雲了吧?它裡面可以包含許多類型為PointT的點

師兄:對,我們繼續。其實RGB-D圖像轉換為點雲的方式也簡單,代碼如下

for (int m = 0; m < depth.rows; m++)
for (int n = 0; n < depth.cols; n++)
{
// 獲取深度圖中(m,n)處的值
ushort d = depth.ptr<ushort>(m)[n];
// d 可能沒有值,若如此,跳過此點
if (d == 0)
continue;
// d 存在值,則向點雲增加一個點
PointT p;
// 計算這個點的空間坐標
p.z = double(d) / camera.scale;
p.x = (n - camera.cx) * p.z / camera.fx;
p.y = (m - camera.cy) * p.z / camera.fy;

// 從rgb圖像中獲取它的顏色
p.b = rgb.ptr<uchar>(m)[n * 3];
p.g = rgb.ptr<uchar>(m)[n * 3 + 1];
p.r = rgb.ptr<uchar>(m)[n * 3 + 2];

// 把p加入到點雲中
cloud->points.push_back(p);
}

之所以能這樣寫,前提是 RGB 和 depth圖已經對齊了,也就是 depth 圖中某個位置的深度值在 RGB圖中同樣的位置處就是它對應的顏色。

小白:中間那個計算點的空間坐標好像就是用《從零開始一起學習SLAM | 相機成像模型》的相機成像模型公式的?

師兄:對,所以這裡需要相機內參。然後需要注意的就是OpenCV裏 RGB 圖像裏存儲顏色順序其實是BGR,所以從 RGB中獲取顏色時順序也是 BGR而不是RGB,這裡容易錯。如果沒 問題的話,輸出結果如下,可以在終端裏用pcl_viewer 查看,用滑鼠可以縮放和翻轉查看,如果你放大了就發現是一個個的點。下圖是離的比較遠的結果

小白:嗯,這個看起來挺不錯的,那下一步呢?

師兄:下一步就是多個點雲融合了,這部分我給你變成了作業的形式,你可以自己去編程練習一下,可以利用前面圖像生成點雲的代碼。小白:額,好。。師兄猝不及防啊。。。

留個作業再走

題目:點雲融合實驗。已經給定3幀(不連續)RGB-D相機拍攝的 RGB + depth 圖像,以及他們之間的變換矩陣(以第一幀為參考幀),請將上述3幀RGB-D圖像分別生成點雲並融合出最終的點雲輸出。

練習目的:熟悉PCL的使用,熟悉RGB-D圖像到點雲的轉換過程,掌握簡單的點雲融合方法。

如果不出意外,最終點雲融合結果如下:

本文內容部分參考:PCL官網、半閑居士博客。

師兄提醒:關注「計算機視覺life」微信公眾號,菜單欄回復「點雲」,就能下載代碼框架和數據啦!

歡迎留言討論,更多學習視頻、文檔資料、參考答案等掃描下方二維碼進入知識星球「從零開始學習SLAM」,菜單欄點擊「知識星球」查看星球介紹,快來和其他小夥伴一起學習交流~

相關推薦

從零開始一起學習SLAM | 為什麼要學SLAM?

從零開始一起學習SLAM | 學習SLAM到底需要學什麼?

從零開始一起學習SLAM | SLAM有什麼用?

從零開始一起學習SLAM | C++新特性要不要學?

從零開始一起學習SLAM | 為什麼要用齊次坐標?

從零開始一起學習SLAM | 三維空間剛體的旋轉

從零開始一起學習SLAM | 為啥需要李羣與李代數?

從零開始一起學習SLAM | 相機成像模型

從零開始一起學習SLAM | 不推公式,如何真正理解對極約束?

從零開始一起學習SLAM | 神奇的單應矩陣

零基礎小白,如何入門計算機視覺?


推薦閱讀:
查看原文 >>
相關文章