1. 程式人生 > >PCL點雲濾波去噪

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)大小等引數,提高演算法效率。該函式對輸入的點雲資料建立一個三維體素柵格,每個體素內用體素中所有點的重心來近似顯示體素中其他點,這樣該體素內所有點都用一個重心點最終表示。它的優點是可以在下采樣的時候儲存點雲的形狀特徵。

關鍵程式碼:

pcl::VoxelGrid<PointT> downSampled;  //建立濾波物件
downSampled.setInputCloud (cloud);            //設定需要過濾的點雲給濾波物件
downSampled.setLeafSize (0.01f, 0.01f, 0.01f);  //設定濾波時建立的體素體積為1cm的立方體,三個引數表示體素柵格葉大小,分別表示體素在XYZ方向的尺寸
downSampled.setDownsampleAllData(bool downsample)//設定是否對所有的欄位進行下采樣
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 是標準差倍數的一個閾值,可以自己指定。

pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;   //建立濾波器物件
sor.setInputCloud (cloud);                           //設定待濾波的點雲
sor.setMeanK (50);                               //設定在進行統計時考慮的臨近點個數
sor.setStddevMulThresh (1.0);                      //設定判斷是否為離群點的閥值,用來倍乘標準差,也就是上面的std_mul
sor.filter (*cloud_filtered);                    //濾波結果儲存到cloud_filtered

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

2.2  RadiusOutlierRemoval

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

                                                 

pcl::RadiusOutlierRemoval<pcl::PointXYZ> pcFilter;  //建立濾波器物件
pcFilter.setInputCloud(cloud);             //設定待濾波的點雲
pcFilter.setRadiusSearch(0.8);               // 設定搜尋半徑
pcFilter.setMinNeighborsInRadius(2);      // 設定一個內點最少的鄰居數目
pcFilter.filter(*cloud_filtered);        //濾波結果儲存到cloud_filtered

2.3  FastBilateralFilter、BilateralFilter

       雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合影象的空間鄰近度和畫素值相似度的一種折中處理,同時考慮空域資訊和灰度相似性,達到保邊去噪的目的。具有簡單、非迭代、區域性的特點 。雙邊濾波器的好處是可以做邊緣儲存。對於雙邊濾波不只用在影象,很多時候也會在處理點雲資料的時候使用,對點雲資料進行光滑處理

        雙邊 濾 波 算 法主要用於對點雲資料的小尺度起伏噪聲進行平滑光順。雙邊濾波應用於三維點雲資料去噪,既有效地對空間三維模型表面進行降噪,又可以保持點雲資料中的幾何特徵資訊,避免三維點雲資料被過渡光滑。在點雲模型中設點p 的k 鄰域點集及單位法向量分別為Nk與ni ,雙邊濾波可以定義為:

                                                

                    

                             

    WC,WS 分別表示雙邊濾波函式的空間域和頻率域權重函式,它們分別控制著雙邊濾波的平滑程度和特徵保持程度。’<n,pj-pi>為n與pj-pi的內積,nj,ni 為點 的 法 向量。

                      

 

 pcl::PointCloud<pcl::PointXYZ>::Ptr xyz (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::FastBilateralFilter<pcl::PointXYZ> fbf;
  fbf.setInputCloud (xyz);
  fbf.setSigmaS (sigma_s);//設定雙邊濾波器用於空間鄰域/視窗的高斯的標準偏差

  fbf.setSigmaR (sigma_r);//設定高斯的標準偏差用於控制相鄰畫素由於強度差異而下降多少(在我們的情況下為深度)
  pcl::PointCloud<pcl::PointXYZ> xyz_filtered;
  fbf.filter (xyz_filtered);

注意:能使用雙邊濾波的點雲必須得包含強度欄位。現有的points型別中,只有PointXYZI和PointXYZINormal有強度資訊。FastBilateralFilter只適用於有序點雲。

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