一.點雲顯示模塊
根據PCL中國官方論壇上田博士的四篇文章
http://www.pclcn.org/bbs/forum.php?mod=viewthread&tid=223&page=1&extra=#pid750,在MFC環境中搭建了基本的點雲顯示模塊。這是后續所有操作的基礎。
1.需要解決的問題有:
(
1
)由於田博士在帖子里說,
PCL-1.6.0-AllInOne-msvc2010-win32
中提供的
VTK5.8
缺少關鍵文件
vtkMFCWindow.h
和
vktMFC.lib
,所以無法實現基於
MFC
的
PCL
窗體。因此需要自行下載
VTK5.10
,用
CMake
生成工程文件;
我下載的
CMake
版本是
2.8.11.1
,第一次進行配置的時候,看不到
VTK_USE_MFC
的選項,通過復選“
Advanced
”復選框找到了
VTK_GUI_SUPPORT
選項,勾選這個選項之后單擊“
Config
”按鈕,才找到了
VTK_USE_MFC
的選項;
注意,如果不勾選
VTK_USE_MFC
的選項,就不能生成
vtkMFC
工程需要的信息;(具體過程參考筆記《VTK安裝及源碼編譯》)。
(2
)編譯自己的項目時會在下面的代碼處,遇到很多編譯錯誤:
std::numeric_limits<double >::max();
std::max();
編譯錯誤的內容是:
“(
”:
“::
”右邊的非法標記
錯誤原因:函數模板
max
與
Visual C++
中的全局的宏
max
沖突。
從網上找到的解決辦法是把“std::numeric_limits<double>::max
”用小括號括起來;
(std::numeric_limits<double>::max)();
(std::max)();
還有另外一種解決方法是在沖突的文件的頭文件加上:#undef max
#undef min
(3)一些其他的調試問題。
2.修改點雲顯示模塊
田博士修改的代碼中點雲顯示類型是
sensor_msgs::PointCloud2
- this->binary_blob.reset();
- binary_blob = sensor_msgs::PointCloud2::Ptr (new sensor_msgs::PointCloud2);
- // read new data
- //*.pcd文件
- pcl::PCDReader pcd_reader;
- if (pcd_reader.read ((char*)_bstr_t(filename.c_str()), *binary_blob) != 0) //* load the file
- {
- MessageBox (_T("Couldn't read PCData file!"));
- return;
- }
- }
- if (binary_blob == NULL)
- {
- MessageBox("Please load PCD file firstly!");
- return;
- }
- else
- {
- //其他句柄
- if (pcl::getFieldIndex(*binary_blob, "rgb") > 0)
- {
- color_Handler = pcl::mfc_visualization::PointCloudColorHandlerRGBField<sensor_msgs::PointCloud2>::Ptr
- (new pcl::mfc_visualization::PointCloudColorHandlerRGBField<sensor_msgs::PointCloud2> (binary_blob));
- this->viewer->addPointCloud(binary_blob, color_Handler, sensor_origin, sensor_orientation);
- }
- else
- {
- xyz_Handler = pcl::mfc_visualization::PointCloudGeometryHandlerXYZ<sensor_msgs::PointCloud2>::Ptr
- (new pcl::mfc_visualization::PointCloudGeometryHandlerXYZ<sensor_msgs::PointCloud2> (binary_blob));
- this->viewer->addPointCloud(binary_blob, xyz_Handler, sensor_origin, sensor_orientation);
- }
- this->viewer->resetCamera();
我們將其修改為
pcl::PointCloud<pcl::PointXYZ>:並獨立出顯示函數
void CPointCloudLabDlg::simplevis (pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
//統計選取點雲數
//創建3D窗口並添加點雲
viewer->removeAllPointClouds();
viewer->removeAllShapes();
viewer->setBackgroundColor (0,0,0);
viewer->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud");
viewer->setPointCloudRenderingProperties (pcl::mfc_visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
viewer->addCoordinateSystem (1.0);
//viewer->initCameraParameters ();
viewer->resetCamera();
}

圖1

圖2
二.點雲濾波
1.直通濾波器
這是一個書桌的場景,濾波之前其可視化結果如圖2所示。很明顯可以看出其右側存在一大塊噪聲數據,對於這種大塊的且與主體點雲數據存在明顯界限的噪聲數據,最快的方法就是直接設計一個直通濾波器,該方法簡單易用,且效果明顯,唯一不足的就是需要手動濾波,即用戶必須經過多次嘗試,找到噪聲數據與主體點雲數據的大致邊界。圖3即為直通濾波之后的結果,直通濾波器設置為保留x坐標在-0.9~0.6之間的點雲數據,很明顯可以看出書桌左右兩部分的大量噪聲數據被移除掉了。

圖3
對於巷道

圖4
2.StatisticOutlierRemoval濾波器移除離群點
直通濾波雖然能快速移除大量的噪聲點,但其具有很大的局限性,一是需要手動濾波,需要人為判斷噪聲點的大致位置,經過多次嘗試才能找到大致的濾波范圍;二是直通濾波的應用場合有限,除非噪聲點與主體點雲數據具有明顯的界限。下面介紹一種不需要人工判斷且能有限移除主體點雲周圍離群噪聲點的方法,可以解決其中部分問題:建立點雲數據的拓撲結構,對每個點的鄰域進行一個統計分析,並修剪掉那些不符合一定標准的點。我們的稀疏離群點移除方法基於在輸人數據中對點到臨近點的距離分布的計算。對每個點,我們計算它到它的所有臨近點的平均距離。假設得到的結果是一個高斯分布,其形狀由均值和標准差決定,平均距離在標准范圍(由全 局距離平均值 和方差定義)之外的點,可被定義為離群點並可從數據集中去除掉。使用
StatisticOutlierRemoval
濾波器移除離群點之前如圖3
所示,濾波過后如圖5
所示。


三.點雲精簡
上面兩幅圖的右下角都顯示了其點的數量。
1.包圍盒法
該方法是首先用一個體包圍盒來約束點雲,將所有的點雲數據置於這個包圍盒中,然后把這個大包圍盒分解成許多大小一致的小盒,選取與各小盒中心點或與中心點最接近的點取代各小盒中全部的點,經過該方法處理過的點雲個數即為小盒的個數,該方法操作簡單,能有效減少點雲數量。
首先設置包圍盒長寬高,一般我們就用立方體。邊長越長,精簡程度越大。



2.基於Alpha Shapes
基於Alpha Shapes的點雲精簡算法是筆者在研究三維點雲的凸包模型時發現的,三維點雲的凸包模型能近似表示物體表面的輪廓,通過提取三維凸包模型的凸包點來構建物體表面,就可以大幅減少點雲數據量,但是三維凸包不能真實反映物體的輪廓形貌,當物體表面存在凹陷時,凸包就不能反映出來,因此衍生出一種Alpha Shapes的概念,該方法能有效保持物體的原貌,其精簡精度也易控制。下面對上面的點雲進一步簡化。

四.點雲重建
1.貪婪投影三角化算法
設置參數





開發環境:vs2010+PCL1.6.0-32bit+MFC
源碼工程下載地址:https://pan.baidu.com/s/1gfjUL4v
附件列表