PCL點雲濾波去噪

爲什麼要對點雲濾波?

一般下面這幾種情況需要進行點雲濾波處理:
(1)  點雲數據密度不規則需要平滑
(2) 因爲遮擋等問題造成離羣點需要去除
(3) 大量數據需要下采樣
(4) 噪聲數據需要去除

     點雲中的噪聲點對後續操作的影響比較大。就像蓋房子一樣,地基有很多瑕疵,如果不加以處理最終可能會導致整個房子坍塌的。不過別擔心,PCL中有一個專門的點雲濾波模塊,可以將噪聲點去除,還可以進行點雲壓縮等操作,非常靈活實用,例如:雙邊濾波,統計濾波,條件濾波,隨機採樣一致性濾波等。這樣才能夠更好的進行配準,特徵提取,曲面重建,可視化等後續應用處理。PCL中關於點雲濾波的所有函數都在這裏:

http://docs.pointclouds.org/trunk/group__filters.html

一般來說,濾波對應的方案有如下幾種:
(1)按照給定的規則限制過濾去除點
(2) 通過常用濾波算法修改點的部分屬性
(3)對數據進行下采樣

1.點雲下采樣:

      點雲的數目越大,儲存、操作都是個大問題!通過按一定的規則從裏面抽取有代表性的樣本,可以代替原來的樣本,節省計算開銷,這個下采樣PCL中有專門的類,叫做

class  pcl::ApproximateVoxelGrid< PointT >

       比較適合對海量的點雲在處理前進行數據壓縮,而且可以在特徵提取等處理中選擇合適的體素(voxel)大小等參數,提高算法效率。該函數對輸入的點雲數據創建一個三維體素柵格,每個體素內用體素中所有點的重心來近似顯示體素中其他點,這樣該體素內所有點都用一個重心點最終表示。它的優點是可以在下采樣的時候保存點雲的形狀特徵。

關鍵代碼:

  1. pcl::VoxelGrid<PointT> downSampled; //創建濾波對象
  2. downSampled.setInputCloud (cloud); //設置需要過濾的點雲給濾波對象
  3. downSampled.setLeafSize (0.01f, 0.01f, 0.01f); //設置濾波時創建的體素體積爲1cm的立方體,三個參數表示體素柵格葉大小,分別表示體素在XYZ方向的尺寸
  4. downSampled.setDownsampleAllData(bool downsample)//設置是否對所有的字段進行下采樣
  5. downSampled.filter (*cloud_downSampled); //執行濾波處理,存儲輸出

setDownsampleAllData的意思是:點雲有不同的類型,比如 PointXYZ,有的是PointXYZRGB,還有其他類型,也就是一個點包含多種不同信息,比如空間位置XYZ,顏色信息RGB,或者強度信息等,如果想要對所有信息(字段)下采樣則設置爲true,只對XYZ下采樣的話設置爲false。下采樣結果如下圖所示。

2.去除點雲的離羣

       離羣點對應的英文是outliers,也叫外點,就是明顯偏離“羣衆”的點,比如我們用激光掃描一面平坦的牆壁,正常情況下得到的應該是差不多也位於同一個平面的點雲,但是由於設備測量誤差等原因,會產生少量脫離羣衆的空間點,離本來的牆壁過遠,我們就叫這部分點爲離羣點。離羣點會使局部點雲特徵(如表面法線或曲率變化)的估計複雜化,從而導致錯誤的值,從而可能導致點雲配準失敗。列舉兩個常用的去除離羣點的類:StatisticalOutlierRemoval 、RadiusOutlierRemoval

2.1   StatisticalOutlierRemoval 

    顧名思義,使用統計分析技術,從一個點雲數據中集中移除測量噪聲點。對每個點的鄰域進行統計分析,剔除不符合一定標準的鄰域點。具體來說:

1.對於每個點,計算它到所有相鄰點的平均距離。假設得到的分佈是高斯分佈,我們可以計算出一個均值 μ 和一個標準差 σ;

