点云是在同一空间参考系下表达目标空间分布和目标表面特性的海量点集合,物体表面设置多个采样点获取这些点的信息,这些点包含了丰富的信息,包括三维坐标X,Y,Z、颜色、分类值、强度值、时间等等,而大量这种点组成的点集合就称之为点云(Point Cloud)。
点云文件可看作是一张三维图,将通过设备读取到的点云数据以某种特定格式存储于文件中,目前常见的点云存储格式有*.pcd,.ply,.pts; *.asc ; *.dat; .stl ; [1] .imw;.xyz;.las,不同的格式文件存储点云数据的格式也不同,这个需要不再深入介绍。其中,LAS格式文件已成为LiDAR数据的工业标准格式,LAS文件按每条扫描线排列方式存放数据,包括激光点的三维坐标、多次回波信息、强度信息、扫描角度、分类信息、飞行航带信息、飞行姿态信息、项目信息、GPS信息、数据点颜色信息等。
C–class(所属类)
F一flight(航线号)
T一time(GPS时间)
I一intensity(回波强度)
R一return(第几次回波)
N一number of return(回波次数)
A一scan angle(扫描角)
RGB一red green blue(RGB颜色值)
作为3D扫描的结果,点云数据有多方面的用途,包括为制造部件,质量检查,多元化视觉,卡通制作,三维制图和大众传播工具应用等创建3D CAD模型。当点云可以直接被描绘和观察时,通常点云本身不能直接用于3D应用,因此一般通过表面重建的方法将它转换为多边形或三角形等网状模型,NURBS曲面模型(曲线曲面的非均匀有理B样条模型)和CAD模型。这里有很多技术应用在将点云转换为3D表面的过程中。
前面我们已经了解到,点云数据是我们对一个物体进行3D扫描结果的描述,它在诸多领域都有广泛的应用前景,既然是应用,那就不可避免的会涉及到点云数据的可视化工作。显然,通过编码来实现点云文件的可视化肯定是个复杂的工作,因为它不仅会涉及到点云数据的读取,还涉及到数据的处理以及点云的渲染显示,如果仅通过自主独立编码的方式来实现这一系列功能,那么肯定会极大地影响开发效率和成品质量,还会极大地阻碍点云技术在各行各业的应用。由于这些问题的存在,点云数据处理领域出现了一个可以大大简化开发的工具——PCL (Point Cloud Library)。
PCL(Point Cloud Library)是在吸收了前人点云相关研究基础上建立起来的大型跨平台开源C++编程库,它实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。支持多种操作系统平台,可在Windows、Linux、Android、Mac OS X、部分嵌入式实时系统上运行。如果说OpenCV是2D信息获取与处理的结晶,那么PCL就在3D信息获取与处理上具有同等地位。
(1). 准备工作:
获取All in one 安装包、All in one对应的PDB文件包(用于后期单步调试),QT安装包以及与All in one 版本对应的vs
(2). 安装
具体安装步骤就不一一赘述,因为大体的安装步骤和其他软件都近似相同,下面只强调一些注意事项
https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/
,注意选择正确的版本,先安装VS2015Visual C++ 库的运行时组件(64位); 再安装VS2015的生成工具。D:\QT\PCL\PCL1.8.0\3rdParty\OpenNI2
D:\QT\PCL\PCL1.8.0\lib
https://drive.google.com/drive/folders/0B77sn1oU1VMDV09GckNMNFlwd3c
https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.3/qt-opensource-windows-x86-5.9.3.exe
项目创建之前,首先要配置Qt Creator的构建套件,依次打开工具——选项——构建与运行——编译器,如果上述安装成功,编译器将会自动检测出MSVC编译器
成功后选择构建套件卡片,这里会自动检测到,只需要在下方做一些配置即可,调试器是必选的,如果不选或者选择错误会出现红色感叹号,如果没有调试器会显示黄色感叹号,如果是黄色感叹号可以使用
执行配置之后,便可以创建QT项目,项目创建完成之后首先就是配置.pro文件,具体配置如下,下面路径较多,注意根据自己的实际安装情况而改变,主要是版本不同。
指定编译项目时应该被搜索的#include目录:
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/include/pcl-1.8\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/include/pcl-1.8/pcl\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/Boost/include/boost-1_61\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/Eigen/eigen3\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/FLANN/include\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/FLANN/include/flann\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/OpenNI2/Include\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/Qhull/include\
INCLUDEPATH += D:/QT/PCL/PCL1.8.0/3rdParty/VTK/include/vtk-7.0\
指定链接到项目中的库列表:
CONFIG(debug,debug|release){
LIBS += -LD:/QT/PCL/PCL1.8.0/lib\
# -lpcl_apps_debug\
-lpcl_common_debug\
-lpcl_features_debug\
-lpcl_filters_debug\
-lpcl_io_debug\
-lpcl_io_ply_debug\
-lpcl_kdtree_debug\
-lpcl_keypoints_debug\
-lpcl_ml_debug\
-lpcl_octree_debug\
-lpcl_outofcore_debug\
-lpcl_people_debug\
-lpcl_recognition_debug\
-lpcl_registration_debug\
-lpcl_sample_consensus_debug\
-lpcl_search_debug\
-lpcl_segmentation_debug\
# -lpcl_simulation_debug\
-lpcl_stereo_debug\
-lpcl_surface_debug\
-lpcl_tracking_debug\
-lpcl_visualization_debug\
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/Boost/lib\
-llibboost_atomic-vc140-mt-gd-1_61\
-llibboost_chrono-vc140-mt-gd-1_61\
-llibboost_container-vc140-mt-gd-1_61\
-llibboost_context-vc140-mt-gd-1_61\
-llibboost_coroutine-vc140-mt-gd-1_61\
-llibboost_date_time-vc140-mt-gd-1_61\
-llibboost_exception-vc140-mt-gd-1_61\
-llibboost_filesystem-vc140-mt-gd-1_61\
-llibboost_graph-vc140-mt-gd-1_61\
-llibboost_iostreams-vc140-mt-gd-1_61\
-llibboost_locale-vc140-mt-gd-1_61\
-llibboost_log-vc140-mt-gd-1_61\
-llibboost_log_setup-vc140-mt-gd-1_61\
-llibboost_math_c99-vc140-mt-gd-1_61\
-llibboost_math_c99f-vc140-mt-gd-1_61\
-llibboost_math_c99l-vc140-mt-gd-1_61\
-llibboost_math_tr1-vc140-mt-gd-1_61\
-llibboost_math_tr1f-vc140-mt-gd-1_61\
-llibboost_math_tr1l-vc140-mt-gd-1_61\
-llibboost_mpi-vc140-mt-gd-1_61\
-llibboost_prg_exec_monitor-vc140-mt-gd-1_61\
-llibboost_program_options-vc140-mt-gd-1_61\
-llibboost_random-vc140-mt-gd-1_61\
-llibboost_regex-vc140-mt-gd-1_61\
-llibboost_serialization-vc140-mt-gd-1_61\
-llibboost_signals-vc140-mt-gd-1_61\
-llibboost_system-vc140-mt-gd-1_61\
-llibboost_test_exec_monitor-vc140-mt-gd-1_61\
-llibboost_thread-vc140-mt-gd-1_61\
-llibboost_timer-vc140-mt-gd-1_61\
-llibboost_unit_test_framework-vc140-mt-gd-1_61\
-llibboost_wave-vc140-mt-gd-1_61\
-llibboost_wserialization-vc140-mt-gd-1_61
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/FLANN/lib\
-lflann-gd\
-lflann_cpp_s-gd\
-lflann_s-gd
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/OpenNI2/Lib\
-lOpenNI2
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/Qhull/lib\
# -lqhull-gd\
-lqhullcpp-gd\
-lqhullstatic-gd\
-lqhullstatic_r-gd\
-lqhull_p-gd\
-lqhull_r-gd
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty\VTK\lib\
-lvtkalglib-7.0-gd\
-lvtkChartsCore-7.0-gd\
-lvtkCommonColor-7.0-gd\
-lvtkCommonComputationalGeometry-7.0-gd\
-lvtkCommonCore-7.0-gd\
-lvtkCommonDataModel-7.0-gd\
-lvtkCommonExecutionModel-7.0-gd\
-lvtkCommonMath-7.0-gd\
-lvtkCommonMisc-7.0-gd\
-lvtkCommonSystem-7.0-gd\
-lvtkCommonTransforms-7.0-gd\
-lvtkDICOMParser-7.0-gd\
-lvtkDomainsChemistry-7.0-gd\
-lvtkDomainsChemistryOpenGL2-7.0-gd\
-lvtkexoIIc-7.0-gd\
-lvtkexpat-7.0-gd\
-lvtkFiltersAMR-7.0-gd\
-lvtkFiltersCore-7.0-gd\
-lvtkFiltersExtraction-7.0-gd\
-lvtkFiltersFlowPaths-7.0-gd\
-lvtkFiltersGeneral-7.0-gd\
-lvtkFiltersGeneric-7.0-gd\
-lvtkFiltersGeometry-7.0-gd\
-lvtkFiltersHybrid-7.0-gd\
-lvtkFiltersHyperTree-7.0-gd\
-lvtkFiltersImaging-7.0-gd\
-lvtkFiltersModeling-7.0-gd\
-lvtkFiltersParallel-7.0-gd\
-lvtkFiltersParallelImaging-7.0-gd\
-lvtkFiltersProgrammable-7.0-gd\
-lvtkFiltersSelection-7.0-gd\
-lvtkFiltersSMP-7.0-gd\
-lvtkFiltersSources-7.0-gd\
-lvtkFiltersStatistics-7.0-gd\
-lvtkFiltersTexture-7.0-gd\
-lvtkFiltersVerdict-7.0-gd\
-lvtkfreetype-7.0-gd\
-lvtkGeovisCore-7.0-gd\
-lvtkglew-7.0-gd\
# -lvtkGUISupportQt-7.0-gd\
# -lvtkGUISupportQtSQL-7.0-gd\
-lvtkhdf5-7.0-gd\
-lvtkhdf5_hl-7.0-gd\
-lvtkImagingColor-7.0-gd\
-lvtkImagingCore-7.0-gd\
-lvtkImagingFourier-7.0-gd\
-lvtkImagingGeneral-7.0-gd\
-lvtkImagingHybrid-7.0-gd\
-lvtkImagingMath-7.0-gd\
-lvtkImagingMorphological-7.0-gd\
-lvtkImagingSources-7.0-gd\
-lvtkImagingStatistics-7.0-gd\
-lvtkImagingStencil-7.0-gd\
-lvtkInfovisCore-7.0-gd\
-lvtkInfovisLayout-7.0-gd\
-lvtkInteractionImage-7.0-gd\
-lvtkInteractionStyle-7.0-gd\
-lvtkInteractionWidgets-7.0-gd\
-lvtkIOAMR-7.0-gd\
-lvtkIOCore-7.0-gd\
-lvtkIOEnSight-7.0-gd\
-lvtkIOExodus-7.0-gd\
-lvtkIOExport-7.0-gd\
-lvtkIOGeometry-7.0-gd\
-lvtkIOImage-7.0-gd\
-lvtkIOImport-7.0-gd\
-lvtkIOInfovis-7.0-gd\
-lvtkIOLegacy-7.0-gd\
-lvtkIOLSDyna-7.0-gd\
-lvtkIOMINC-7.0-gd\
-lvtkIOMovie-7.0-gd\
-lvtkIONetCDF-7.0-gd\
-lvtkIOParallel-7.0-gd\
-lvtkIOParallelXML-7.0-gd\
-lvtkIOPLY-7.0-gd\
-lvtkIOSQL-7.0-gd\
-lvtkIOVideo-7.0-gd\
-lvtkIOXML-7.0-gd\
-lvtkIOXMLParser-7.0-gd\
-lvtkjpeg-7.0-gd\
-lvtkjsoncpp-7.0-gd\
-lvtklibxml2-7.0-gd\
-lvtkmetaio-7.0-gd\
-lvtkNetCDF-7.0-gd\
-lvtkNetCDF_cxx-7.0-gd\
-lvtkoggtheora-7.0-gd\
-lvtkParallelCore-7.0-gd\
-lvtkpng-7.0-gd\
-lvtkproj4-7.0-gd\
-lvtkRenderingAnnotation-7.0-gd\
-lvtkRenderingContext2D-7.0-gd\
# -lvtkRenderingContextOpenGL2-7.0-gd\
-lvtkRenderingCore-7.0-gd\
-lvtkRenderingFreeType-7.0-gd\
-lvtkRenderingImage-7.0-gd\
-lvtkRenderingLabel-7.0-gd\
-lvtkRenderingLOD-7.0-gd\
# -lvtkRenderingOpenGL2-7.0-gd\
-lvtkRenderingQt-7.0-gd\
-lvtkRenderingVolume-7.0-gd\
-lvtkRenderingVolumeOpenGL2-7.0-gd\
-lvtksqlite-7.0-gd\
-lvtksys-7.0-gd\
-lvtktiff-7.0-gd\
-lvtkverdict-7.0-gd\
-lvtkViewsContext2D-7.0-gd\
-lvtkViewsCore-7.0-gd\
-lvtkViewsInfovis-7.0-gd\
-lvtkViewsQt-7.0-gd\
-lvtkzlib-7.0-gd
} else {
LIBS += -LD:/QT/PCL/PCL1.8.0/lib\
# -lpcl_apps_release\
-lpcl_common_release\
-lpcl_features_release\
-lpcl_filters_release\
-lpcl_io_release\
-lpcl_io_ply_release\
-lpcl_kdtree_release\
-lpcl_keypoints_release\
-lpcl_ml_release\
-lpcl_octree_release\
-lpcl_outofcore_release\
-lpcl_people_release\
-lpcl_recognition_release\
-lpcl_registration_release\
-lpcl_sample_consensus_release\
-lpcl_search_release\
-lpcl_segmentation_release\
# -lpcl_simulation_release\
-lpcl_stereo_release\
-lpcl_surface_release\
-lpcl_tracking_release\
-lpcl_visualization_release\
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/Boost/lib\
-llibboost_atomic-vc140-mt-1_61\
-llibboost_chrono-vc140-mt-1_61\
-llibboost_container-vc140-mt-1_61\
-llibboost_context-vc140-mt-1_61\
-llibboost_coroutine-vc140-mt-1_61\
-llibboost_date_time-vc140-mt-1_61\
-llibboost_exception-vc140-mt-1_61\
-llibboost_filesystem-vc140-mt-1_61\
-llibboost_graph-vc140-mt-1_61\
-llibboost_iostreams-vc140-mt-1_61\
-llibboost_locale-vc140-mt-1_61\
-llibboost_log-vc140-mt-1_61\
-llibboost_log_setup-vc140-mt-1_61\
-llibboost_math_c99-vc140-mt-1_61\
-llibboost_math_c99f-vc140-mt-1_61\
-llibboost_math_c99l-vc140-mt-1_61\
-llibboost_math_tr1-vc140-mt-1_61\
-llibboost_math_tr1f-vc140-mt-1_61\
-llibboost_math_tr1l-vc140-mt-1_61\
-llibboost_mpi-vc140-mt-1_61\
-llibboost_prg_exec_monitor-vc140-mt-1_61\
-llibboost_program_options-vc140-mt-1_61\
-llibboost_random-vc140-mt-1_61\
-llibboost_regex-vc140-mt-1_61\
-llibboost_serialization-vc140-mt-1_61\
-llibboost_signals-vc140-mt-1_61\
-llibboost_system-vc140-mt-1_61\
-llibboost_test_exec_monitor-vc140-mt-1_61\
-llibboost_thread-vc140-mt-1_61\
-llibboost_timer-vc140-mt-1_61\
-llibboost_unit_test_framework-vc140-mt-1_61\
-llibboost_wave-vc140-mt-1_61\
-llibboost_wserialization-vc140-mt-1_61
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/FLANN/lib\
-lflann\
-lflann_cpp_s\
# -lflann_s
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/OpenNI2/Lib\
-lOpenNI2
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty/Qhull/lib\
-lqhull\
-lqhullcpp\
-lqhullstatic\
-lqhullstatic_r\
-lqhull_p\
-lqhull_r
LIBS += -LD:/QT/PCL/PCL1.8.0/3rdParty\VTK\lib\
-lvtkalglib-7.0\
-lvtkChartsCore-7.0\
-lvtkCommonColor-7.0\
-lvtkCommonComputationalGeometry-7.0\
-lvtkCommonCore-7.0\
-lvtkCommonDataModel-7.0\
-lvtkCommonExecutionModel-7.0\
-lvtkCommonMath-7.0\
-lvtkCommonMisc-7.0\
-lvtkCommonSystem-7.0\
-lvtkCommonTransforms-7.0\
-lvtkDICOMParser-7.0\
-lvtkDomainsChemistry-7.0\
# -lvtkDomainsChemistryOpenGL2-7.0\
-lvtkexoIIc-7.0\
-lvtkexpat-7.0\
-lvtkFiltersAMR-7.0\
-lvtkFiltersCore-7.0\
-lvtkFiltersExtraction-7.0\
-lvtkFiltersFlowPaths-7.0\
-lvtkFiltersGeneral-7.0\
-lvtkFiltersGeneric-7.0\
-lvtkFiltersGeometry-7.0\
-lvtkFiltersHybrid-7.0\
-lvtkFiltersHyperTree-7.0\
-lvtkFiltersImaging-7.0\
-lvtkFiltersModeling-7.0\
-lvtkFiltersParallel-7.0\
-lvtkFiltersParallelImaging-7.0\
-lvtkFiltersProgrammable-7.0\
-lvtkFiltersSelection-7.0\
-lvtkFiltersSMP-7.0\
-lvtkFiltersSources-7.0\
-lvtkFiltersStatistics-7.0\
-lvtkFiltersTexture-7.0\
-lvtkFiltersVerdict-7.0\
-lvtkfreetype-7.0\
-lvtkGeovisCore-7.0\
# -lvtkglew-7.0\
# -lvtkGUISupportQt-7.0\
# -lvtkGUISupportQtSQL-7.0\
-lvtkhdf5-7.0\
-lvtkhdf5_hl-7.0\
-lvtkImagingColor-7.0\
-lvtkImagingCore-7.0\
-lvtkImagingFourier-7.0\
-lvtkImagingGeneral-7.0\
-lvtkImagingHybrid-7.0\
-lvtkImagingMath-7.0\
-lvtkImagingMorphological-7.0\
-lvtkImagingSources-7.0\
-lvtkImagingStatistics-7.0\
-lvtkImagingStencil-7.0\
-lvtkInfovisCore-7.0\
-lvtkInfovisLayout-7.0\
-lvtkInteractionImage-7.0\
-lvtkInteractionStyle-7.0\
-lvtkInteractionWidgets-7.0\
-lvtkIOAMR-7.0\
-lvtkIOCore-7.0\
-lvtkIOEnSight-7.0\
-lvtkIOExodus-7.0\
-lvtkIOExport-7.0\
-lvtkIOGeometry-7.0\
-lvtkIOImage-7.0\
-lvtkIOImport-7.0\
-lvtkIOInfovis-7.0\
-lvtkIOLegacy-7.0\
-lvtkIOLSDyna-7.0\
-lvtkIOMINC-7.0\
-lvtkIOMovie-7.0\
-lvtkIONetCDF-7.0\
-lvtkIOParallel-7.0\
-lvtkIOParallelXML-7.0\
-lvtkIOPLY-7.0\
-lvtkIOSQL-7.0\
-lvtkIOVideo-7.0\
-lvtkIOXML-7.0\
-lvtkIOXMLParser-7.0\
-lvtkjpeg-7.0\
-lvtkjsoncpp-7.0\
-lvtklibxml2-7.0\
-lvtkmetaio-7.0\
-lvtkNetCDF-7.0\
-lvtkNetCDF_cxx-7.0\
-lvtkoggtheora-7.0\
-lvtkParallelCore-7.0\
-lvtkpng-7.0\
-lvtkproj4-7.0\
-lvtkRenderingAnnotation-7.0\
-lvtkRenderingContext2D-7.0\
# -lvtkRenderingContextOpenGL2-7.0\
-lvtkRenderingCore-7.0\
-lvtkRenderingFreeType-7.0\
-lvtkRenderingImage-7.0\
-lvtkRenderingLabel-7.0\
-lvtkRenderingLOD-7.0\
# -lvtkRenderingOpenGL2-7.0\
# -lvtkRenderingQt-7.0\
-lvtkRenderingVolume-7.0\
# -lvtkRenderingVolumeOpenGL2-7.0\
-lvtksqlite-7.0\
-lvtksys-7.0\
-lvtktiff-7.0\
-lvtkverdict-7.0\
-lvtkViewsContext2D-7.0\
-lvtkViewsCore-7.0\
-lvtkViewsInfovis-7.0\
# -lvtkViewsQt-7.0\
-lvtkzlib-7.0
}
下面就是一个简单的应用实例解析,先贴代码
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char *argv[])
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 创建点云(指针)
if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("D:/2.pcd", *cloud) == -1){ //* 读入PCD格式的文件,如果文件不存在,返回-1
PCL_ERROR("Couldn't read file test_pcd.pcd \n"); //文件不存在时,返回错误,终止程序。
return -1;
}
pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");//直接创造一个显示窗口
viewer.showCloud(cloud);//再这个窗口显示点云
while (!viewer.wasStopped()){
qDebug()<<"窗口未关闭"
}
return 0;
}
然后我们对代码进行分解
#include //标准输入输出头文件声明
#include //读取pcd文件头文件声明
#include //I/O相关头文件声明
#include //类CloudViewer头文件声明
首先是相关类的头文件声明
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 创建点云(指针)
创建一个共享指针并对指针进行实例化
if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("D:/2.pcd", *cloud) == -1){ //* 读入PCD格式的文件,如果文件不存在,返回-1
PCL_ERROR("Couldn't read file test_pcd.pcd \n"); //文件不存在时,返回错误,终止程序。
return -1;
}
从磁盘上读取pcd格式文件到二进制存储块中,并对读取结果进行判断,如果文件不存在将退出程序。
pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");//直接创造一个显示窗口
加载点云数据之后就是将数据显示出来,这一步就是创建viewer对象。CloudViewer是简单显示点云的可视化工具类,它可以让用户使用较少的代码来显示点云,有一点需要注意,CloudViewer类不能应用于多线程应用程序中。
viewer.showCloud(cloud);//再这个窗口显示点云
实现点云在窗口中的显示
while (!viewer.wasStopped()){
qDebug()<<"窗口未关闭"
}
这几行代码是判断窗口是否已经被关闭,如果没有关闭就可以做一些其他操作。