前一篇得到的點雲還不能拿來直接用,因為乙個是太多了,另乙個是還存在一大堆的雜訊。所以這一篇我會記錄一下我使用到的一些濾波操作。
主要的的參考資料都在這裡了:
但是我利用得到的點雲做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 可以用於...