2.這個鄰域點集中所有點與其鄰域距離大於   μ + std_mul * σ   區間之外的點都可以被視爲離羣點,並可從點雲數據中去除。std_mul 是標準差倍數的一個閾值,可以自己指定。

  1. pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //創建濾波器對象
  2. sor.setInputCloud (cloud); //設置待濾波的點雲
  3. sor.setMeanK (50); //設置在進行統計時考慮的臨近點個數
  4. sor.setStddevMulThresh (1.0); //設置判斷是否爲離羣點的閥值,用來倍乘標準差,也就是上面的std_mul
  5. sor.filter (*cloud_filtered); //濾波結果存儲到cloud_filtered

     如上代碼所示,先創建統計分析濾波器,然後設置濾波器輸入是 cloud,也就是我們待處理的點雲,然後設置對每個點分析的臨近點的個數設置爲50 ,並將標準差的倍數設置爲1,  這意味着如果一個點的距離超出了平均距離加上一個標準差以上,則該點被標記爲離羣點,並將它移除。最後統計分析濾波後,輸出的結果就是cloud_filtered。

2.2  RadiusOutlierRemoval

      一個比較簡單常用的方法就是根據空間點半徑範圍臨近點數量來濾波,對應的類名是 RadiusOutlinerRemoval,這個很容易理解,它的濾波思想非常直接,就是在點雲數據中,設定每個點一定半徑範圍內周圍至少有足夠多的近鄰,不滿足就會被刪除。比如你指定了一個半徑d,然後指定該半徑內至少有1個鄰居,那麼下圖中只有黃色的點將從點雲中刪除。如果指定了半徑內至少有2個鄰居,那麼黃色和綠色的點都將從點雲中刪除。

                                                 

  1. pcl::RadiusOutlierRemoval<pcl::PointXYZ> pcFilter; //創建濾波器對象
  2. pcFilter.setInputCloud(cloud); //設置待濾波的點雲
  3. pcFilter.setRadiusSearch(0.8); // 設置搜索半徑
  4. pcFilter.setMinNeighborsInRadius(2); // 設置一個內點最少的鄰居數目
  5. pcFilter.filter(*cloud_filtered); //濾波結果存儲到cloud_filtered

2.3  FastBilateralFilter、BilateralFilter

       雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合圖像的空間鄰近度和像素值相似度的一種折中處理,同時考慮空域信息和灰度相似性,達到保邊去噪的目的。具有簡單、非迭代、局部的特點 。雙邊濾波器的好處是可以做邊緣保存。先簡要介紹圖像的雙邊濾波:

    該算法是針對圖像的空間域(spatial domain)和像素範圍域(range domain),所以在設計的時候就會有兩個權重,Ws和Wr,那麼公式就可以簡單的理解爲:

                                         
p爲當前點,之所以是向量,因爲有時候圖像不只是灰度圖像,也有三色圖像,所以用向量表示p的多維空間,I則爲圖像,Ip就是表示圖像I的p點,S爲p的鄰域集,q是鄰域中的一個點,BF則爲輸出的圖像。

                                                
σs和σc分別爲空域濾波權值函數的標準差和像素相關性權值函數的標準差。

     雙邊濾波的權重是ws和wr的乘積。對於ws來說,這就是普通的高斯濾波函數,其代入的座標,sigmas是程序輸入值,該函數是在空間臨近度上計算的。而wr是計算像素值相似度(顏色空間)。

    當圖像在變化程度平緩的區域時,鄰域中的像素值(RGB值)差距相差不大。此時wr無限接近於1,因此此時的雙邊就是普通的高斯濾波,達到對圖像平滑的效果,如左圖。

    當圖像在變化程度劇烈的區域,比如在邊緣區域時,鄰域中的像素值(RGB值)差距相差很大。此時wr朝0值趨近,顏色差值越大,wr越逼近0,最終整個式子的值逼近於0。最終的結果是權值爲0。因此在最終計算時,該處將不影響輸出值,如右圖。

                          
