PCL 從點雲到網格(二)點雲預處理

2021-09-22 02:07:29 字數 4072 閱讀 1335

前一篇得到的點雲還不能拿來直接用,因為乙個是太多了,另乙個是還存在一大堆的雜訊。所以這一篇我會記錄一下我使用到的一些濾波操作。

主要的的參考資料都在這裡了:

但是我利用得到的點雲做icp得到的融合的矩陣效果不理想,有可能是我相機移動的幅度較大,也可能是我計算icp的點太少(我是先利用降取樣,再做icp的,效果不太理想,得到的t矩陣應用之後效果也不是很好,但是如果直接做icp實在是太慢了)

點雲中密度不規則,存在離群點,資料太多,雜訊等因素導致點雲需要被濾波。沒有濾波的點雲不能用來做mesh。

pcl1.8.1 的濾波函式都在這:

我對得到的點雲做的預處理:

#include

//用於體素網格化的濾波類標頭檔案

#include

//濾波相關標頭檔案

#include

#include

//濾波相關類標頭檔案

#include

//統計方法去除離群點

#include

//統計方法去除離群點

#include

//對點雲的預處理,就是點雲下取樣,去離群點濾波,

void

preporcessingofpointcloud

(pcl::pointcloud

::ptr &cloud_in, pcl::pointcloud

::ptr &cloud_out)

接著來逐個看看每個函式。

首先進行下取樣

我用到的下取樣函式比較簡單,pcl::voxelgrid

//點雲下取樣

void

downsample

(pcl::pointcloud

::ptr &cloud_in, pcl::pointcloud

::ptr &cloud_out)

接下來是去離群點

去除一些離群雜訊。(資料中說:因為離群點會使區域性點雲特徵(如表面法線或曲率變化)的估計複雜化,從而導致錯誤的值,從而可能導致點雲配準失敗。離群點還會累積,誤差會越來越大)

pcl::statisticaloutlierremoval 和 pcl::radiusoutlierremoval

利用統計學 和 利用幾何來去除離群點。

pcl::statisticaloutlierremoval 利用統計學,對每個點的鄰域進行統計分析,剔除不符合一定標準的鄰域點。(具體來說,對於每個點,我們計算它到所有相鄰點的平均距離。假設得到的分布是高斯分布,我們可以計算出乙個均值 μ 和乙個標準差 σ,那麼這個鄰域點集中所有點與其鄰域距離大於μ + std_mul * σ 區間之外的點都可以被視為離群點,並可從點雲資料中去除。std_mul 是標準差倍數的乙個閾值,可以自己指定。)

pcl::radiusoutlierremoval 設定半徑後,每個點周圍再該半徑的球內至少要有足夠多的鄰居,否則他就是個外點。(公尺為單位)

//去除離群點

void

outlierfilter

(pcl::pointcloud

::ptr & cloud_in, pcl::pointcloud

::ptr & cloud_out)

統計這個比較慢,我最後還是用了根據幾何距離來找離群點的,可能沒有統計上那麼準,但是快。

不夠由於還有一些工作,想融合兩幀的點雲。但是由於變換矩陣算出來實在是有問題,因此效果並不好。不知道是**出了問題。先把方法記下來,之後再改改。如果有dalao能夠幫我指出我的問題我真的非常感謝~

由於2幀點雲不相同,因此考慮利用 trimmedicp 計算點雲之間的變換矩陣。這個函式返回變換矩陣,並且利用下面這個函式做變換(引數為示意引數 t為變換矩陣)

pcl::

transformpointcloud

(ptr cloud_from,ptr cloud_from,eigen::matrix4f t)

變換矩陣求解(沒有讀過這個**,具體的引數並不是很了解):

eigen::matrix4f usetrimmedicpwithtwopointclouds

(pcl::pointcloud

::ptr &cloud_1, pcl::pointcloud

::ptr &cloud_2)

align這個函式執行之後會填充t,得到變換矩陣(時間巨長)。

接著計算兩個點雲的重疊區域,這後面就是自己寫的了,也不知道對不對:從correspondenceestimation得到重疊的區域,再利用兩個點雲生成新點雲,重疊區域只生成一次(以第二個點雲為主,重複了就用第二個點雲的資料)

//對兩個點雲融合?correspondenceestimation 計算點雲之間重疊區域

pcl::pointcloud

::ptr fusetwopointcloud

(pcl::pointcloud

::ptr &cloud_1, pcl::pointcloud

::ptr &cloud_2)

pcl::pointcloud

::ptr totalpointcloud

(new pcl::pointcloud()

);totalpointcloud-

>

resize

(cloud_1-

>

size()

+ cloud_2-

>

size()

- all_correspondences.

size()

);int* mask_1 =

newint

[cloud_1-

>

size()

];//2的點雲是新的點雲,所以重疊的部分顯示二的,這個就存的是相應的1中的index

for(

int i =

0; i < cloud_1-

>

size()

; i++

)for

(int i =

0; i < all_correspondences.

size()

; i++

)int cloud2cnt = cloud_2-

>

size()

;int idxintotalcnt =0;

//在totalcloud中的index

for(

int i =

0; i < cloud2cnt + cloud_1-

>

size()

; i++

)else

else}}

std::cout <<

"fuse time(s): "

<< time.

gettimeseconds()

<< std::endl;

std::cout <<

"finish fuse , total size:"

<< totalpointcloud-

>

size()

<< std::endl;

totalpointcloud-

>is_dense =

true

;return totalpointcloud;

}

is_dense 變數是判斷點雲中是否有nan這種不合理的點的。不過有時候這玩意不起作用,有時候它是true,但是還是有nan點。如果它不起做用,就用這個自定義函式,主要部分 pcl_isfinite(double) :

//遍歷並刪除重取樣之後的無效點

void

eraseinvalidpoints

(pcl::pointcloud

::ptr & cloud)

else

++it;

} std::cout <<

"erase points: "

<< cnt << std::endl;

}

點雲到網格

rgbd感測器獲取的資料通常是大量的三維點,後期的處理過程都是在對這些點的座標進行處理。網格重建要求我們從點雲恢復出網格。輸入 點雲檔案 ply,pcd等 輸出 單一網格 1 點雲雜訊。每個點雲都會帶有雜訊,雜訊有可能和物體表面光學性質 物體深度 感測器效能等都有關係。2 點雲匹配誤差。三維重建中需...

pcl點雲處理

一 如何實現類似pcl pointcloud ptr和pcl pointcloud的兩個類相互轉換?include include include pcl pointcloud ptr cloudpointer new pcl pointcloud pcl pointcloudcloud cloud...

pcl教程筆記(二)點雲顯示與執行緒

pcl官方教程提供了乙份點雲顯示的文件教程。點雲顯示與主線程不相關,是乙個單獨的執行緒。所以如果在主線程中對點雲進行操作,很有可能會發生執行緒爭用的問題。viewer.runonvisualizationthreadonce 和viewer.runonvisualizationthread 可以用於...