1. 为什么2024年还有人折腾VS2013配PCL
先把话说在前头:如果你现在打开搜索引擎搜“VS2013配置PCL”,大概率会看到两种声音。一种是“都什么年代了还用VS2013”,另一种是“兄弟我也是,项目锁死在VS2013了”。我属于后者,而且前后帮人配过不下十次,从Win7到Win10,从PCL 1.6到1.8.1,踩过的坑能写满两页A4纸。
这个组合为什么到现在还有需求?核心原因就一个:存量项目的工具链锁定。很多工业视觉、逆向工程、三维扫描相关的老项目,当年就是基于VS2013 + PCL 1.7.x/1.8.x搭起来的,编译环境、第三方库、甚至某些硬件SDK都绑死了这个版本。你贸然升级到VS2019或者VS2022,轻则编译报错几百个,重则整个点云处理管线跑不起来。所以这不是“怀旧”,是“保命”。
PCL(Point Cloud Library)本身是个庞大的C++模板库,点云滤波、配准、分割、曲面重建、可视化全都有。它依赖Boost、Eigen、FLANN、VTK、Qhull这一大串第三方库,版本之间的兼容性极其敏感。VS2013对应的是MSVC 12.0编译器,PCL官方从1.7.0开始提供MSVC 2013的All-in-one安装包,一直到1.8.1都还有支持。再往后1.9.x就只给VS2015+了。所以VS2013 + PCL 1.8.1基本是这个组合的天花板。
这篇文章我打算把整个流程拆透:从安装包怎么选、VS2013装的时候哪些组件必须勾、PCL的All-in-one和单独配置两条路怎么走、环境变量和VS工程属性怎么设、PCD文件包怎么用起来、最后跑一个完整的读写+可视化Demo。中间会穿插大量我实际踩过的坑,比如OpenNI2的路径问题、VTK的DLL缺失、Debug和Release混用导致的诡异崩溃等等。目标很明确:你照着做,能跑通,能少走弯路。
提示:本文涉及的安装包和文件包,请通过正规渠道获取,注意核对文件完整性。所有操作在本地离线环境完成,不涉及任何网络代理配置。
2. 安装包与文件包的准备清单
2.1 VS2013安装程序的选择与版本差异
VS2013的安装程序有好几个版本:Ultimate、Premium、Professional、Community。对于PCL开发来说,Community版完全够用,它包含了完整的C++编译器和MFC支持。但如果你手头只有Ultimate的镜像,也没问题,功能只多不少。
关键点在于:VS2013的安装包分“带Update”和“不带Update”的。原始RTM版本是12.0.21005.1,后面有Update 1到Update 5。强烈建议用Update 5(12.0.40629.00),因为它修复了大量C++编译器的bug,尤其是模板相关的。PCL大量使用C++11模板元编程,RTM版本编译某些头文件时会直接内部错误。我最早用RTM版编PCL的pcl::search::KdTree就遇到过编译器崩溃,换成Update 5后一次通过。
安装的时候,工作负载选择“自定义”,必须勾选的组件:
- 编程语言 → Visual C++ → Visual C++ 2013 编译器
- 编程语言 → Visual C++ → Microsoft Foundation Classes (MFC)
- Windows 和 Web 开发 → 通用 Windows 应用开发工具(可选,但有些SDK依赖)
- 常用工具 → Visual Studio 2013 更新程序
注意:不要勾选“Blend for Visual Studio”和“Silverlight”这些无关组件,装了只会拖慢启动速度。另外,安装路径不要带中文和空格,默认的
C:\Program Files (x86)\Microsoft Visual Studio 12.0就很好。我见过有人装在D:\我的项目\VS2013下面,结果CMake生成时路径解析出错,排查了半天。
2.2 PCL安装程序的两种形态:All-in-one vs 单独编译
PCL官方为Windows提供的安装包有两种:
| 类型 | 文件名示例 | 包含内容 | 适用场景 |
|---|---|---|---|
| All-in-one | PCL-1.8.1-AllInOne-msvc2013-win64.exe | PCL核心库 + Boost + Eigen + FLANN + VTK + Qhull + OpenNI2 | 快速上手,推荐 |
| 单独库 | 各第三方库独立安装包 | 需要自己逐个下载配置 | 需要特定版本组合时 |
All-in-one是绝大多数人的选择,它把依赖都打包好了,安装完只需要配环境变量和VS属性。但要注意:All-in-one安装时会让你选择是否安装OpenNI2,这个组件默认路径是C:\Program Files\OpenNI2,而PCL的配置里期望它在3rdParty\OpenNI2下面。这就是第一个大坑,后面会详细讲。
PCL版本选择上,1.8.1是VS2013的最后一个官方支持版本。1.8.0有个已知的VTK可视化bug,1.7.2缺少某些配准算法。所以直接上1.8.1。
2.3 PCD文件包的用途与内容结构
PCD(Point Cloud Data)是PCL的原生点云格式,分ASCII和Binary两种编码。所谓的“PCD文件包”通常是一批示例点云,用来测试环境是否配好。常见的包括:
bunny.pcd:斯坦福兔子,经典测试模型table_scene_lms400.pcd:桌面场景,带噪声,适合滤波测试room_scan.pcd:室内扫描,点数量大,测试内存和性能car.pcd:车辆点云,用于配准实验
这些文件包一般从PCL官方示例数据或者某些教程配套资源里来。拿到之后不要放在中文路径下,PCL的io::loadPCDFile对非ASCII路径支持很差,会直接返回-1。我一般放在D:\PCL_Data\这种纯英文短路径下。
提示:如果你手头的PCD文件包是压缩包,解压时注意不要产生嵌套目录,比如
pcd_data\pcd_data\bunny.pcd,代码里写路径时容易搞错。
3. VS2013安装中的关键勾选项与验证
3.1 安装过程中的组件取舍逻辑
VS2013安装程序启动后,选择“自定义”安装。这里有个细节:如果你之前装过VS2010或VS2012,安装程序可能会提示升级或并存。我的建议是,如果只是为PCL用,直接全新安装VS2013,不要和旧版本混在一起。MSVC的编译器版本虽然不同,但环境变量VS120COMNTOOLS和VCINSTALLDIR可能会冲突。
必须勾选的组件清单:
- Visual C++ 2013 编译器(核心,不选这个等于白装)
- Microsoft Foundation Classes (MFC)(PCL的某些可视化模块间接依赖)
- Windows SDK 8.1(VS2013默认带的是8.1,PCL的VTK模块需要)
- Visual Studio 2013 更新程序(用于后续打Update 5补丁)
不需要的组件:
- Blend for Visual Studio(做WPF动画用的,跟PCL无关)
- Silverlight(已经淘汰的技术)
- LightSwitch(同样淘汰)
- SQL Server Data Tools(除非你要做数据库)
安装过程大概20-40分钟,取决于磁盘速度。装完后先别急着打开VS,去控制面板确认一下“Microsoft Visual C++ 2013 Redistributable”是否已经安装。如果没有,手动装一下,否则后面运行PCL程序会提示缺少msvcr120.dll。
3.2 安装完成后的环境自检
装完VS2013后,做三个检查:
检查一:编译器版本。打开“VS2013 开发人员命令提示”,输入cl,应该输出类似:
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.40629 for x64版本号18.00.40629就是Update 5。如果是18.00.21005,说明还是RTM版,需要打补丁。
检查二:环境变量。在命令行输入echo %VS120COMNTOOLS%,应该输出C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\。如果为空,说明安装时没注册环境变量,需要手动添加。
检查三:MFC是否存在。去C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\atlmfc目录下看看有没有include和lib文件夹。没有的话,说明MFC组件没勾选,需要重新运行安装程序修改。
注意:如果你用的是Windows 10,VS2013安装程序可能会提示“此程序兼容性有问题”,直接忽略,以管理员身份运行即可。Win10下VS2013能正常工作,只是安装界面有点老。
4. PCL All-in-one安装与路径陷阱
4.1 安装过程中的OpenNI2路径问题
运行PCL-1.8.1-AllInOne-msvc2013-win64.exe,安装向导会依次让你选择:
- PCL主安装路径(默认
C:\Program Files\PCL 1.8.1) - 第三方库路径(默认
C:\Program Files\PCL 1.8.1\3rdParty) - OpenNI2的安装路径(默认
C:\Program Files\OpenNI2)
第三个就是坑。PCL的CMake配置文件里,OpenNI2的搜索路径写死为${PCL_ROOT}/3rdParty/OpenNI2。如果你按默认装到C:\Program Files\OpenNI2,后面在VS里配置时,pcl_io模块会找不到OpenNI2的头文件和库,链接时报LNK2019: 无法解析的外部符号。
解决方案有两个:
- 方案A(推荐):安装时手动把OpenNI2的路径改成
C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2 - 方案B:装完后把
C:\Program Files\OpenNI2整个文件夹复制到C:\Program Files\PCL 1.8.1\3rdParty\下面,并改名为OpenNI2
我一般用方案A,省得后面忘了。如果你已经装完了才发现这个问题,用方案B补救也来得及。
4.2 环境变量的配置细节
All-in-one装完后,需要手动添加环境变量。右键“此电脑” → 属性 → 高级系统设置 → 环境变量。
系统变量Path中添加:
C:\Program Files\PCL 1.8.1\bin C:\Program Files\PCL 1.8.1\3rdParty\VTK\bin C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\Tools C:\Program Files\PCL 1.8.1\3rdParty\FLANN\bin新建系统变量:
PCL_ROOT = C:\Program Files\PCL 1.8.1这里有个细节:Path的顺序很重要。如果系统里之前装过其他版本的VTK或者OpenNI,它们的路径可能排在前面,导致加载了错误的DLL。我建议把PCL相关的路径移到Path列表的最前面。
另外,3rdParty\OpenNI2\Tools这个路径是给OpenNI2的设备驱动用的,如果你不用Kinect或者Xtion这类深度相机,可以不添加。但加上没坏处。
4.3 验证安装是否成功的命令行测试
环境变量配好后,重启命令行(重要,否则Path不生效),然后输入:
pcl_viewer如果弹出一个小窗口,标题是“PCL Viewer”,说明PCL的运行时环境没问题。如果提示“不是内部或外部命令”,检查Path里有没有C:\Program Files\PCL 1.8.1\bin。
再测试一下PCD文件读取:
pcl_viewer D:\PCL_Data\bunny.pcd如果能看到兔子点云,说明IO模块和可视化模块都正常。如果报错“Failed to find match for field 'x'”,说明PCD文件格式有问题,换一个文件试试。
注意:
pcl_viewer在PCL 1.8.1里是pcl_viewer.exe,有些版本叫pcl_viewer_release.exe。如果找不到,去bin目录下看看实际文件名。
5. VS2013工程属性配置的完整流程
5.1 新建工程与平台选择
打开VS2013,新建一个“Win32控制台应用程序”,命名为PCLTest。在向导里选择“空项目”,不要勾选“预编译头”,因为PCL的头文件里有些和预编译头冲突。
关键:平台选择x64。PCL 1.8.1的All-in-one只有64位版本,如果你用Win32平台编译,链接时会报“模块计算机类型x64与目标计算机类型x86冲突”。在VS顶部的工具栏里,把“解决方案平台”从Win32改成x64。如果没有x64选项,去“配置管理器”里新建一个。
5.2 包含目录与库目录的填写规则
右键工程 → 属性 → 配置属性 → VC++目录。
包含目录添加:
C:\Program Files\PCL 1.8.1\include\pcl-1.8 C:\Program Files\PCL 1.8.1\3rdParty\Boost\include\boost-1_64 C:\Program Files\PCL 1.8.1\3rdParty\Eigen\eigen3 C:\Program Files\PCL 1.8.1\3rdParty\FLANN\include C:\Program Files\PCL 1.8.1\3rdParty\VTK\include\vtk-7.0 C:\Program Files\PCL 1.8.1\3rdParty\Qhull\include C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\Include库目录添加:
C:\Program Files\PCL 1.8.1\lib C:\Program Files\PCL 1.8.1\3rdParty\Boost\lib C:\Program Files\PCL 1.8.1\3rdParty\FLANN\lib C:\Program Files\PCL 1.8.1\3rdParty\VTK\lib C:\Program Files\PCL 1.8.1\3rdParty\Qhull\lib C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\Lib这里有个版本号陷阱:Boost的目录名是boost-1_64,VTK是vtk-7.0,不同PCL版本对应的第三方库版本号不同。如果你装的是PCL 1.7.2,Boost可能是boost-1_58,VTK是vtk-6.2。一定要去实际目录下看一眼文件夹名字,不要照抄网上的教程。
5.3 预处理器定义与链接器输入
在“C/C++ → 预处理器 → 预处理器定义”中添加:
_CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS这两个宏是为了屏蔽PCL头文件里的一些安全警告,不加的话编译时会有大量C4996警告,虽然不影响运行,但看着烦。
在“链接器 → 输入 → 附加依赖项”中添加需要的lib文件。注意Debug和Release要分开配:
Debug版:
pcl_common_debug.lib pcl_io_debug.lib pcl_visualization_debug.lib pcl_search_debug.lib pcl_kdtree_debug.lib pcl_filters_debug.lib pcl_features_debug.lib pcl_registration_debug.lib pcl_segmentation_debug.lib pcl_surface_debug.libRelease版:
pcl_common.lib pcl_io.lib pcl_visualization.lib pcl_search.lib pcl_kdtree.lib pcl_filters.lib pcl_features.lib pcl_registration.lib pcl_segmentation.lib pcl_surface.lib注意:PCL的lib文件命名规则是
模块名_debug.lib对应Debug,模块名.lib对应Release。如果你在Debug模式下链接了Release的lib,会出现“LNK2038: 检测到_RuntimeLibrary的不匹配”错误。这个坑我踩过,排查了一下午才发现是配置管理器里Debug和Release搞混了。
5.4 运行时DLL缺失的排查方法
编译通过后,运行程序如果提示“找不到xxx.dll”,用Dependencies工具(或者VS自带的dumpbin /dependents)查看exe依赖哪些DLL。常见的缺失:
| 缺失DLL | 来源 | 解决方案 |
|---|---|---|
| pcl_common.dll | PCL bin目录 | 确认Path包含PCL 1.8.1\bin |
| vtkCommonCore-7.0.dll | VTK bin目录 | 确认Path包含3rdParty\VTK\bin |
| boost_system-vc120-mt-1_64.dll | Boost lib目录 | 确认Path包含3rdParty\Boost\lib |
| OpenNI2.dll | OpenNI2 Tools目录 | 确认Path包含3rdParty\OpenNI2\Tools |
| msvcr120.dll | VS2013运行时 | 安装VC++ 2013 Redistributable |
最省事的办法:把上述所有bin目录下的DLL复制到exe所在目录。但这样不优雅,还是配Path比较好。
6. 用PCD文件包跑通第一个点云程序
6.1 读取与可视化PCD文件的完整代码
新建一个main.cpp,写入以下代码:
#include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/visualization/cloud_viewer.h> int main(int argc, char** argv) { // 定义点云类型 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 读取PCD文件 if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\PCL_Data\\bunny.pcd", *cloud) == -1) { PCL_ERROR("Couldn't read file bunny.pcd \n"); return (-1); } std::cout << "Loaded " << cloud->width * cloud->height << " data points from bunny.pcd with the following fields: " << std::endl; // 打印前10个点的坐标 for (size_t i = 0; i < 10; ++i) std::cout << " " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl; // 可视化 pcl::visualization::CloudViewer viewer("PCL Viewer"); viewer.showCloud(cloud); while (!viewer.wasStopped()) { // 等待窗口关闭 } return (0); }这段代码做了三件事:加载PCD文件、打印前10个点的坐标、用可视化窗口显示点云。CloudViewer是PCL里最简单的可视化类,适合快速验证。
6.2 编译链接时的常见报错与修复
报错1:fatal error C1083: 无法打开包括文件: "pcl/io/pcd_io.h"
说明包含目录没配好。检查C:\Program Files\PCL 1.8.1\include\pcl-1.8下面有没有pcl文件夹。如果没有,说明PCL安装不完整,重新安装。
报错2:LNK1104: 无法打开文件 "pcl_common_debug.lib"
库目录没配好,或者lib文件名不对。去C:\Program Files\PCL 1.8.1\lib下面看看实际有哪些lib文件。有些版本的Debug lib叫pcl_commond.lib(少个e),这是历史遗留问题。
报错3:LNK2019: 无法解析的外部符号 "public: virtual __cdecl pcl::visualization::CloudViewer::~CloudViewer(void)"
链接器输入里少了pcl_visualization_debug.lib。加上即可。
报错4:程序运行后闪退,没有任何输出
可能是PCD文件路径不对。把路径改成绝对路径,并且用双反斜杠\\或者正斜杠/。另外确认PCD文件不是空的,用记事本打开看看有没有DATA ascii或者DATA binary头。
6.3 点云数据的简单滤波与保存
跑通读取之后,可以试试滤波和保存。下面这段代码对点云做体素栅格降采样,然后保存为新的PCD文件:
#include <pcl/filters/voxel_grid.h> // 创建滤波对象 pcl::VoxelGrid<pcl::PointXYZ> sor; sor.setInputCloud(cloud); sor.setLeafSize(0.01f, 0.01f, 0.01f); // 1cm的体素 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); sor.filter(*cloud_filtered); std::cout << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl; // 保存 pcl::io::savePCDFileASCII("bunny_filtered.pcd", *cloud_filtered);setLeafSize的参数是体素栅格的边长,单位是米。0.01就是1厘米。这个值越小,降采样后点越多,计算越慢。对于兔子这种小模型,0.005到0.01比较合适。对于室内场景,0.05到0.1更合理。
注意:
savePCDFileASCII保存的是文本格式,文件体积大但可读。如果要节省空间,用savePCDFileBinary。但Binary格式在不同字节序的机器上可能不兼容,一般本地用没问题。
7. 那些年我踩过的坑与排查思路
7.1 Debug与Release混用导致的诡异崩溃
这个坑我印象最深。有一次在Debug模式下编译通过,运行到viewer.showCloud(cloud)时直接崩溃,没有任何错误信息。用调试器跟进去,发现崩在VTK的vtkRenderer::AddActor里面。
排查过程:先怀疑是点云数据有问题,换了个PCD文件还是崩。然后怀疑是VTK版本不兼容,重装了VTK还是崩。最后用dumpbin /dependents查看exe依赖的DLL,发现它加载的是vtkCommonCore-7.0.dll(Release版),而我的工程是Debug模式,应该加载vtkCommonCore-7.0d.dll(Debug版)。
根因:Path环境变量里VTK\bin目录下同时有Debug和Release的DLL,系统按文件名匹配,优先找到了Release版。而PCL的Debug lib链接的是Debug版VTK,两者ABI不兼容,导致崩溃。
解决方案:把VTK\bin下的Debug DLL和Release DLL分开放,或者干脆在Debug模式下把Release DLL临时改名。更彻底的办法是,在工程属性里把“调试 → 环境”设置为PATH=C:\Program Files\PCL 1.8.1\3rdParty\VTK\bin\debug;%PATH%,强制优先加载Debug DLL。
7.2 OpenNI2路径错误引发的链接失败
前面提过OpenNI2的默认安装路径问题。这里补充一个细节:即使你把OpenNI2复制到了3rdParty下面,VS工程里的库目录如果还指向C:\Program Files\OpenNI2\Lib,链接时仍然会报错。因为PCL的pcl_io模块在编译时记录的OpenNI2路径是${PCL_ROOT}/3rdParty/OpenNI2,运行时和链接时都按这个路径找。
排查方法:在VS里右键pcl_io_debug.lib→ 属性 → 查看“附加依赖项”里有没有OpenNI2的lib。如果有,说明PCL在编译时已经绑定了路径。你只需要保证3rdParty\OpenNI2下面有对应的Include和Lib文件夹即可。
7.3 PCD文件路径中的中文与空格问题
PCL的loadPCDFile底层用的是std::ifstream,在Windows上对宽字符路径支持不好。如果你的PCD文件放在D:\点云数据\bunny.pcd,即使路径存在,也会返回-1。
解决方案:要么把文件移到纯英文路径,要么用boost::filesystem做路径转换。但后者比较麻烦,不如直接改路径。我一般建一个D:\PCL_Data\目录,所有测试数据都放这里。
另外,路径里的空格也会有问题。C:\Program Files\PCL 1.8.1\这个路径本身带空格,但PCL的安装程序已经处理好了。你自己放数据的时候,避免用带空格的目录名。
7.4 内存泄漏与智能指针的使用建议
PCL大量使用boost::shared_ptr(后来改成std::shared_ptr)。如果你手动new了一个点云对象,忘记delete,就会内存泄漏。但更常见的问题是循环引用:两个shared_ptr互相指向对方,导致引用计数永远不为零。
建议:尽量用PCL提供的::Ptr类型别名,比如pcl::PointCloud<pcl::PointXYZ>::Ptr。创建对象时用new,但不要手动delete,交给智能指针管理。如果需要在多个函数间传递点云,用const引用或者Ptr拷贝,不要传裸指针。
// 推荐 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 不推荐 pcl::PointCloud<pcl::PointXYZ>* cloud = new pcl::PointCloud<pcl::PointXYZ>(); // ... 后面忘了delete8. 从能跑到好用:性能与工程化建议
8.1 编译速度优化:预编译头与并行编译
PCL的头文件非常庞大,一个简单的#include <pcl/visualization/cloud_viewer.h>就会拖入上百个VTK头文件。全量编译一次可能要几分钟。
优化手段:
- 开启多处理器编译:工程属性 → C/C++ → 常规 → 多处理器编译 → 是(/MP)
- 使用预编译头:把常用的PCL头文件放到
stdafx.h里,然后开启预编译头。但注意,PCL的某些模板头文件和预编译头有冲突,需要测试。 - 减少不必要的包含:只包含用到的模块,不要
#include <pcl/pcl.h>这种全量包含。
我实测下来,开启/MP后编译时间从3分钟降到1分钟左右。预编译头能再降到30秒,但配置起来麻烦,适合大型项目。
8.2 点云数据量增大后的内存管理
当点云点数超过百万级时,内存占用会急剧上升。一个PointXYZ是16字节(4个float,但实际对齐后是16字节),100万个点就是16MB。加上法线、颜色、描述子,轻松上GB。
建议:
- 读取大点云后,立即做降采样,减少后续处理的数据量
- 使用
pcl::PointCloud<pcl::PointXYZ>::Ptr而不是栈上对象,避免拷贝 - 及时释放不再使用的点云:
cloud->clear(); cloud->points.shrink_to_fit(); - 如果内存实在不够,考虑分块处理,用
pcl::PCDReader的read函数按偏移量读取部分数据
8.3 将配置固化:属性表与CMake的取舍
每次新建工程都要手动配一遍包含目录、库目录、附加依赖项,非常繁琐。有两种固化方案:
方案A:VS属性表(.props)。在属性管理器里新建一个属性表,把所有配置写进去,以后新建工程直接添加这个属性表即可。优点是简单,缺点是属性表文件在不同机器上路径可能不同,需要手动改。
方案B:CMake。写一个CMakeLists.txt,用find_package(PCL 1.8 REQUIRED)自动查找PCL。优点是跨平台、路径自动解析,缺点是需要额外学习CMake语法,而且VS2013对CMake的支持不如新版VS。
我个人的选择是:小项目用属性表,大项目用CMake。属性表配置一次,导出成.props文件,以后直接导入。CMake适合需要频繁切换编译环境或者多人协作的场景。
cmake_minimum_required(VERSION 3.1) project(PCLTest) find_package(PCL 1.8 REQUIRED) include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS}) add_executable(PCLTest main.cpp) target_link_libraries(PCLTest ${PCL_LIBRARIES})这段CMakeLists.txt在VS2013下用CMake 3.1以上版本生成工程,能自动配好所有路径。但要注意,CMake生成的工程默认是Win32平台,需要手动改成x64。
8.4 版本锁定与团队协作的注意事项
如果你在团队里推广这套环境,一定要把安装包和配置步骤文档化。我见过太多因为版本不一致导致的“在我机器上能跑”问题。
建议做法:
- 把VS2013安装包、PCL All-in-one安装包、PCD测试文件包放在共享目录
- 写一个
setup.md,记录每一步的勾选项和路径 - 导出一份配好的VS属性表,放在共享目录
- 在代码仓库的README里注明环境要求:VS2013 Update 5 + PCL 1.8.1 + x64
另外,不要用“最新版”这种模糊描述。PCL 1.8.1就是1.8.1,Boost 1.64就是1.64。版本号写清楚,省得后面扯皮。
提示:如果团队里有人的机器是Windows 7,注意VS2013 Update 5在Win7上需要先安装.NET Framework 4.5.2。Win10则自带,不用管。
9. 一些零散但有用的经验补充
9.1 如何快速判断PCD文件是ASCII还是Binary
用记事本打开PCD文件,看头部有没有DATA ascii或者DATA binary。ASCII格式可以直接看到坐标数值,Binary格式则是乱码。另外,ASCII格式的文件体积通常是Binary的3到5倍。
如果拿到一个PCD文件但不确定格式,可以用pcl_viewer打开,能显示就说明格式没问题。如果报错“Failed to find match for field”,说明点类型不匹配,比如文件里是PointXYZRGB,但你用PointXYZ去读。
9.2 PCL可视化窗口的交互操作
CloudViewer窗口支持一些快捷键:
r:重置视角+/-:放大缩小- 鼠标左键拖动:旋转
- 鼠标中键拖动:平移
- 鼠标滚轮:缩放
如果窗口一片黑,可能是点云坐标范围太大或太小。按r重置视角试试。如果还是黑,检查点云是否为空。
9.3 点云格式转换的常见需求
PCL支持多种点云格式:PCD、PLY、OBJ、STL等。转换用pcl::io模块的loadPLYFile、savePLYFile等函数。但注意,PLY和OBJ支持网格(Mesh),而PCD只支持点云。从Mesh转点云可以,反过来不行。
// PLY转PCD pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPLYFile("model.ply", *cloud); pcl::io::savePCDFileBinary("model.pcd", *cloud);9.4 遇到编译器内部错误时的应对
VS2013的编译器在处理某些复杂模板时,可能会报fatal error C1001: 编译器中发生内部错误。这不是你的代码问题,是编译器bug。
应对方法:
- 尝试把出错的代码拆分成多个小函数
- 减少模板嵌套层级
- 升级到VS2013 Update 5(如果还没升)
- 如果实在不行,用VS2015编译PCL部分,然后和VS2013的代码混合链接(不推荐,ABI可能不兼容)
我遇到过一次在pcl::registration::CorrespondenceEstimation里报C1001,后来把#include <pcl/registration/icp.h>移到文件最前面就好了。编译器的头文件包含顺序有时会影响模板实例化。
9.5 备份与恢复:配好的环境如何迁移
配好一套VS2013 + PCL环境不容易,建议做备份:
- 导出VS的所有设置:工具 → 导入和导出设置 → 导出所选环境设置
- 备份环境变量:用
set > env_backup.txt导出当前命令行环境 - 备份VS属性表:把
.props文件复制到安全位置 - 记录PCL安装路径和版本号
迁移到新机器时,按同样的顺序安装VS2013、PCL,然后导入设置和属性表。注意新机器的盘符和路径要一致,否则属性表里的绝对路径会失效。
如果路径不一致,可以用文本编辑器批量替换.props文件里的路径。比如把C:\Program Files\PCL 1.8.1替换成D:\PCL 1.8.1。
9.6 关于PCL 1.8.1之后版本的升级考量
如果你哪天决定升级到PCL 1.9.x或更高,需要注意:
- PCL 1.9.x开始只支持VS2015及以上
- 点类型系统有变化,
PointXYZ的内存布局可能不同 - 某些API被标记为deprecated,编译时会有大量警告
- VTK版本从7.0升到8.x,可视化模块的接口有变动
升级不是简单的替换安装包,需要重新编译所有依赖PCL的代码。如果项目不急,建议先在独立分支上测试,确认所有功能正常后再合并。
10. 写在最后:关于这套老组合的几句实话
VS2013 + PCL 1.8.1这套组合,放在今天确实不算“先进”,但它稳定、资料多、坑都被踩得差不多了。对于维护存量项目的开发者来说,能跑通、能编译、能出结果,比什么都重要。
我自己的经验是,配置过程中90%的问题都出在三个地方:路径不对、版本不匹配、Debug/Release混用。把这三个点盯死了,剩下的就是体力活。另外,不要迷信网上的“一键配置脚本”,那些脚本往往针对特定机器环境,换台机器就失效。老老实实按步骤配,配完做备份,才是正道。
如果你在配置过程中遇到了本文没覆盖的问题,我的建议是:先用dumpbin /dependents看依赖,再用Process Monitor看文件加载,最后用调试器跟崩溃点。这三板斧下去,大部分问题都能定位。实在不行,把PCL降级到1.7.2试试,那个版本对VS2013的支持更成熟,只是少了几个新算法。
最后提醒一句:所有安装包和文件包,注意从正规渠道获取,核对文件哈希值,避免下载到被篡改的版本。环境配置这种事,安全第一。