通過此種方式,其既能平滑圖像,又保持了圖像的邊緣。

      對於雙邊濾波不只用在圖像,很多時候也會在處理點雲數據的時候使用,對點雲數據進行光滑處理。雙邊濾波算法主要用於對點雲數據的小尺度起伏噪聲進行平滑光順。雙邊濾波應用於三維點雲數據去噪,既有效地對空間三維模型表面進行降噪,又可以保持點雲數據中的幾何特徵信息,避免三維點雲數據被過渡光滑。在點雲模型中設點p的k鄰域點集及單位法向量分別爲N_{K}n_{i} ,雙邊濾波可以定義爲:

                                                

                    

                             

    WC,WS 分別表示雙邊濾波函數的空間域和頻率域權重函數,它們分別控制着雙邊濾波的平滑程度和特徵保持程度。<n,pj-pi>爲n與pj-pi的內積,n_{j}n_{i} 爲點 的法向量。

                      

   舉一個極端的例子,如果對一條直線上的點進行雙邊濾波,因爲每個點的法向量都相同,則<n_i,n_j>-1接近於0,即y因子接近於零,此時最大值<n_i,p_j-p_j>因爲垂直,所以等於0,即最終雙邊濾波因子\lambda =0。這種結果是滿足實際的。

  1. pcl::PointCloud<pcl::PointXYZ>::Ptr xyz (new pcl::PointCloud<pcl::PointXYZ>);
  2. pcl::FastBilateralFilter<pcl::PointXYZ> fbf;
  3. fbf.setInputCloud (xyz);
  4. fbf.setSigmaS (sigma_s);//設置雙邊濾波器用於空間鄰域/窗口的高斯的標準偏差
  5. fbf.setSigmaR (sigma_r);//設置高斯的標準偏差用於控制相鄰像素由於強度差異而下降多少(在我們的情況下爲深度)
  6. pcl::PointCloud<pcl::PointXYZ> xyz_filtered;
  7. fbf.filter (xyz_filtered);

    注意:能使用雙邊濾波的點雲必須得包含強度字段。現有的points類型中,只有PointXYZI和PointXYZINormal有強度信息。FastBilateralFilter只適用於有序點雲。

from:https://mp.weixin.qq.com/s/9pxff6LwcecDHsx4kI34sw

2.4、基於點雲頻率的濾波方法

點雲的頻率: 點雲和圖像一樣,有可能也存在頻率的概念。點雲表達的是三維空間中的一種信息,這種信息本身並沒有一一對應的函數值。故點雲本身並沒有在講訴一種變化的信號。但點雲存在某種空間關係。我們可以人爲的指定點雲空間中的一個點,基於此點來討論點雲在各個方向上所謂的頻率。

  在傳統的信號處理中,高頻信號一般指信號變化快,低頻信號一般指信號變化緩慢。在圖像處理中,高低頻的概念被引申至不同方向上圖像灰度的變化,傅里葉變換可以用於提取圖像的週期成分濾除布紋噪聲。在點雲處理中,定義:點雲法線向量差爲點雲所表達的信號。換言之,如果某處點雲曲率大,則點雲表達的是一個變化的信號。如果點雲曲率小,則其表達的是一個不變的信號。這和我們的直觀感受也是相近的,地面曲率小,它表達的信息量也小;人的五官部分曲率大,其表達了整個Scan中最大的信息量。

DoN算法

  點雲頻率的思想已經被廣泛的應用在了各個方面,最著名的莫過於DoN算法。DoN算法被作者歸類於點雲分割算法中,本質上DoN只是一種前處理,應該算是一種比較先進的點雲濾波算法。分割本質上還是由歐式分割算法完成的。DoN 是 Difference of Normal 的簡寫。算法的目的是在去除點雲低頻濾波,低頻信息(例如建築物牆面,地面)往往會對分割產生干擾,高頻信息(例如建築物窗框,路面障礙錐)往往尺度上很小,直接採用 基於臨近信息 的濾波器會將此類信息合併至牆面或路面中。所以DoN算法利用了多尺度空間的思想,算法如下:

  1. 在小尺度上計算點雲法線1
  2. 在大尺度上計算點雲法線2
  3. 法線1-法線2
  4. 濾去3中值較小的點
  5. 根據第三步得到的法線差,進行歐式分割

  顯然,在小尺度上是可以對高頻信息進行檢測的,此算法可以很好的小尺度高頻信息。其在大規模點雲(如LiDar點雲)中優勢尤其明顯。

PCL實現參見博客:https://www.cnblogs.com/ironstark/p/5010771.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章