VTK源码编译安装记录与教程(VS2019+QT5.15.2+PCL1.12.1+VTK9.1.0配置,超详细)
因为PCL库(傻瓜式安装)中自动安装的VTK库并不完整,不支持QT环境的UI界面开发,于是,想用QT在VS2019上开发图形界面程序,需要单独自己通过VTK源码编译安装,再进行配置。本人安装时开发环境已经装好的是VS2019+QT5.15.2+PCL1.12.1,供参考,其他版本基本上大同小异,需要注意的是在自动安装的PCL库中,看到里面VTK库的版本是9.1.0,于是,在源码编译安装VTK过程中,为了保险也用的是9.1.0版本。
下载VTK源码:
-
下载VTK源码
VTK官网下载链接,点击进入找到源码地址,找到官方在gitlab上的官方仓库,根据自己需要的版本下载源码。
进入gitlab官方仓库,点击标签
找到自己需要的版本进行下载
-
下载安装CMake
进入CMake官网进行下载,Windows系统下载二进制的安装文件直接点击就可以安装。
用CMake编译源码
- 准备好以下空目录,并把下载到的源码解压到VTK-Source中(目录命名仅作参考,读者可根据自己情况定义,但是建议目录中不要有中文字符,避免出现字符编码问题)
- 打开CMake-GUI
我是以管理员身份运行的CMake,不知道是不是必须条件,没有试过,运行后首先配置路径:
- 勾选grouped和advanced这两个选项(为了configure之后显示的结果进行分组归整,容易查看),再点击configure选择合适的编译器,点击Finish开始进行编译。
- 经过一定时间的等待,可以看到有很多红色选项是需要手动去检查或设置的,大家不要被一堆红色吓到了,这里的红色并不是报错了,只是编译器检测到了有这么多项需要配置,根据需要核查和设置几个最主要的项就行了。
- 配置关键属性项
1) BUILD_SHARED_LIBS 这个默认是勾选的,如果没勾选,勾选即可,作用是生成动态链接库dll,如果不勾,就是静态链接了,一般都是勾选的。
2)CMAKE_INSTALL_PREFIX是VTK的安装目录,默认是C盘中的一个目录,这里把它改为我们希望的目录地址,我这里改就是事先准备好的VTK-Install下的release(我后来在VTK-Install这个目录下又分别创建了release和debug两个目录,是为了以后万一要再生成一个debug版的库)
PS(事后补充):除非只打算编译一种(release或debug或其他,见下一条设置),这里可以不用分,或者说事后再分。因为如果下一条编译类型写了多个的话(还是见下一条),那么在最后生成库的时候(VS中生成INSTALL这个项目时,后面会讲到),其实会全部生成到这个选项所设置的目录当中去,如果要区分,只能自己在生成过程中或者之后,手动剪切粘贴来完成(尝试过在VS中修改输出目录,但没起作用,欢迎大神解答或者以后再研究)。
3)CMAKE_CONFIGURATION_TYPES 是设置编译的类型(release或者debug等),默认是“Debug;Release;MinSizeRel;RelWithDebInfo”,这样一来生成的VS解决方案里(就是上面Buld这个目录)的工程打开,就可以支持四种不同设置的工程。这个根据需要来设置即可,也可以按默认的来。
4)与QT有关的配置,可以用关键词来搜索相关的配置项,默认都是DEFAULT,咱也不知道这个默认值到底是啥(有兴趣的伙伴可以试试),按照网上说的教程选了WANT,有的版本是只有勾选框,就直接勾选就好了,我这个版本有四个选项(YES,NO,WANT,NO_WANT),我也不知道YES和WANT有啥区别(搜了一下也没找到答案,有知道的大佬欢迎评论指正)。
- 以上这些主要的配置完了之后,再次点击“Configure”,会把大部分的配置项清除(或者变为白色,个人理解就是系统不需要向用户确认了)。但是由于我们在QT相关的配置项做了修改(主要是WANT了QT相关内容),所以又会出现一些红色配置项(系统需要我们补充配置或向我们确认),情况如下:
这里出现了一个小插曲:由于我的机器之前装了anaconda3且配置了环境变量,里面可能以前装了(不记得是默认装的还是手动装的了)QT,所以这里目录自动检索到了anaconda3里的目录,但是我实际上是单独安装了QT5.15.2且选择了对应的msvc2019编译器,也装了vs的QT插件,显然这个需求和anaconda3里的QT是不符合的。所以手动重新按照自己单独安装QT的目录重新设置了(如果在系统环境变量中,自己装的QT的目录在anaconda之前,应该可以直接避免这种情况),如下:
设置好后再次点击Configure,理想情况,应该是没有红色的事项了,然而意外还是发生了:
这里还有一个红色的警告,和QML有关,警告内容上面截图没截到,内容是“CMake Warning (dev) at GUISupport/QtQuick/qml/CMakeLists.txt:93 (message): Qt5 is configured in both Debug and Release modes. Due to Qt issue 47774 (https://bugreports.qt.io/browse/QTBUG-47774), skipping generation of qmltypes file. Using the one provided with the source tree instead.”,网上搜索一番,有人说是QML不能编译release版的,具体解决方法没有深究,只是一个告警,再次点击configure,会被直接忽略,如下图:
点击Generate,如下,大功告成?!
在VS中生成库
好了,上面那步的Generate只是生成了VS的解决方案,也就是build里的东西,接下来,点击旁边的“Open Project”,会自动启动Visual Studio并打开Build目录下的解决方案。如下图:
可以看到,上图中,编译类型有四种,跟我们之前在CMake中配置的一样。
- 编译DEBUG版本的
选择,Debug,64位,
首先,右键右边项目列表中的ALL_BUILD,点击生成,这个过程会比较慢,耐心等。生成成功以后,可以看到Build目录下多了一个bin目录,里面还有个debug目录,里面有很多的dll文件和pdb文件。但是我们之前CMake里面配置的Install目录下还空空如也呢!
然后,在右侧找到项目INSTALL,右键点击——生成,这个就块多了。
生成成功!这下算真的大功告成了!我们之前设置的Install的目录下有了四个子目录,这就是我们要用的VTK的库文件了,如下:
上面提到,不管编译debug还是release,都会按照CMake里CMAKE_INSTALL_PREFIX项的值所指向的目录来生成这些文件,所以我后来这个项设置为…/VTK-Install/output了。
最后,把这些剪切到自己想放的debug目录下(因为我们这里编译的是debug的库,可以看到bin目录下的dll文件最后都会带一个字母“d”。 - 编译RELEASE版本的
跟上面Debug版本的过程类似,只是最前面选择release即可,就不赘述了。
最后,得到debug和release的VTK的库,如下:
这两个目录都是自己创建的,内容都是从output中拷出来的。
替换PCL库中的VTK
好了,我们的目的并不是单独为了这个VTK,是因为PCL中的VTK不全(不支持QT),所以,接下来就直接替换,替换前我对比了一下,如下图:
可以看到,右边是我们自己编译安装的,要多一些文件,左边是PCL自带的,很明显少了些东西(除了QT还有啥?没有深究)
然后,因为看了一下PCL中的VTK,里面lib,bin这些目录下,release和debug版本的文件都在一个目录里没有分,索性我也不分了,直接把output中(前面提到了,release和debug的都生成到这个里面了)的文件拷贝过去。
很显然,拷贝的时候会遇到重名的,4261个,跟上图左边的一致,因为两边都是9.1版本的VTK,为了防止这些重名文件跟PCL有啥关联,就没有覆盖,直接跳过重名,相当于只补充多出来的跟QT有关的(或许还有别的?)。
如图,果然是多了一些跟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<pcl/****.h>
之类的写法,如果包含目录像上图那样写,就只能写成#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的项目属性配置的链接器——输入——附加依赖项里就行了。
点击下载提取文件名批处理程序及处理结果
测试点云显示(QT项目PCL读取+VTK显示)
-
QVTK显示控件
根据网上说的,在VTK9.0以后没有QT插件了,需要通过OpenGL Widget来提升,如下图:
点击提升为后,在窗口中填写提升的类名称为QVTKOpenGLNativeWidget
,下面的头文件会自动填充。
点击提升完成后,修改该控件的Object Name为自己需要的,我这里是修改为qvtkWidget了,如下图:
回到Visual Studio以后,进入”ui_*****.h"这个特殊的头文件(QT自动生成的UI界面的头文件)会发现自动添加了上述头文件,控件的定义也添加进去了,如图:
-
读取点云(仅以.ply数据读取为例)
回到Visual Studio,代码中添加如下头文件:
#include<pcl/io/ply_io.h> //用来读取.ply格式的点云
#include<pcl/point_types.h> //用于点云变量定义
然后在自己希望的地方添加如下读取代码:
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<pcl/visualization/pcl_visualizer.h>
#include<vtkGenericOpenGLRenderWindow.h>
#include<QVTKOpenGLNativeWidget.h>
然后添加如下代码显示点云:
//创建渲染器
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的编译和配置,这个代码的折腾纯粹为了测试一下配置好了没。
最后运行程序,成功!