一、簡介
PCL(Point Cloud Library)是在吸收了前人點雲相關研究基礎上建立起來的大型跨平臺開源C++編程庫,它實現了大量點雲相關的通用算法和高效數據結構,涉及點雲獲取、濾波、分割、配準、檢索、特徵提取、識別、追蹤、曲面重建、可視化等,支持多種操作系統平臺,可在Windows、Linux、Android、Mac OS、部分嵌入式實時系統上運行。如果說OpenCV是2D信息獲取與處理的結晶,那麼PCL就在3D信息獲取與處理上具有同等地位,PCL是BSD授權方式,可以免費進行商業和學術應用。
二、安裝準備
本人電腦系統是Window10,所以接下來也會以該環境示例如何安裝。
下載文件包括以下內容
vs2017: 官網更新了vs2019,可根據情況下載安裝,我這裏用的vs2017,安裝過程可自行上網搜索,這個網上很多,這裏不再過多贅述。
Qt: 由於在後期可能需要用到Qt做界面,所以這裏也提前將Qt安裝好,具體安裝過程也可自行上網搜索。我這裏安裝的版本是Qt 5.13.1的版本
CMake: 需要編譯源碼,直接去官網下載最新版本安裝即可。
PCL: 去這裏下載
下載我圈中的那兩個文件即可,但由於網速會很慢,可以通過下面給出的百度網盤鏈接進行下載。
VTK1.8:
在PCL的第三方庫中,包含了VTK1.8版本,但由於PCL自帶的VTK不支持Qt,所以需要進行手動編譯VTK1.8源碼,將編譯後的文件進行替換即可,但由於VTK官網已沒有VTK1.8的源碼,而最新的PCL1.9.1最高只支持到VTK1.8的版本,所以我同樣把VTK1.8的源碼放置在了百度網盤裏供大家下載。
百度網盤地址:
鏈接:百度網盤
提取碼:vni6
三、安裝過程
1、PCL安裝
雙擊前面下載好的安裝包進行安裝,具體安裝過程可以參考如下網址:
但是該博客裏並沒有重新對VTK1.8版本進行重新編譯,所以接下來將會講述如何進行VTK的編譯
2、VTK1.8安裝
首先,將從前面網盤裏下載的VTK1.8的源碼解壓到一個文件夾裏,並另外新建2個文件夾,一個用作編譯目錄,一個用做安裝目錄:
在進行編譯之前,還需要一步操作,將如下代碼添加到源碼文件夾下的CMakeLists.txt文件裏大概88行左右的位置
set(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Add a postfix to the debug libraries")
mark_as_advanced(CMAKE_DEBUG_POSTFIX)
保存關閉之後打開CMake
VTK編譯
選擇好目錄之後,點擊Configure,在彈窗中選擇generator爲Visual Studio 15 2017,platform爲x64(這裏根據自己電腦環境進行選擇),最後點擊Finish。
等待Configure完成後,cmake界面會出現一堆紅色的Name與Value,這時需要手動修改一些變量的值:
- 勾選
BUILD_SHARED_LIBS
,使生成VTK的lib與dll; - 設置
CMAKE_DEBUG_POSTFIX
的值,該變量表示在Debug模式下輸出文件名的後面加上的字符,這裏設置爲_d
,則最後Debug模式下編譯生成的文件名後面都有_d
後綴,從而區分Release模式與Debug模式所用文件; - 勾選
VTK_Group_Qt
,讓VTK支持Qt Application; - 設置
CMAKE_INSTALL_PREFIX
目錄爲VTK安裝目錄(VTK-8.1.1-install
)
修改完成後,再次點擊Configure,會發現紅色變量會少一些,請確認紅色變量的路徑(Qt路徑(QTDIR,這個如果報錯找不到路徑的話,就在環境變量那裏新建一個QTDIR的路徑)是否正確,以及Qt的版本是否爲5。
如果正確,則再次點擊Configure,正常的話就不會再有紅色的變量,接下來點擊Generate,等待Generate done
編譯完成後,在build目錄下會生成VTK.sln
VTK生成
cmake編譯完成後,需要用VS2017對項目進行生成與安裝。
【注意】:直接在cmake中點擊Open Project打開VS2017可能會生成失敗,因爲一些文件夾的讀取權限問題,我們需要用管理員權限打開VS2017後,再打開項目VTK.sln
-
使用管理員身份運行VS2017,打開項目VTK.sln,現在Debug與x64,然後右鍵ALL_BUILD,點擊重新生成,等待漫長的時間,當全部成功後,執行下一步操作。
-
右鍵INSTALL,選擇僅用於項目→僅生成INSTALL。等待時間很短,當生成成功後,可以在VTK的安裝目錄下,看到所生成的lib文件的文件名後綴都有“_d”。
-
然後在VS2017中將解決方案配置由Debug改爲Release,重複以上ALL_BUILD與INSTALL過程。
-
完成後,在VTK的安裝目錄下,看到所生成的lib文件有2種,帶後綴“_d”與不帶的。
至此,VTK的Debug與Release模式的編譯安裝就已經完成了。
3、vs2017配置
將VTK安裝目錄下的所有文件:
copy到PCL安裝目錄下的\3rdParty\VTK
下
最後vs2017的相關配置過程可繼續參考上述博客進行配置。
四、測試
新建PCL項目,用如下代碼進行測試:
#include <iostream>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/sample_consensus/sac_model_sphere.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
boost::shared_ptr<pcl::visualization::PCLVisualizer>
simpleVis(pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
// --------------------------------------------
// -----Open 3D viewer and add point cloud-----
// --------------------------------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0);
viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
//viewer->addCoordinateSystem (1.0, "global");
viewer->initCameraParameters();
return (viewer);
}
int
main(int argc, char** argv)
{
// initialize PointClouds
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr final(new pcl::PointCloud<pcl::PointXYZ>);
// populate our PointCloud with points
cloud->width = 500;
cloud->height = 1;
cloud->is_dense = false;
cloud->points.resize(cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size(); ++i)
{
if (pcl::console::find_argument(argc, argv, "-s") >= 0 || pcl::console::find_argument(argc, argv, "-sf") >= 0)
{
cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0);
cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0);
if (i % 5 == 0)
cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0);
else if (i % 2 == 0)
cloud->points[i].z = sqrt(1 - (cloud->points[i].x * cloud->points[i].x)
- (cloud->points[i].y * cloud->points[i].y));
else
cloud->points[i].z = -sqrt(1 - (cloud->points[i].x * cloud->points[i].x)
- (cloud->points[i].y * cloud->points[i].y));
}
else
{
cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0);
cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0);
if (i % 2 == 0)
cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0);
else
cloud->points[i].z = -1 * (cloud->points[i].x + cloud->points[i].y);
}
}
std::vector<int> inliers;
// created RandomSampleConsensus object and compute the appropriated model
pcl::SampleConsensusModelSphere<pcl::PointXYZ>::Ptr
model_s(new pcl::SampleConsensusModelSphere<pcl::PointXYZ>(cloud));
pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr
model_p(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud));
if (pcl::console::find_argument(argc, argv, "-f") >= 0)
{
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_p);
ransac.setDistanceThreshold(.01);
ransac.computeModel();
ransac.getInliers(inliers);
}
else if (pcl::console::find_argument(argc, argv, "-sf") >= 0)
{
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_s);
ransac.setDistanceThreshold(.01);
ransac.computeModel();
ransac.getInliers(inliers);
}
// copies all inliers of the model computed to another PointCloud
pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *final);
// creates the visualization object and adds either our orignial cloud or all of the inliers
// depending on the command line arguments specified.
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
if (pcl::console::find_argument(argc, argv, "-f") >= 0 || pcl::console::find_argument(argc, argv, "-sf") >= 0)
viewer = simpleVis(final);
else
viewer = simpleVis(cloud);
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return 0;
}
如果最後在Debug和Release兩種模式下均能成功運行如下圖形,則表示環境搭建成功!