Qt Creator中使用PCL库

我之前写过一篇博客Qt 5.9使用VTK显示点云,可惜其中很多部分都是失败的,而且排版糟糕,不过其中PCL的安装以及在VS中使用PCL的方法是值得参考的,起码我通过这种方式安装的PCL在VS上一直用得OK。但是用了一段时间还是有一些小问题,不致命但是极其恶心,比如

  • 在VS中使用PCL我怀疑加入的附加依赖项过多,经常导致IntelliSense卡半天,自动补全功能近乎废了,对于我这种“面向自动补全开发”的程序猿来说无异于灭顶之灾
  • VS中使用Qt做界面还是很麻烦,虽然可以装一个Qt的插件使用Qt Designer设计界面,但总还是不如Qt自己的Creator好
  • 另外在VS中使用Qt库还是不太直接

鉴于此,本着“生命不息,折腾不止”的原则,把PCL折腾到Qt中来。

1.环境

我的环境和之前博客中的不太一样,但是安装与配置方法大同小异。

  • 使用的win10系统。小问题,没差别
  • 使用的VS2015不再是2013(2015对应的是VC14编译器,与2013不一样),小问题
  • 使用的是pcl-1.8.1-msvc2015-x86版本,也就是32位的,安装很简单——在这里下载,提取码:utw2;直接点击PCL-1.8.1-AllInOne-msvc2015-win32.exe安装,完成后需要像博客中第一部分PCL的安装中说明的一样配置环境变量,之后配置属性表(这里我给出的安装包里有配好的属性表,如果你的安装目录不一样,只需要更改一下包含目录与库目录即可);完成以上就可以在VS中使用PCL了
  • 我的Qt版本是Qt5.8.0,没有装MINGW版本的,MSVC64位与32位的编译套件都安装了(如果要在Qt中使用PCL,那么Qt必须与PCL的版本相协调,因为我的PCL装的32位的,无可奈何只能再装一个MSVC32位版的Qt编译套件;Qt的安装过程略,很简单,下载,安装即可)

2.编译VTK

实际上在Qt的项目中配置一下包含目录、外部库位置即可(按照第3部分),但是最后配置好后会发现PCL能正常使用但是涉及到其中第三方库VTK的部分功能不能使用,故这里重新编译下VTK库。

  1. VTK源码下载
    前两步可直接跳过使用我编译好的,除非你的版本不一样,得自己编译。这里用PCL1.8.1配套的VTK8.0,源码下载地址,提取码:2f5x
  2. CMAKE配置VTK for Qt编译环境与源码编译
    2.1. 打开CMAKE配置项目(CMAKE随便装一个版本),设置源代码目录与构建目录,如下:
    在这里插入图片描述
    2.2. 点击configure,选择VS2015generator选择win32平台(与PCL同平台)
    在这里插入图片描述
    2.3. 继续configure
    在这里插入图片描述
    2.4. 之后是配置项目构建的一些路径以及项目的配置,选中BUILD_SHARED_LIBS和VTK_GROUP_QT(对Qt的支持),接下来继续configure会提示配置QMAKE路径与Qt版本,配置完了后继续configure,然后是配置QT的安装目录以及其一些子目录,按照本机路径配置即可(注意也要指定同平台的Qt,比如VS2015WIN32,我这里使用的x64的Qt路径,倒了大霉重新编译)
    这里有一点一定要注意,要设置VTK的渲染后端为OpenGL而不是OpenGL2,如图
在这里插入图片描述 在这里插入图片描述
在这里插入图片描述 在这里插入图片描述

在这里插入图片描述
2.5. 一直configure直到标红消失,然后generate,在构建目录下会出现生成的项目文件VTK.sln,使用VS(以管理员身份运行)打开这个项目,选择ALL_BUILD-右键-生成
在这里插入图片描述
2.6. 生成完了选择INSTALL-右键-仅用于项目-仅生成INSTALL,会在C:\\Program Files(x86)\\下生成一个VTK文件夹,这即是最终要拷到PCL中使用的东西。
在这里插入图片描述
2.7. 将以上生成的VTK文件夹下的bin目录下所有dll文件名称改成-gd.dll格式,lib文件夹下lib文件名称改为-gd.lib格式,然后再VS中使用release模式在执行一遍以上生成与安装步骤,将其dlllib拷到之前的VTK文件夹下,大功告成。
将VTK下dlllib批量改名可使用以下python脚本

import os

def rename_file(old):
    #将lib文件或dll文件改名成*-gd.lib或*-gd.dll
    if old[::-1].find('bil.')==0 or old[::-1].find('lld.')==0:
        path=os.path.dirname(old)
        f_name=os.path.basename(old)
        suf=f_name[-4:]
        f_name=f_name[:-4]
        return path+'\\'+f_name+'-gd'+suf
    else:
        return old

root='D:\\VTK'
paths=[root+'\\bin',root+'\\lib']
for p in paths:
    os.chdir(p)
    fs=os.listdir()
    fs_old=[p+'\\'+f for f in fs]
    fs_new=[rename_file(p+'\\'+f) for f in fs]
    for (f_old,f_new) in zip(fs_old,fs_new):
        os.rename(f_old,f_new)

  1. 编译后库的放置
    编译后文件下载,提取码:2f5x;将以上编译好的VTK文件夹复制到PCL安装目录下的3rdParty\\下覆盖同名文件夹(记得先备份)

3.Qt项目配置

