QT5.7.1 + VTK8.2.0 + PCL1.11.0 + VS2019 + OpenCV4.3.0 +Cmake3.18.0
由于需要使用QVTKWidget在QT交互界面里进行显示,但是PCL自带的第三方库里的VTK不包含这个插件,所以需要使用独立的VTK,在编译VTK源码时,需要勾选 Module_vtkGUISupportQt,Module_vtkGUISupportQtOpenGL,VTK_Group_Qt。
一、CMakeLists.txt及工程配置
用安装包安装PCL,但是使用find_package 这一套命令(如下所示),在Cmake中自动包含PCL的头文件、链接lib等,会导致VTK的头文件包含不进来。也就是说下面这样的写法,会导致VTK的头文件无法包含全,导致无法使用
....
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
link_directories(${VTK_LIBRARY_DIRS})
find_package(PCL 1.3 REQUIRED COMPONENTS common io)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
....
TARGET_LINK_LIBRARIES( ProjectName ... ${VTK_LIBRARIES} ${PCL_LIBRARIES}...)
CmakeLists.txt 如下:
cmake_minimum_required(VERSION 2.8)
PROJECT(scan3d-capture)
set(CMAKE_AUTOMOC ON)
#QT
find_package(Qt5Widgets)
find_package(Qt5Core)
find_package(Qt5Gui)
find_package(Qt5OpenGL)
Set (BASEDIR "D:/projects/3DReconstruction/uiFile")#设置此路径为UI文件所在的文件夹
FILE(GLOB UI_FILES "${BASEDIR}/*.ui")
qt5_wrap_ui(WRAP_FILES ${
UI_FILES})
source_group("Ui" FILES ${
UI_FILES} ${
WRAP_FILES} )
#opencv
FIND_PACKAGE(OpenCV REQUIRED)
include_directories( ${
OPENCV_INCLUDE_DIR} )
#vtk
find_package(VTK REQUIRED)
include(${
VTK_USE_FILE})
link_directories(${
VTK_LIBRARY_DIRS})
#PCL
set (PCL_Root_Path "D:\\Toolkit\\PCL\ 1.11.0")#设置为PCL的根目录
#设置PCL及第三方库头文件所在目录。因为我们使用独立的VTK,所以没有包含PCL自带的VTK的头文件。
set(BOOST_Head_File_Path "${PCL_Root_Path}\\3rdParty\\Boost\\include\\boost-1_73")
set (Qhull_Head_File_Path "${PCL_Root_Path}\\3rdParty\\Qhull\\include")
set (OpenNI2_Head_File_Path "${PCL_Root_Path}\\3rdParty\\OpenNI2\\Include")
set (FLANN_Head_File_Path "${PCL_Root_Path}\\3rdParty\\FLANN\\include")
set (Eigen_Head_File_Path "${PCL_Root_Path}\\3rdParty\\Eigen\\eigen3")
set (PCL_Head_File_Path "${PCL_Root_Path}\\include\\pcl-1.11")
include_directories(${
BOOST_Head_File_Path} ${
Qhull_Head_File_Path} ${
OpenNI2_Head_File_Path} ${
FLANN_Head_File_Path} ${
Eigen_Head_File_Path} ${
PCL_Head_File_Path})
#设置PCL及第三方库lib所在目录。因为我们使用独立的VTK,所以没有包含PCL自带的VTK的lib。
set(BOOST_Lib_Path "${PCL_Root_Path}\\3rdParty\\Boost\\lib")
set (Qhull_Lib_Path "${PCL_Root_Path}\\3rdParty\\Qhull\\lib")
set (OpenNI2_Lib_Path "${PCL_Root_Path}\\3rdParty\\OpenNI2\\Lib")
set (FLANN_Lib_Path "${PCL_Root_Path}\\3rdParty\\FLANN\\lib")
set (PCL_Lib_Path "${PCL_Root_Path}\\lib")
link_directories(${
BOOST_Lib_Path} ${
Qhull_Lib_Path} ${
OpenNI2_Lib_Path} ${
FLANN_Lib_Path} ${
PCL_Lib_Path})
#把项目所有的头文件和源文件建立工程
FILE(GLOB SRC_FILES "./*.cpp")
FILE(GLOB HEAD_FILES "./*.hpp")
ADD_EXECUTABLE(scan3d-capture ${
SRC_FILES} ${
HEAD_FILES} ${
RCC_FILES} ${
WRAP_FILES} ${
QRC_FILES} ${
app_ICON})
#链接所使用的第三方库的lib。此处没有链接PCL,需要在VS里面手动链接,否则会出现无法解析的外部符号的错误。
TARGET_LINK_LIBRARIES( scan3d-capture
${
OpenCV_LIBS} ${
VTK_LIBRARIES} Qt5::OpenGL Qt5::Widgets Qt5::Core Qt5::Gui)
手动链接PCL的lib文件:我们在Cmake中指定了库目录,也就是lib文件所在的目录,所以,我们在这里只需要把lib文件的文件名放在附加依赖项中就可以了,不需要指明它具体在哪个目录里面。
我们首先找到PCL所有的lib文件名,文件有很多,我也把(文件名列表附在了本文结尾),把所有lib文件名复制到红框里。注意,debug和release模式下,包含的lib是不一样的,需要把对应模式下的lib文件复制到红框里。一般debug的lib后面会都一个字母’d’
检查你的lib文件和我给出的静态链接库版本一不一样,如果不一样,需要按照下述方法重新获取。
属性–》链接器–》输入–》附加依赖项:
获取lib文件列表方法:
参考:https://blog.csdn.net/weixin_41991128/article/details/83864713
win+r调出“运行”窗口并输出cmd
输入:cd /d D:\P_pcl\PCL1.9.0\PCL 1.9.0\3rdParty\VTK\lib 回车 (填自己的路径)
输入:dir /b *.lib *>0.txt 回车
这样当前目录下所有lib文件名都写入了0.txt文件中,但是release和debug版本的链接库时紧挨着放置的,需要按照如下链接所述方法,将0.txt文件中的奇数行和偶数行分别存储到两个不同的文件中,再根据你的编译模式,把对应的lib复制到附加依赖项中。
链接: https://blog.csdn.net/weixin_41991128/article/details/83965051.
这里还有一个bug,如果环境变量里面, vtk debug目录在release 目录之上,那么程序会首先在debug目录里寻找动态链接库,如果使用了QVTKWidget,这时候relase模式下,就会出现如下错误。如果release在debug之上,则debug模式下,会出现这个错误。
我自己的经验表示,如果我们不使用QVTKWidget控件,则不会出现这个错误。
QWidget: Must construct a QApplication before a QWidget
解决方案:
方案一(推荐):在使用debug模式时,把环境变量中的vtk的release的dll所在路径去掉,在使用relase模式时,把环境变量中vtk的bebug的dll所在路径去掉。
方案二:把vtk编译debug目录放在release之前,并且在relase模式下,需要把所有QT的lib文件改为debug版本的lib,即在附加依赖项里面找到所有的QT相关的lib, 一般为:
将
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Widgets.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Gui.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Core.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Sql.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5OpenGL.lib
修改为
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Widgetsd.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Guid.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Cored.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5Sqld.lib
D:\Toolkit\QT_5.7.1\QT_5.7.1\5.7\msvc2015_64\lib\Qt5OpenGLd.lib
虽然此方法能解决上述提到的这个问题,但是不推荐此解决方案,毕竟你在release模式下调用了QT的debug版本的库,可能会出现一些奇奇怪怪的错误。
二、使用QT+PCL显示点云
使用QVTKWidget 和pcl::visualization::PCLVisualizer .
必须QVTKWidget会出现如下警告,也就是说QVTKWidget 会在未来的版本中删除:
一般我们需要使用QVTKOpenGLNativeWidget代替QVTKWidget,对应的,也需要用vtkGenericOpenGLRenderWindow代替vtkRenderWindow,但是pcl::visualization::PCLVisualizer只支持QVTKWidget,我们只能使用QVTKWidget。
第一步:
首先在UI界面里添加一个QVTKWidget插件。
在QTDesigner中添加QVTKWidget的方法如下链接所示:https://blog.csdn.net/u012135461/article/details/77833316
第二步:
在类中,比如MainWindow 中添加 私有成员变量
class MainWindow : public QMainWindow
{
Q_OBJECT
....
pri