从PointNet到PCL:我是如何用VS2019在Win10上搭建第一个点云可视化Demo的
第一次读到PointNet论文时,那些在三维空间中跳动的点云数据让我着迷。但论文中的可视化效果似乎依赖于专业CAD软件,而我更想用代码直接操控这些空间点阵。经过一番探索,我发现了点云库(PCL)——这个被誉为"OpenCV for 3D"的强大工具。本文将分享我在Windows 10系统下,使用Visual Studio 2019搭建PCL开发环境,并实现第一个点云可视化Demo的全过程。
1. 环境准备:PCL与VS2019的完美组合
选择PCL 1.11.0版本是因为它与VS2019有着最佳的兼容性。就像搭积木需要稳固的基础,环境配置是整个项目成功的关键第一步。
1.1 获取安装包
需要下载两个核心文件:
- PCL-1.11.0-AllInOne-msvc2019-win64.exe:主安装程序
- pcl-1.11.0-pdb-msvc2019-win64.zip:调试符号文件
提示:建议从PCL官方GitHub仓库下载,确保文件完整性。
1.2 安装过程详解
安装时有两个关键决策点:
- 勾选"Add PCL to the system PATH for all users"选项
- 修改OpenNI2的安装路径到PCL目录下的3rdParty文件夹
安装完成后,需要将pdb文件解压到PCL的bin目录。这一步经常被忽略,但对后续调试至关重要。
2. 环境变量配置:让系统找到PCL
即使安装程序自动添加了部分路径,手动检查仍是必要的。以下是必须包含的系统环境变量:
| 变量类型 | 路径示例 |
|---|---|
| PATH | D:\PCL\bin |
| PATH | D:\PCL\3rdParty\VTK\bin |
| PATH | D:\PCL\3rdParty\OpenNI2\Redist |
# 验证环境变量是否生效 echo %PATH%如果发现路径缺失,需要手动添加并重启系统使更改生效。
3. VS2019项目配置:精细调整每一步
3.1 基础项目设置
新建空项目后,首先确保:
- 平台工具集设置为Visual Studio 2019
- 解决方案平台为x64
- 配置为Release
3.2 包含目录与库目录
在属性管理器中,需要添加以下包含目录:
D:\PCL\include\pcl-1.11 D:\PCL\3rdParty\Boost\include\boost-1_73 D:\PCL\3rdParty\Eigen\eigen3 D:\PCL\3rdParty\FLANN\include D:\PCL\3rdParty\Qhull\include D:\PCL\3rdParty\VTK\include\vtk-8.2 D:\PCL\3rdParty\OpenNI2\Include库目录则需要包含:
D:\PCL\lib D:\PCL\3rdParty\Boost\lib D:\PCL\3rdParty\FLANN\lib D:\PCL\3rdParty\Qhull\lib D:\PCL\3rdParty\VTK\lib D:\PCL\3rdParty\OpenNI2\Lib3.3 预处理器与链接器设置
关键预处理器定义:
BOOST_USE_WINDOWS_H NOMINMAX _CRT_SECURE_NO_DEPRECATE同时需要关闭SDL检查,这在项目属性和属性页中都需要设置。
4. 第一个点云可视化Demo
配置完成后,终于可以编写代码了。我们从最简单的点云生成和显示开始。
4.1 创建随机点云
#include <pcl/visualization/cloud_viewer.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> int main() { // 创建点云对象 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 生成1000个随机点 cloud->width = 1000; cloud->height = 1; cloud->points.resize(cloud->width * cloud->height); for (size_t i = 0; i < cloud->points.size(); ++i) { cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f); } // 创建可视化窗口 pcl::visualization::CloudViewer viewer("Simple Cloud Viewer"); viewer.showCloud(cloud); // 保持窗口打开 while (!viewer.wasStopped()) {} return 0; }4.2 加载并显示PCD文件
实际项目中,我们更多需要处理已有的点云数据。PCL支持多种点云文件格式,其中PCD是最常用的。
#include <pcl/io/pcd_io.h> #include <pcl/visualization/cloud_viewer.h> int main(int argc, char** argv) { if (argc < 2) { std::cerr << "Usage: " << argv[0] << " <pcd-file>\n"; return -1; } pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 加载PCD文件 if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud) == -1) { std::cerr << "Couldn't read file " << argv[1] << "\n"; return -1; } std::cout << "Loaded " << cloud->width * cloud->height << " data points\n"; // 可视化 pcl::visualization::CloudViewer viewer("PCD Viewer"); viewer.showCloud(cloud); while (!viewer.wasStopped()) {} return 0; }5. 常见问题与解决方案
在配置过程中,我遇到了几个典型问题,这里分享解决方法:
5.1 OpenNI2.dll缺失错误
现象:运行时提示找不到OpenNI2.dll解决:确保环境变量中包含OpenNI2的Redist目录路径
5.2 链接错误
现象:编译时报LNK2019等链接错误解决:
- 检查附加依赖项是否包含所有必要的lib文件
- 确认平台工具集和解决方案平台设置正确
- 确保使用的是Release版本的库文件
5.3 可视化窗口闪退
现象:CloudViewer窗口立即关闭解决:添加while循环保持窗口打开,如示例代码所示
6. 进阶:自定义点云显示
基础的显示功能实现后,我们可以进一步定制可视化效果:
pcl::visualization::PCLVisualizer viewer("Custom 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); // 添加坐标系 viewer.initCameraParameters(); while (!viewer.wasStopped()) { viewer.spinOnce(100); std::this_thread::sleep_for(std::chrono::milliseconds(100)); }这段代码实现了:
- 自定义背景颜色
- 调整点大小
- 添加参考坐标系
- 更流畅的交互体验
7. 从Demo到实际应用
完成基础Demo后,我尝试将其应用到实际项目中。例如,处理Kinect捕获的点云数据时,可以添加以下功能:
- 点云滤波:去除离群点和噪声
- 特征提取:计算法线、曲率等特征
- 分割处理:将场景分割为不同对象
- 配准对齐:将多帧点云拼接为完整场景
// 简单的VoxelGrid滤波示例 pcl::VoxelGrid<pcl::PointXYZ> voxel; voxel.setInputCloud(cloud); voxel.setLeafSize(0.01f, 0.01f, 0.01f); // 1cm的体素大小 voxel.filter(*filteredCloud);通过这些扩展,简单的Demo就变成了一个实用的点云处理工具。