项目配置与VS中类似,无非是配置包含目录、添加外部库,不过VS中添加外部库分为了添加库目录与附加依赖项两部分。在Qt中添加包含目录的方式是在.pro文件中使用语句INCLUDEPATH+=包含目录;添加外部库的方式可以选中项目-右键-添加库-外部库-浏览到库文件位置(即lib文件位置),在Qt中使用PCL需要添加的库有lib目录下的库,还有3rdParty目录下各个第三方库目录下的各自的lib文件夹中的lib文件,这些文件洋洋洒洒有几百条,一个一个加入配置文件中将十分费事,可以通过以下python脚本批量一次性生成配置文件:

import re
import os

def isDebug(lib):
    return len(re.findall(r'.+debug\..+',lib))!=0 or len(re.findall(r'.+-gd-[1-9_]+\..+',lib))!=0 or len(re.findall(r'.+-gd\..+',lib))!=0 or len(re.findall(r'.+_d\..+',lib))!=0
def get_libs():
    return [os.path.abspath('.')+'\\'+f for f in os.listdir() if len(re.findall(r'.+\.lib',f))!=0]
def get_debug_release(libs):
    dbg=[d for d in libs if isDebug(d)]
    rls=[r for r in libs if not isDebug(r)]
    return dbg,rls 
def get_pairs(dbg,rls):
    d_mod=list(dbg)
    r_mod=list(rls)
    d_mod=[d.replace('_debug','') for d in d_mod]
    r_mod=[r.replace('_release','') for r in r_mod]
    d_mod=[d.replace('-gd-','-') for d in d_mod]
    d_mod=[d.replace('-gd.','.') for d in d_mod]
    d_mod=[d.replace('_d.','.') for d in d_mod]
    d_match=[dbg[i] for i in range(len(dbg)) if d_mod[i] in r_mod]
    r_match=[rls[r_mod.index(d_mod[i])] for i in range(len(d_match))]
    return d_match,r_match
    
root=os.path.abspath('.')
all_dbg=[]
all_rls=[]
paths=[root+'/lib/',root+'/3rdParty/Boost/lib/',root+'/3rdParty/FLANN/lib/',root+'/3rdParty/Qhull/lib/',root+'/3rdParty/VTK/lib/']
for p in paths:
    os.chdir(p)
    libs=get_libs()
    debug,release=get_debug_release(libs)
    all_dbg+=debug
    all_rls+=release
all_dbg+=['D:\\PCL-1.8.1\\3rdParty\\OpenNI2\\Lib\\OpenNI2.lib']
all_rls+=['D:\\PCL-1.8.1\\3rdParty\\OpenNI2\\Lib\\OpenNI2.lib']
all_dbg=[item.replace('\\','/') for item in all_dbg]
all_rls=[item.replace('\\','/') for item in all_rls]
lib_d,lib_r=get_pairs(all_dbg,all_rls)

text=''

#添加包含目录
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/include/pcl-1.8\n')
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/3rdParty/Boost/include/boost-1_64\n')
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/3rdParty/Eigen/eigen3\n')
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/3rdParty/FLANN/include\n')
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/3rdParty/OpenNI2/Include\n')
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/3rdParty/Qhull/include\n')
text+=('INCLUDEPATH += '+root.replace('\\','/')+'/3rdParty/VTK/include/vtk-8.0\n\n')

#添加依赖项
for (d,r) in zip(lib_d,lib_r):
    path=os.path.dirname(d)
    d_name=os.path.basename(d).replace('.lib','')
    r_name=os.path.basename(r).replace('.lib','')
    text+=('win32:CONFIG(release, debug|release): LIBS += -L'+path+'/'+' -l'+r_name+'\n')
    text+=('else:win32:CONFIG(debug, debug|release): LIBS += -L'+path+'/'+' -l'+d_name+'\n')
    text+=('else:unix: LIBS += -L'+path+'/'+' -l'+r_name+'\n')
    text+='\n'

#导出
with open(root+'/qt_config.txt','w') as f:
    f.write(text)

将以上python脚本放在PCL根目录下运行,将生成的qt_config.txt文件中的所有内容拷贝到.pro文件中即可。为避免每一次都需要配置,新建一个PCL.pri文件,将配置内容添加到其中,然后在.pro文件中include(PCL.pri)即可完成配置(类似VS中使用配置好的属性表一样)

4.测试

  • 本来想用QVTKWidget显示点云,经过测试还是失败,如果避免使用可视化方面的功能上述配置已经没有错误了,而且也可以使用简单的CloudViewer来显示点云(虽然性能渣得一匹,一个几万个点的点云只要随便转一下马上就能卡死,比起CloudCompare的加载上百万点甚至千万点可谓差的不是一星半点)如下为一个简单的测试结果:
用CloudViewer显示点云主界面被卡死(点数157541)
  • 将VTK文件夹下plugin目录下的QVTKWidget.dll放到QT Creator的插件目录下确实能用,在Creator中也能像一般插件一样拖动使用,但是debug的时候程序意外退出,只能以release模式运行。debug时异常提示:QWidget: Must construct a QApplication before a QWidget 程序异常结束。这里显示用的是VTK库,VTK库底层用的OpenGL渲染,库又调用库,层次繁杂。放弃
  • Qt中使用PCL一样卡死自动补全,归根到底还是这个库太臃肿了,递归检索文件太艰难
发布了28 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/liyunxin_c_language/article/details/100585844