PCL点云库、Qt、VS联合配置
一、PCL部分
1.PCL下载
- AllInOne是PCL安装包,该包包含了PCL中所使用的全部第三方编译包,除了Qt编译包;
- pdb是PCL包对应PDB文件包,用于后期单步调试时使用;
- source是PCL源码包,可以通过Cmake进行二次编译,生成对应编译器的运行包。
下载AllInOne 以及 pdb。
2.PCL安装
- 点击AllInOne以管理员运行进行安装
- 一直选择下一步,选择“Add PCL to the system PATH for all users”,它可以自动添加系统路径
- 安装路径注意不要有空格 如:
“C:\PCL 1.11.1”,“C:\PCL1.11.1” - 中间可能会跳出openNI2的安装,若不跳出,则需在安装PCL后自行在“PCL安装路径\3rdParty\OpenNI2”文件夹下点击安装包进行安装,openNI2安装路径为openNI2安装包所在文件夹 如:“C:\PCL 1.11.1\3rdParty\OpenNI2”。
- 解压之前下载好的PBD文件到 “PCL安装路径\PCL 1.11.1\bin”文件夹下
3.设置PCL环境变量:
- 编辑系统变量中的:PCL_ROOT 值设置为PCL安装路径,如“C:\PCL1.11.1”
- 编辑系统变量中的:Path 值 添加如下路径 :
%PCL_ROOT%\bin;
%PCL_ROOT%\3rdParty\FLANN\bin;
%PCL_ROOT%\3rdParty\VTK\bin;
%PCL_ROOT%\3rdParty\Qhull\bin;
%PCL_ROOT%\3rdParty\OpenNI2\Tools
- 注销或者重启计算机使环境变量生效。
二、Qt部分
1.Qt下载
2.Qt安装
- 以管理员进行安装,安装过程中需要注册Qt账号,注册好后即可继续安装
- 组件选择是安装重点:勾选安装 MSVC 组件,其中若无“MSVC 2019 64-bit”组件,则选择“MSVC 2017 64-bit”组件,也可于vs2019编译。 Qt 组件建议全部勾选,防止后期缺少补充比较麻烦。
3.Qt设置环境变量
- 打开系统环境变量 Path :看Qt是否已在安装过程中自动添加路径,若无,则手动添加如下路径
Qt安装路径\
Qt安装路径\msvc2017_64\bin
三、VTK部分
前面安装PCL时有讲到过,PCL默认的三方库中是没有编译好的Qt库的,(默认的3rdParty中的VTK是没有Qt相关的)因此需要下载与已安装好的PCL版本对应的VTK库,然后自行编译出相关的VTK库以及QT插件。
1.VTK下载
VTK 与PCL 版本对应关系可自行百度
2.VTK编译
- 下载cmake官网下载地址,并安装
- 解压下载好的VTK
- 打开安装好的Cmake 软件,选择好路径,source路径是解压好的VTK路径,build路径是cmake后生成的sln文件路径,文件夹自建,文件名以及路径不可存在中文。

- 点击Add Entry,添加CMAKE_DEBUG_POSTFIX, Value设置为 -gd (用来区别debug和release版本)

- 点击config 选择版本

- CMAKE_INSTALL_PREFIX设置编译后的VTK路径
取消勾选BUILD_TESTING,无需编译测试项目
勾选VTK_Group_Qt,编译Qt
点击config继续 - 显示找到的Qt路径,则点击config继续,否则请检查Qt是否正确安装

- 待所有选项无红色(设置都正确),点击Generate,生成sln文件,用VS管理员权限打开生成的sln文件(此文件在cmake 设置路径时的 build 路径下),若无管理员权限则可能编译sln不通过,或install时报错。
- 打开sln文件后

选择好要编译的VTK版本
右键 ALL_BUILD ,点击“生成”,开始编译,编译时常视电脑配置决定,半小时到2小时,编译好后,右键 INSTALL,生成编译好的VTK,生成好的VTK在 cmake 设置中 :“CMAKE_INSTALL_PREFIX设置编译后的VTK路径”下
- 将编译好的VTK替换掉原有在 “PCL安装路径\3rdParty\VTK”文件夹内容,并打开\plugins\designer文件夹,将文件夹下的 QVTKWidgetPlugin.dll 文件复制到
“Qt安装目录\msvc2017_64\plugins\designer”
- 打开qt designer

在QVTK栏中存在QVTKWidget,则Qt与VTK配置成功。
四、VS部分
1. VS 与 PCL
- 新建c++空白项目,在属性管理器的相应位置下新建属性表:PCLRelease64

- 双击进行编辑

- 在 VC++目录 \包含目录 输入(这些都为PCL编译时所要用到的头文件,PCL_ROOT已经在PCL配置环境变量的时候设置,因此VS能自动识别引用路径,其他版本可根据PCL安装路径下各个文件名自行修改)
$(PCL_ROOT)\include\pcl-1.11;
$(PCL_ROOT)\3rdParty\Eigen\eigen3;
$(PCL_ROOT)\3rdParty\Qhull\include;
$(PCL_ROOT)\3rdParty\FLANN\include;
$(PCL_ROOT)\3rdParty\OpenNI2\Include;
$(PCL_ROOT)\3rdParty\VTK\include\vtk-8.2;
$(PCL_ROOT)\3rdParty\Boost\include\boost-1_74;
- 在 VC++目录 \库目录 输入(这些都为PCL编译时所要用到的库文件)
$(PCL_ROOT)\lib;
$(PCL_ROOT)\3rdParty\VTK\lib;
$(PCL_ROOT)\3rdParty\Qhull\lib;
$(PCL_ROOT)\3rdParty\Boost\lib;
$(PCL_ROOT)\3rdParty\FLANN\lib;
$(PCL_ROOT)\3rdParty\OpenNI2\Lib;
- 在 链接器 \输入\附加依赖项 输入上步骤引用的库目录路径下的各个lib文件的文件名(这些都为PCL编译时所要用到的库文件),根据之前cmake编译步骤4中描述:

