因为PCL库(傻瓜式安装)中自动安装的VTK库并不完整,不支持QT环境的UI界面开发,于是,想用QT在VS2019上开发图形界面程序,需要单独自己通过VTK源码编译安装,再进行配置。本人安装时开发环境已经装好的是VS2019+QT5.15.2+PCL1.12.1,供参考,其他版本基本上大同小异,需要注意的是在自动安装的PCL库中,看到里面VTK库的版本是9.1.0,于是,在源码编译安装VTK过程中,为了保险也用的是9.1.0版本。
4)与QT有关的配置,可以用关键词来搜索相关的配置项,默认都是DEFAULT,咱也不知道这个默认值到底是啥(有兴趣的伙伴可以试试),按照网上说的教程选了WANT,有的版本是只有勾选框,就直接勾选就好了,我这个版本有四个选项(YES,NO,WANT,NO_WANT),我也不知道YES和WANT有啥区别(搜了一下也没找到答案,有知道的大佬欢迎评论指正)。
好了,上面那步的Generate只是生成了VS的解决方案,也就是build里的东西,接下来,点击旁边的“Open Project”,会自动启动Visual Studio并打开Build目录下的解决方案。如下图:
可以看到,上图中,编译类型有四种,跟我们之前在CMake中配置的一样。
最后,得到debug和release的VTK的库,如下:
这两个目录都是自己创建的,内容都是从output中拷出来的。
好了,我们的目的并不是单独为了这个VTK,是因为PCL中的VTK不全(不支持QT),所以,接下来就直接替换,替换前我对比了一下,如下图:
可以看到,右边是我们自己编译安装的,要多一些文件,左边是PCL自带的,很明显少了些东西(除了QT还有啥?没有深究)
然后,因为看了一下PCL中的VTK,里面lib,bin这些目录下,release和debug版本的文件都在一个目录里没有分,索性我也不分了,直接把output中(前面提到了,release和debug的都生成到这个里面了)的文件拷贝过去。
很显然,拷贝的时候会遇到重名的,4261个,跟上图左边的一致,因为两边都是9.1版本的VTK,为了防止这些重名文件跟PCL有啥关联,就没有覆盖,直接跳过重名,相当于只补充多出来的跟QT有关的(或许还有别的?)。
如图,果然是多了一些跟QT有关的库文件。
在VS中创建QT项目,然后添加属性文件,这里也可以直接右键项目编辑属性,但是采用属性文件的方式,有利于项目配置的复用(毕竟配置一次完整的PCL相关库需要添加很多lib文件)。具体操作步骤如下图:
注意这里debug版本的和release版本的需要分别添加。具体VS项目属性文件的有关教程可以网上自行搜索,这里照着后面接着做即可。
创建好后双击,即可打开项目属性设置窗口,这个窗口是针对该项目属性文件的,配置好后,以后新建项目或者其他项目需要用到PCL库release或者Debug版的属性配置,只需要添加这个属性文件即可。
插曲:OpenNI2的安装
在直接自动安装的PCL1.12.1目录里面,发现OpenNI2目录中居然是空的(只有安装程序,好像是直接给装到C盘去了?),后面包含目录和库目录可是要用到的啊!于是直接在目录中安装,如果显示已经有了OpenNI,需要先用清除选项清除,然后再一次运行安装程序就可以了,如下图:
照惯例,安装目录只要能修改,就修改成我们想要的,我直接修改成了当前的PCL中的OpenNI2的目录,安装完成以后是这样的:
系统环境变量跟着这个新安装的目录改一下就好,我也不知道为什么之前安装PCL的时候系统环境变量虽然添加了OpenNI2,但是目录却是C盘的而不是PCL的安装目录。
包含目录的设置
可以通过属性配置窗口的“C/C++"—>”常规“中的附加包含目录,也可以通过”VC++目录“中的”包含目录“进行添加,添加结果如下:
注意事项:上图中pcl、boost等几个库的包含目录一直写到了”……\pcl“(以pcl为例),后来写代码的时候发现,最好是写到前一级目录即可(或者加一个前一级目录,按我自己这个例子,就是写到D:\My3rdLib\PCL 1.12.1\include\pcl-1.12),为什么?因为这些包含目录里的.h头文件很多,我们开发的时候实际也不会只用这一两个库(可能有一大堆),这些库里面的很多头文件都并没有带自己的库名称,所以为了更好地区分和阅读代码,在引用pcl的库的时候(其他库也是一样),更习惯于用#include
之类的写法,如果包含目录像上图那样写,就只能写成#include<****.h>
,万一有些库里面出现了同名头文件,还会让编译器混淆。
链接器——输入——附加依赖项
这个设置算是最麻烦的一步了,主要是因为要添加的lib文件太多了。更麻烦的是,有很多库文件,是要区分debug版和release版的,光vtk有200多个(release的和debug的各100多个,关键咱这还是专门为了它而来)。网上很多教程给了批处理的代码,这里自己完善了一下,如下图,一次性把pcl和里面各种第三方库.lib文件的文件名都分别提取到.txt中,便于复制粘贴,有一些库的debug版本和release版本文件可以很容易用代码区分,就分别存到不同的.txt中(release后缀r,debug后缀d),部分库区分不易,就都在一起了,后缀rd,提取完了以后再手动区分,如下图:
批处理的代码如下(路径可以根据自己需要修改):
dir "D:\My3rdLib\PCL 1.12.1\lib\*.lib" /b > libs_pcl_rd.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\Boost\lib\*mt-gd-x64-1_78.lib" /b > libs_boost_d.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\Boost\lib\*mt-x64-1_78.lib" /b > libs_boost_r.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\FLANN\lib\*.lib" /b > libs_flann_rd.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\OpenNI2\Lib\*.lib" /b > libs_openni2_rd.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\Qhull\lib\*.lib" /b > libs_qhull_rd.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\VTK\lib\*1.lib" /b > libs_vtk_r.txt
dir "D:\My3rdLib\PCL 1.12.1\3rdParty\VTK\lib\*d.lib" /b > libs_vtk_d.txt
为了方便,上传了我自己的批处理程序文件和处理好(自动提取+手动整理)的结果,跟我这篇记录的版本完全一致的,想偷懒的,直接用压缩包里面libs_pcl_3rdpart_all_d.txt
和libs_pcl_3rdpart_all_r.txt
(后缀r的是release的,后缀d的是debug的)这两个文件中的内容即可,是pcl相关所有库的lib文件整理合并之后的,直接粘贴到vs的项目属性配置的链接器——输入——附加依赖项里就行了。
点击下载提取文件名批处理程序及处理结果
QVTK显示控件
根据网上说的,在VTK9.0以后没有QT插件了,需要通过OpenGL Widget来提升,如下图:
点击提升为后,在窗口中填写提升的类名称为QVTKOpenGLNativeWidget
,下面的头文件会自动填充。
点击提升完成后,修改该控件的Object Name为自己需要的,我这里是修改为qvtkWidget了,如下图:
回到Visual Studio以后,进入”ui_*****.h"这个特殊的头文件(QT自动生成的UI界面的头文件)会发现自动添加了上述头文件,控件的定义也添加进去了,如图:
读取点云(仅以.ply数据读取为例)
回到Visual Studio,代码中添加如下头文件:
#include //用来读取.ply格式的点云
#include //用于点云变量定义
然后在自己希望的地方添加如下读取代码:
pcl::PointCloud<pcl::PointXYZ>::Ptr myCloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPLYFile<pcl::PointXYZ>("D:\\Users\\YeL313\\Downloads\\bunny.ply", *myCloud) == -1) {
QMessageBox::information(NULL, "Title", "read failed!");
}
else {
QMessageBox::information(NULL, "Title", "read completed!");
}
#include
#include
#include
然后添加如下代码显示点云:
//创建渲染器
vtkRenderer* ren = vtkRenderer::New();
//创建渲染窗口
vtkGenericOpenGLRenderWindow* renderWindow = vtkGenericOpenGLRenderWindow::New();
//创建pcl显示器并与VTK的渲染器和渲染窗口绑定
pcl::visualization::PCLVisualizer::Ptr pclViewer(new pcl::visualization::PCLVisualizer(ren,renderWindow,"viewer", false));
//渲染窗口与qvtkWidget绑定
ui.qvtkWidget->setRenderWindow(pclViewer->getRenderWindow());
//添加点云数据
pclViewer->addPointCloud(myCloud,"cloud");
//刷新控件(如果是第一次载入点云,点云没有变更,可以不加下面这句)
ui.qvtkWidget->update();
网上找到一些代码,但是有很多显示不出来,不知道是不是我没用对,还有一些用VTK来读取点云的或者一些比较复杂的,就没去深究,想用最简单的方法来显示,就折腾了这么几句代码,根据自己的理解写了注释,如有错误,欢迎指正。以后关于更加详细和复杂的点云操作和显示,再另外开帖,这篇主要是讲VTK的编译和配置,这个代码的折腾纯粹为了测试一下配置好了没。