ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

QT5.9.6与PCL1.8.1在VS2015下的点云显示Demo配置指南

QT5.9.6与PCL1.8.1在VS2015下的点云显示Demo配置指南 简介面向需要在VS2015中整合QT5.9.6与PCL1.8.1进行3D点云应用开发的工程师与学生这份Demo工程提供了完整的集成示例可减少自行配置和摸索的时间。项目共27个文件包含pro工程配置、5个cpp源文件、4个头文件、UI界面、资源文件及可直接运行的exe压缩包仅233KB便于下载后快速对照学习。配套代码演示了QT界面与PCL库的衔接方式涵盖点云数据读取、去噪预处理、PCA特征提取、PCLVisualizer可视化等关键步骤同时体现了多线程调用和Qt-pro文件依赖配置等工程细节。资源已有2356人学习适合希望缩短环境搭建周期、快速掌握QTPCL协作开发路径的入门与进阶开发者。 QT5.9.6、PCL1.8.1、VS2015这三个版本号放一起第一眼像是一套十年前的老古董但搞过Windows点云桌面开发的人都知道这套组合到今天依然是很多项目的起跑线。PCL作为工业界最常用的点云处理库在Windows上最省事的预编译版本就是基于VS2015构建的1.8.1QT5.9.6则是和它配合最稳定的LTS界面框架。这篇内容要聊的就是怎么用VS2015把这几样东西拧到一起写出一个能打开、显示、自由缩放旋转点云的软件demo并解决从环境配置、工程属性到打包发布的全过程问题。无论你是刚接触PCL的学生还是要给设备做上位机软件的工程师这套流程都值得完整过一遍很多坑我提前帮你踩完了。1. 版本搭配为什么非得是5.9.6、1.8.1、VS20151.1 编译器与预编译库的锁死关系PCL在Windows上有两条路用CMake从源码自己编译一套或者直接用官方分发版。自己编译PCL耗时两三个小时起步中间要处理Boost、VTK、Qhull、FLANN等一堆第三方库任何一个版本号对不上编译期错误能刷屏几百行脾气再好的人也会被磨没。所以绝大多数情况下正确选择是直接使用官方1.8.1的AllInOne安装包装完以后PCL本体以及自带第三方库全部是已经编译好的二进制文件。关键点来了这套预编译的二进制由哪个编译器生成你就必须用哪个编译器去链接。PCL 1.8.1 AllInOne的编译工具链对应MSVC2015也就是VS2015。C不同于其他语言二进制接口没有稳定的ABI规范不同编译器版本编出来的.lib和.dll混合使用时会出现大量莫名其妙的外部符号错误。虽然MSVC14.x系列从VS2015到VS2019理论上可以互相链接可实际项目里用VS2017或VS2019去链接官方PCL包总会蹦出几个版本不匹配或者类型重定义的报错而VS2015是唯一能保证全程绿灯的选择。所以我建议别再纠结编译器新旧直接装VS2015整套环境都会安静很多。1.2 QT版本的选择逻辑QT这边我选5.9.6原因也和版本咬合有关。PCL 1.8.1自带的VTK 7.1里GUI支持模块是按QT 5.9这个时代编译的官方的qt-opensource-windows-x86-msvc2015_64-5.9.6安装包内部DLL、插件和编译路径全部对得上。你可能会问直接用QT 5.12或者5.15行不行我试过纯QT工程没问题但一旦涉及PCL可视化器和QVTKWidget的桥接新老版本之间经常出现渲染窗口初始化失败、控件白屏、或者点击几下就崩溃的情况。QT 5.9.6虽然看起来老但它是LTS分支社区里围绕这个版本的踩坑文档特别多出问题基本一搜就有答案。做项目稳定压倒一切没必要为了追新给自己挖坑。下载QT 5.9.6的话官方archive可以直接找到安装包国内用清华或阿里镜像下载会快很多。1.3 demo到底解决什么问题这套demo要解决的核心问题就三个。第一把PCL的点云处理能力集成进QT界面这是Windows桌面点云软件的基本形态第二实现最基本的PCD文件加载与点云显示支持鼠标拖拽旋转、缩放查看第三能正常打包移植到一台全新的Windows电脑上运行而不是只在开发机上活蹦乱跳。搞清楚这三个目标后面所有配置步骤都有了参照遇到问题时也知道该往哪个方向查。2. 环境搭建与工程配置一步步来2.1 安装包与目录规划先装VS2015社区版就够用重点要装C桌面开发组件。然后是QT 5.9.6的MSVC2015 64位安装包再装PCL 1.8.1 AllInOne。PCL安装时路径我建议放在默认的C盘Program Files下路径里带空格没关系官方包一直这么用的。安装过程中如果提示OpenNI2相关选项一并勾上后面做深度相机点云获取时会用到。装完以后记住两个关键目录即可QT目录C:\Qt\Qt5.9.6\5.9.6\msvc2015_64PCL目录C:\Program Files\PCL 1.8.1这两个目录内部的结构要心里有数。QT目录下bin里放的是QT运行库和designer等工具plugins里是各种平台插件。PCL目录下除了include和lib还有一个3rdParty文件夹里面就是Boost、VTK、Qhull、FLANN这些依赖库后面的工程配置全都要用到。2.2 环境变量和PATH安装完成后首选建议手动配置环境变量不要图省事勾选安装器自带的添加到PATH选项。打开系统环境变量设置新建一个系统变量PCL_ROOT指向PCL安装目录然后在Path变量中追加以下路径C:\Qt\Qt5.9.6\5.9.6\msvc2015_64\bin 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\FLANN\bin C:\Program Files\PCL 1.8.1\3rdParty\Qhull\bin这里有一个很常见的问题有人为了省事把PCL的整个3rdParty目录全都塞进PATH结果系统启动后出现多个同名DLL冲突好几个软件直接打不开。PATH只加bin级别的目录就够了不要加更上层。配置完环境变量后务必重启一次否则新开的终端和IDE读不到。如果你用的是Qt Creator而不是VS2015还要在Qt Creator的构建套件设置里把上述路径填到环境一栏否则程序一运行就报找不到DLL。2.3 新建工程链接库与属性配置打开VS2015新建一个Qt Widgets Application工程。在VS2015里用QT需要先装一个Qt VS Tools插件插件装好后VS菜单栏会多出一个Qt VS Tools项在里面把QT Version指向刚才的QT目录即可。工程建好之后打开项目属性页配置以下内容。首先是包含目录对应VC目录里的Include Directories或者属性页里的C/C - Additional Include Directories。一套最小可用的清单如下C:\Qt\Qt5.9.6\5.9.6\msvc2015_64\include C:\Program Files\PCL 1.8.1\include\pcl-1.8 C:\Program Files\PCL 1.8.1\3rdParty\boost\include\boost-1_61 C:\Program Files\PCL 1.8.1\3rdParty\VTK\include\vtk-7.1 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\Qhull\include然后是库目录C:\Qt\Qt5.9.6\5.9.6\msvc2015_64\lib 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\VTK\lib C:\Program Files\PCL 1.8.1\3rdParty\Qhull\lib最后是附加依赖项。这一步最头疼因为PCL依赖的模块实在太多。只做点云加载和可视化的话Release版本加这些就够了pcl_common.lib pcl_io.lib pcl_visualization.lib pcl_filters.lib pcl_features.lib pcl_search.lib pcl_kdtree.lib pcl_sample_consensus.lib pcl_segmentation.lib pcl_registration.lib pcl_surface.lib vtkCommonCore-7.1.lib vtkCommonDataModel-7.1.lib vtkCommonMath-7.1.lib vtkCommonMisc-7.1.lib vtkCommonSystem-7.1.lib vtkCommonTransforms-7.1.lib vtkRenderingCore-7.1.lib vtkRenderingLOD-7.1.lib vtkRenderingOpenGL2-7.1.lib vtkInteractionStyle-7.1.lib vtkInteractionWidgets-7.1.lib vtkFiltersCore-7.1.lib vtkFiltersGeneral-7.1.lib vtkFiltersSources-7.1.lib vtkImagingCore-7.1.lib vtkImagingSources-7.1.lib vtkGUISupportQt-7.1.lib libboost_system-vc140-mt-1_61.lib libboost_filesystem-vc140-mt-1_61.lib libboost_thread-vc140-mt-1_61.lib libboost_date_time-vc140-mt-1_61.libDebug模式下绝大多数库名会多出一段标记比如PCL的pcl_common-gd.libVTK的vtkCommonCore-7.1-gd.libBoost的libboost_system-vc140-mt-gd-1_61.lib。千万别把Release的库抄到Debug工程里最常见的LNK2019就是这样来的。有一个技巧把这份配置存成一个props属性表文件右键工程属性页上的属性表选择添加新属性表并保存。以后再建PCL项目直接添加现有属性表秒级完成配置无需重新输入几十条路径。3. 第一个点云显示demo核心代码逐段拆3.1 把PCL可视化器嵌到QT界面里PCL自带的PCLVisualizer底层依赖VTK而VTK要显示在QT窗口里靠的是一个老牌桥接组件QVTKWidget。这个控件在PCL 1.8.1配VTK 7.1这套组合里是原生的用起来非常稳定。在UI设计器里如果工具里找不到QVTKWidget控件不用慌很可能是VTK的Qt插件没注册到QT Designer直接在代码里创建并塞进布局就行。在MainWindow的头文件里声明可视化器指针#pragma once #include QMainWindow #include QVTKWidget.h #include pcl/visualization/pcl_visualizer.h namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent 0); ~MainWindow(); private slots: void on_openButton_clicked(); private: Ui::MainWindow *ui; pcl::visualization::PCLVisualizer::Ptr viewer; void setupCloudViewer(); };构造函数里完成初始化#include mainwindow.h #include ui_mainwindow.h #include QFileDialog #include QMessageBox #include pcl/io/pcd_io.h #include pcl/point_types.h MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui-setupUi(this); setupCloudViewer(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::setupCloudViewer() { // 第二个参数false很关键不启用PCL自己的交互线程交给QT事件循环 viewer.reset(new pcl::visualization::PCLVisualizer(viewer, false)); ui-qvtkWidget-SetRenderWindow(viewer-getRenderWindow()); viewer-setupInteractor(ui-qvtkWidget-GetInteractor(), ui-qvtkWidget-GetRenderWindow()); ui-qvtkWidget-update(); }这里有个细节值得多说一句PCLVisualizer构造函数的第二个参数传false是要把渲染和交互全部纳入QT的窗口系统管理否则可能抢QT主线程出现窗口卡死或者退出时崩溃。这种崩溃很难定位网上大量程序关闭时异常的提问基本都出在这里。3.2 加载PCD文件并刷新显示在窗口上放一个按钮点击后弹出文件选择框选一个PCD文件加载并显示。核心代码如下void MainWindow::on_openButton_clicked() { QString file QFileDialog::getOpenFileName( this, 打开点云文件, , PCD文件(*.pcd);;PLY文件(*.ply)); if (file.isEmpty()) return; pcl::PointCloudpcl::PointXYZ::Ptr cloud( new pcl::PointCloudpcl::PointXYZ); if (pcl::io::loadPCDFilepcl::PointXYZ(file.toStdString(), *cloud) -1) { QMessageBox::warning(this, 错误, PCD文件加载失败); return; } viewer-removeAllPointClouds(); viewer-addPointCloudpcl::PointXYZ(cloud, cloud); viewer-resetCamera(); ui-qvtkWidget-update(); }loadPCDFile返回-1表示解析失败这个返回值必须检查。addPointCloud之前要removeAllPointClouds清空旧点云防止残留。resetCamera的作用是让观察视角自适应点云包围盒不然载入一坨离得很远的点后画面经常一片黑容易误以为是程序坏了。3.3 显示效果微调与多格式支持默认方式显示的点云是白色小点想看颜色和调节大小可以这样pcl::visualization::PointCloudColorHandlerCustompcl::PointXYZ color( cloud, 0, 255, 0); viewer-addPointCloudpcl::PointXYZ(cloud, color, cloud); viewer-setPointCloudRenderingProperties( pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, cloud);如果点云带RGB信息用PointXYZRGB类型数据里本来就包含颜色就不需要手动指定色彩处理器了。加载PLY格式也是类似流程把loadPCDFile换成loadPLYFile即可。另外一定别忽略在代码里及时调用update()这个函数负责把VTK渲染窗口的更新请求转发给QT绘制事件忘记调用的时候窗口会一直显示旧画面。3.4 运行库与Debug/Release切换的坑工程配置里有一个最容易出错的地方运行库模式。在项目属性页的C/C - 代码生成 - 运行库里Debug版本应该设置为多线程调试DLL/MDdRelease版本设置为多线程DLL/MD。这个参数必须和PCL预编译库一致。官方PCL 1.8.1是按照动态CRT编译的如果你的工程勾选了/MTd或者/MT链接时会抛出一大堆LNK2038错误提示RuntimeLibrary不匹配。这个错和代码本身没有任何关系纯粹是运行时环境没对齐。我自己第一次遇到整整折腾了一下午才意识到只是下拉框里一个选项的问题写出来希望大家少走这个弯路。4. 打包发布与高频故障排查实录4.1 windeployqt打包一步都不能少开发机上跑得好好的拿到别的电脑上一双击就各种弹窗这是所有QT程序发布都会遇到的问题。QT官方给了windeployqt工具直接用命令行部署。在Release模式下编译完demo后把生成的exe单独放到一个目录然后打开命令行执行cd /d D:\dist C:\Qt\Qt5.9.6\5.9.6\msvc2015_64\bin\windeployqt.exe demo.exewindeployqt会把QT相关的运行库、platforms插件、样式插件等自动拷贝到exe同级目录下。但注意它只处理QT依赖PCL、VTK、Boost这些第三方库它管不着必须手动复制。最简单粗暴的做法是把三个bin目录里的DLL都复制过来copy /Y C:\Program Files\PCL 1.8.1\bin\*.dll . copy /Y C:\Program Files\PCL 1.8.1\3rdParty\VTK\bin\*.dll . copy /Y C:\Program Files\PCL 1.8.1\3rdParty\Qhull\bin\*.dll . copy /Y C:\Program Files\PCL 1.8.1\3rdParty\FLANN\bin\*.dll .最后再用dumpbin查看一下exe的依赖确认没有遗漏项。在VS2015的开发者命令行里执行dumpbin /dependents demo.exe看输出里是否还有第三方库带绝对路径如果有就从对应bin目录补拷进去。发布目录会有大量DLL几十MB甚至上百MB都正常这是PCL工程的常态不用刻意精简到极致除非你有洁癖。4.2 no qt platform plugin could be initialized完全解析这个错误几乎成了QT程序发布的代名词标题里的热门搜索词也和它紧密相关。它的完整提示一般是This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.每次看到这个提示先检查exe同级目录下有没有platforms文件夹里面有没有qwindows.dll。qwindows.dll是QT在Windows平台的底层窗口插件QT程序启动时必须通过它创建窗口。windeployqt正常情况下会自动生成platforms目录并放入对应版本的qwindows.dll但如果你的exe目录和QT的bin目录混着多个QT版本或者手动拷贝时拷了其他版本的qwindows.dll过来就等着报错吧。判断方法也很简单platforms目录里放着的qwindows.dll必须和exe所使用的QT版本完全对应。QT5.9.6的程序不能用QT5.15的platform插件哪怕只差一个小版本也可能起不来。解决时不要想着文件一样应该通用直接用刚才的windeployqt重新部署一遍这是最稳妥的。如果客户电脑上装过其他QT程序也要注意PATH环境变量里是否被指向了别的QT目录运行时优先搜索PATH里的QT很容易覆盖程序自带的那一份。4.3 常见报错速查表把我在这个组合下遇到的高频问题整理成一张速查表建议截图保存报错或现象直接原因处理方法LNK2019/LNK2001 无法解析的外部符号附加依赖项缺失或Debug/Release的库混用按前面清单补全lib检查是否误用带gd或不带gd的库LNK2038 RuntimeLibrary不匹配工程的运行库模式和PCL库不一致统一改为/MDdDebug或/MDRelease启动时提示找不到DLLPATH未配置或发布包缺少三方DLL开发机配PATH发布机补拷PCL、VTK、Boost的DLLno qt platform plugin could be initialized缺少platforms/qwindows.dll或版本不匹配用windeployqt重新部署注意QT版本一致性程序退出时崩溃PCLVisualizer开了独立交互线程构造时传false走QVTKWidget统一管理README里出现QVTKWidget无法拖入UI设计器VTK的QtDesigner插件未注册把VTK plugin目录下的QVTKWidgetPlugin.dll拷到QT的plugins/designer目录4.4 一些发布和验收心得发布完成后强烈建议找一台全新的、没装过QT和PCL的干净电脑或者直接开个虚拟机把整个发布目录拷贝过去运行一遍。这一步能筛出开发机上永远不会暴露的依赖缺失问题。还有一个容易疏漏的点工程是64位那发布目录里的所有DLL也必须是64位版本32位程序搭配64位插件是起不来的报错通常还是no qt platform plugin那一套。最后再分享一个实用习惯。我会把这个demo工程直接当作模板保留以后每次做点云相关的新项目复制一份工程目录改改界面和业务逻辑就开工。版本、库、属性配置全部验证过环境问题几乎为零。这套组合虽然版本偏老但三个软件相互咬合得很紧密一旦配置正确开发体验其实相当省心。真遇到问题对照上面这张速查表逐项排查绝大多数都能在一小时内搞定。本文还有配套的精品资源点击获取
返回列表