可知,lib文件名后缀有 -gd 的为debug版本,若无则为release版本,在输入时需要根据需求选择输入。
$(PCL_ROOT)\lib 路径下的文件名(添加时注意添加时候区分debug、release版本):
$(PCL_ROOT)\3rdParty\VTK\lib 路径下的文件名:
$(PCL_ROOT)\3rdParty\Qhull\lib 路径下的文件名:
$(PCL_ROOT)\3rdParty\Boost\lib 路径下的文件名:
$(PCL_ROOT)\3rdParty\FLANN\lib 路径下的文件名:
$(PCL_ROOT)\3rdParty\OpenNI2\Lib 路径下的文件名:
- 测试代码 ,其中测试文件room_scan1.pcd、room_scan2.pcd 官网下载地址,放在项目根目录下
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/ndt.h> // NDT配准
#include <pcl/filters/approximate_voxel_grid.h> // 体素滤波
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/console/time.h>
using namespace std;
int
main(int argc, char** argv)
{
pcl::console::TicToc time;
// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr source_cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("room_scan2.pcd", *source_cloud);
pcl::io::loadPCDFile<pcl::PointXYZ>("room_scan1.pcd", *target_cloud);
if (source_cloud->empty() || target_cloud->empty())
{
cout << "请确认点云文件名称是否正确" << endl;
return -1;
}
else {
cout << "从目标点云读取 " << target_cloud->size() << " 个点" << endl;
cout << "从源点云中读取 " << source_cloud->size() << " 个点" << endl;
}
//将输入的源点云过滤到原始尺寸的大概10%以提高匹配的速度。
pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
approximate_voxel_filter.setInputCloud(source_cloud);
approximate_voxel_filter.setLeafSize(0.5, 0.5, 0.5);
approximate_voxel_filter.filter(*filtered_cloud);
cout << "Filtered cloud contains " << filtered_cloud->size() << " data points " << endl;
// -------------NDT进行配准--------------
time.tic();
pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;
ndt.setStepSize(0.5); // 为More-Thuente线搜索设置最大步长
ndt.setResolution(2); // 设置NDT网格结构的分辨率(VoxelGridCovariance)
ndt.setMaximumIterations(35); // 设置匹配迭代的最大次数
ndt.setInputSource(filtered_cloud); // 设置要配准的点云
ndt.setInputTarget(target_cloud); // 设置点云配准目标
ndt.setTransformationEpsilon(0.001); // 为终止条件设置最小转换差异
//-------------计算变换矩阵--------------
//设置使用机器人测距法得到的初始对准估计结果
Eigen::AngleAxisf init_rotation(0.6931, Eigen::Vector3f::UnitZ());
Eigen::Translation3f init_translation(1.79387, 0.720047, 0);
Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix();
//计算需要的刚体变换以便将输入的点云匹配到目标点云
pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>);
ndt.align(*output_cloud, init_guess);
cout << "NDT has converged:" << ndt.hasConverged()
<< " score: " << ndt.getFitnessScore() << endl;
cout << "Applied " << ndt.getMaximumIterations() << " NDT iterations in " << time.toc() << " ms" << endl;
cout << "变换矩阵:\n" << ndt.getFinalTransformation() << endl;
//使用变换矩阵对未过滤的源点云进行变换
pcl::transformPointCloud(*source_cloud, *output_cloud, ndt.getFinalTransformation());
//保存转换的源点云
//pcl::io::savePCDFileASCII("30.00.pcd", *output_cloud);
//-------------点云可视化----------------
boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("3D-NDT Registration"));
viewer->setBackgroundColor(0, 0, 0);
//对源点云着色并可视化
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>source_color(source_cloud, 0, 0, 255);
viewer->addPointCloud<pcl::PointXYZ>(source_cloud, source_color, "source cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "source cloud");
//对目标点云着色(红色)并可视化
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(target_cloud, 255, 0, 0);
viewer->addPointCloud<pcl::PointXYZ>(target_cloud, target_color, "target cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target cloud");
//对转换后的源点云着色(绿色)并可视化
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>output_color(output_cloud, 0, 255, 0);
viewer->addPointCloud<pcl::PointXYZ>(output_cloud, output_color, "output cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "output cloud");
// 启动可视化
//viewer->addCoordinateSystem(0.1);
//viewer->initCameraParameters();
// 等待直到可视化窗口关闭。
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
测试结果:
2. VS 与 QT
- 点击VS 菜单栏 工具\扩展和更新 ,在弹出窗体的联机搜索框中输入 Qt Visual Studio Tools

- 点击VS 菜单栏 工具\Qt VS Tools\Qt Versions

- 添加Qt Versions

- 重启VS即可

版权声明:本文为weixin_42872983原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。