Windows环境下编译PCL

PCL对VS和第三方库的版本依赖关系较高,所以对于不同VS版本需要对PCL和第三方库分别编译和安装。按照本文一步步进行编译,即可成功安装PCL。需要注意的是,下文中的绝对路径可以根据自己的需要进行调整。

以下步骤如有错误或不妥,欢迎留言交流,以进一步优化编译和安装过程。

一. 安装CMake

进入CMake官网,根据自己的电脑配置选择对应的安装包,下载并进行安装。

二. 依赖库的编译和安装

第三方库 用途 是否必须
Boost 用于智能指针等操作 必选
Eigen 用于矩阵运算等 必选
FLANN 用于邻域搜索等 必选
VTK 可视化库,用于显示点云等 必须
QHULL 一个强大的计算几何库,可以用于计算高维的convex hull,Delaunay triangulation,Voronoi diiagram等 必选
Qt 用于图像交互界面等 可选
OpenNI 用于获取点云等 可选

在编译PCL前须确保已正确安装了第三方依赖库,不能混用32为和64位的代码,不能混用不同编译器编译的第三方库。

a. Boost

下载地址:https://www.boost.org/users/download/

  1. 进入boost文件夹,运行bootstrap.bat,运行结束后会生成project-config.jam。

  2. 使用命令编译boost

    1
    b2.exe install toolset=msvc-14.3 address-model=64 --without-python --build-dir=build --prefix="C:\MyPrograms\PCL\Boost"

b. Eigen

下载地址:https://gitlab.com/libeigen/eigen

  1. 打开CMake,分别设置Eigen的source和build路径。

  2. 点击按钮Configure。配置:

    Name Value
    CMAKE_INSTALL_PREFIX C:\MyPrograms\PCL\Eigen3
  3. 再次点击按钮Configure

  4. 点击按钮Generate

  5. 点击按钮Open Project。找到菜单Build->Batch build...,勾选ALL_BUILD(Debug)ALL_BUILD(Release),点击Build按钮。再勾选INSTALL(Debug)INSTALL(Release),点击Build按钮。

c. FLANN

下载地址:https://github.com/flann-lib/flann

  1. 打开CMake,分别设置FLANN的source和build路径。

  2. 点击按钮Configure。配置:

    Name Value
    BUILD_C_BINDINGS check
    BUILD_MATLAB_BINDINGS uncheck
    BUILD_PYTHON_BINDINGS uncheck
    CMAKE_CONFIGURATION_TYPES Debug;Release
    CMAKE_INSTALL_PREFIX C:\MyPrograms\PCL\flann

    添加Entry:

    Name Type Value
    CMAKE_DEBUG_POSTFIX STRING -gd
  3. 再次点击按钮Configure

  4. 点击按钮Generate

  5. 点击按钮Open Project。找到菜单Build->Batch build...,勾选ALL_BUILD(Debug)ALL_BUILD(Release),点击Build按钮。再勾选INSTALL(Debug)INSTALL(Release),点击Build按钮。

d. QHull

下载地址:https://github.com/qhull/qhull

  1. 打开CMake,分别设置QHull的source和build路径。

  2. 点击按钮Configure。配置:

    Name Value
    CMAKE_INSTALL_PREFIX C:\MyPrograms\PCL\qhull
  3. 再次点击按钮Configure

  4. 点击按钮Generate

  5. 点击按钮Open Project。找到菜单Build->Batch build...,勾选ALL_BUILD(Debug)ALL_BUILD(Release),点击Build按钮。再勾选INSTALL(Debug)INSTALL(Release),点击Build按钮。

e. VTK

下载地址:https://vtk.org/download/

  1. 打开CMake,分别设置VTK的source和build路径。

  2. 点击按钮Configure。配置:

    Name Value
    CMAKE_INSTALL_PREFIX C:\MyPrograms\PCL\VTK
    BUILD_SHARED_LIBS uncheck
    CMAKE_CXX_MP_FLAG check
    VTK_RENDERING_BACKEND OpenGL2

    添加Entry:

    Name Type Value
    CMAKE_DEBUG_POSTFIX STRING -d
  3. 如果需要对Qt的支持,则需要首先安装Qt(点击下载),然后继续配置:

    Name Value
    Qt5_DIR C:\MyPrograms\Qt\Qt5.13.1\5.13.1\msvc2017_64\lib\cmake\Qt5
    VTK_QT_VERSION 5
  4. 再次点击按钮Configure

  5. 点击按钮Generate

  6. 点击按钮Open Project。找到菜单Build->Batch build...,勾选ALL_BUILD(Debug)ALL_BUILD(Release),点击Build按钮。再勾选INSTALL(Debug)INSTALL(Release),点击Build按钮。

三. 编译PCL

下载地址:https://github.com/PointCloudLibrary/pcl/releases

  1. 打开CMake,分别设置PCL的source和build路径。

  2. 点击按钮Configure。配置:

Name Value
EIGEN_INCLUDE_DIR C:\MyPrograms\PCL\Eigen3\include\eigen3
FLANN_INCLUDE_DIR C:\MyPrograms\PCL\flann\include
FLANN_LIBRARY C:\MyPrograms\PCL\flann\lib\flann_cpp_s.lib
FLANN_LIBRARY_DEBUG C:\MyPrograms\PCL\flann\lib\flann_cpp_s-gd.lib
FLANN_LIBRARY_SHARED C:\MyPrograms\PCL\flann\lib\flann_cpp_s.lib
Boost_INCLUDE_DIR C:\MyPrograms\PCL\Boost\include\boost-1_78
Boost_LIBRARY_DIR_DEBUG C:\MyPrograms\PCL\Boost\lib
Boost_LIBRARY_DIR_RELEASE C:\MyPrograms\PCL\Boost\lib
VTK_DIR C:\MyPrograms\PCL\VTK\lib\cmake\vtk-9.1
QHULL_LIBRARY C:\MyPrograms\PCL\qhull\lib\qhullcpp.lib
QHULL_LIBRARY_DEBUG C:\MyPrograms\PCL\qhull\lib\qhullcpp_d-d.lib
CMAKE_INSTALL_PREFIX C:\MyPrograms\PCL\PCL
WITH_CUDA false
  1. 再次点击按钮Configure

  2. 点击按钮Generate

  3. 点击按钮Open Project。找到菜单Build->Batch build...,勾选ALL_BUILD(Debug)ALL_BUILD(Release),点击Build按钮。再勾选INSTALL(Debug)INSTALL(Release),点击Build按钮。

如果使用VS构建时报错,找到报错的项目,逐个解决。举例如下:

  1. 无法打开头文件,如下图所示。

Screenshot_1

解决方法:在项目浏览器中右键点击出错项目pcl_io_ply,在Configuration Properties->C/C++->Additional Include Directories项中增加Boost的头文件目录,如C:\MyPrograms\PCL\Boost\include\boost-1_78。注意Debug和Release的配置都要做相应修改。然后右键项目pcl_io_ply进行Build即可。

  1. lib库文件出错,如下图所示。

Screenshot_2

解决方法:在项目浏览器中右键点击出错项目pcl_kdtree,在Configuration Properties->Linker->Input->Additional Dependencies项中增加flann相关的lib文件。对于Debug配置增加C:\MyPrograms\PCL\flann\lib\flann_cpp_s-gd.lib,对于Release配置增加C:\MyPrograms\PCL\flann\lib\flann_cpp_s.lib。然后右键项目pcl_kdtree进行Build即可。

四. 测试和使用PCL

  1. 新建一个空项目,新建test.cpp,并粘贴以下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #include <pcl/visualization/cloud_viewer.h>
    #include <iostream>
    #include <pcl/io/io.h>
    #include <pcl/io/pcd_io.h>

    int user_data;

    void
    viewerOneOff(pcl::visualization::PCLVisualizer& viewer)
    {
    viewer.setBackgroundColor(1.0, 0.5, 1.0);
    pcl::PointXYZ o;
    o.x = 1.0;
    o.y = 0;
    o.z = 0;
    viewer.addSphere(o, 0.25, "sphere", 0);
    std::cout << "i only run once" << std::endl;

    }

    void
    viewerPsycho(pcl::visualization::PCLVisualizer& viewer)
    {
    static unsigned count = 0;
    std::stringstream ss;
    ss << "Once per viewer loop: " << count++;
    viewer.removeShape("text", 0);
    viewer.addText(ss.str(), 200, 300, "text", 0);

    //FIXME: possible race condition here:
    user_data++;
    }

    int
    main()
    {
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGBA>);
    pcl::io::loadPCDFile("my_point_cloud.pcd", *cloud);

    pcl::visualization::CloudViewer viewer("Cloud Viewer");

    //blocks until the cloud is actually rendered
    viewer.showCloud(cloud);

    //use the following functions to get access to the underlying more advanced/powerful
    //PCLVisualizer

    //This will only get called once
    viewer.runOnVisualizationThreadOnce(viewerOneOff);

    //This will get called once per visualization iteration
    viewer.runOnVisualizationThread(viewerPsycho);
    while (!viewer.wasStopped())
    {
    //you can also do cool processing here
    //FIXME: Note that this is running in a separate thread from viewerPsycho
    //and you should guard against race conditions yourself...
    user_data++;
    }
    return 0;
    }
  2. 配置项目属性页,Debug和Release要分别配置:

    1. Configuration Properties->Debugging->Environment加入各个库的bin文件夹,生成方式见此节(debuggingEnvironments.txt),例如PATH=%(PATH);C:\MyPrograms\PCL\PCL\bin;C:\MyPrograms\PCL\flann\bin;C:\MyPrograms\PCL\qhull\bin;C:\MyPrograms\PCL\VTK\bin
    2. Configuration Properties->VC++ Directories->Include Directories加入各个库的头文件所在的文件夹,生成方式见此节(includeDirs.txt),例如C:\MyPrograms\PCL\PCL\lib;C:\MyPrograms\PCL\Boost\lib;C:\MyPrograms\PCL\flann\lib;C:\MyPrograms\PCL\qhull\lib;C:\MyPrograms\PCL\VTK\lib;$(LibraryPath)
    3. Configuration Properties->VC++ Directories->Library Directories加入各个库的lib所在的文件夹,生成方式见此节(libDirs.txt),例如C:\MyPrograms\PCL\PCL\lib;C:\MyPrograms\PCL\Boost\lib;C:\MyPrograms\PCL\flann\lib;C:\MyPrograms\PCL\qhull\lib;C:\MyPrograms\PCL\VTK\lib;$(LibraryPath)
    4. Configuration Properties->Linker->Input->Additional Dependencies加入分别与Debug和Release相对的lib文件名,生成方式见此节(libsDebugAll.txt和libsReleaseAll.txt),例如Debug的pcl_appsd.lib;pcl_commond.lib;...或Release的pcl_apps.lib;pcl_common.lib;...
  3. 编译并运行此项目,如果可以显示如下可视化结果,即表明PCL成功安装。

Visualization

五. 生成所需路径和lib文件

使用getPCLLibs.py脚本可以完成对所有所需路径和lib文件的提取。注意保证脚本中的路径正确:pclRootBoostRootEigenRootflannRootqhullRootVTKRoot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Copyright: Wu_Zh
Filename: getPCLLibs.py
Description:

@author: wuzhipeng
@email: 763008300@qq.com
@website: https://wuzhipeng.cn/
@create on: 12/27/2021 3:13 PM
@software: PyCharm
"""

import os
import glob

pclRoot = r'C:\MyPrograms\PCL\PCL'
BoostRoot = r'C:\MyPrograms\PCL\Boost'
EigenRoot = r'C:\MyPrograms\PCL\Eigen3'
flannRoot = r'C:\MyPrograms\PCL\flann'
qhullRoot = r'C:\MyPrograms\PCL\qhull'
VTKRoot = r'C:\MyPrograms\PCL\VTK'

# debuggingEnvironments
debuggingEnvironments = ['%(PATH)']
debuggingEnvironments.append(os.path.join(pclRoot,'bin'))
debuggingEnvironments.append(os.path.join(flannRoot,'bin'))
debuggingEnvironments.append(os.path.join(qhullRoot,'bin'))
debuggingEnvironments.append(os.path.join(VTKRoot,'bin'))
debuggingEnvironmentsText = 'PATH='+';'.join(debuggingEnvironments)
print(debuggingEnvironmentsText)

# includeDirs
includeDirs = []
includeDirs.append(glob.glob(os.path.join(pclRoot,'include','pcl*/'))[0])
includeDirs.append(glob.glob(os.path.join(BoostRoot,'include','boost*/'))[0])
includeDirs.append(glob.glob(os.path.join(EigenRoot,'include','eigen*/'))[0])
includeDirs.append(glob.glob(os.path.join(flannRoot,'include'))[0])
includeDirs.append(glob.glob(os.path.join(qhullRoot,'include'))[0])
includeDirs.append(glob.glob(os.path.join(VTKRoot,'include','vtk*/'))[0])
includeDirsText = ';'.join(includeDirs)+';$(IncludePath)'

def distinguishLib(libDir,debugF,releaseF):
libs = os.listdir(libDir)
libsDebug = []
libsRelease = []
for lib in libs:
if not lib.endswith('.lib'):
continue
add_d = lib.replace(releaseF, debugF)
if add_d in libs:
libsDebug.append(add_d)
libsRelease.append(lib)
assert len(libsDebug) == len(libsRelease), 'Wrong number of libs'
print(len(libsDebug))
return libsDebug,libsRelease

# libDirs and libs
libDirs = []
libsDebugAll=[]
libsReleaseAll=[]
#################################################################
libDir = os.path.join(pclRoot,'lib')
libDirs.append(libDir)
libsDebug,libsRelease = distinguishLib(libDir,'d.lib','.lib')
libsDebugAll+=libsDebug
libsReleaseAll+=libsRelease

#################################################################
libDir = os.path.join(BoostRoot,'lib')
libDirs.append(libDir)
libsDebug,libsRelease = distinguishLib(libDir,'-mt-gd-','-mt-')
libsDebugAll+=libsDebug
libsReleaseAll+=libsRelease

#################################################################
libDir = os.path.join(flannRoot,'lib')
libDirs.append(libDir)
libsDebug,libsRelease = distinguishLib(libDir,'-gd.lib','.lib')
libsDebugAll+=libsDebug
libsReleaseAll+=libsRelease

#################################################################
libDir = os.path.join(qhullRoot,'lib')
libDirs.append(libDir)
libsDebug,libsRelease = distinguishLib(libDir,'_d.lib','.lib')
libsDebugAll+=libsDebug
libsReleaseAll+=libsRelease

#################################################################
libDir = os.path.join(VTKRoot,'lib')
libDirs.append(libDir)
libsDebug,libsRelease = distinguishLib(libDir,'d.lib','.lib')
libsDebugAll+=libsDebug
libsReleaseAll+=libsRelease

libDirsText = ';'.join(libDirs)+';$(LibraryPath)'
libsDebugAllText = '\n'.join(libsDebugAll)
libsReleaseAllText = '\n'.join(libsReleaseAll)

# save
saveFolder = 'Results'
if not os.path.exists(saveFolder):
os.mkdir(saveFolder)

with open(os.path.join(saveFolder,'debuggingEnvironments.txt'),'w+') as f:
f.write(debuggingEnvironmentsText)
with open(os.path.join(saveFolder,'includeDirs.txt'),'w+') as f:
f.write(includeDirsText)
with open(os.path.join(saveFolder,'libDirs.txt'),'w+') as f:
f.write(libDirsText)
with open(os.path.join(saveFolder,'libsDebugAll.txt'),'w+') as f:
f.write(libsDebugAllText)
with open(os.path.join(saveFolder,'libsReleaseAll.txt'),'w+') as f:
f.write(libsReleaseAllText)

项目属性页和生成结果的对应关系如下:

项目属性页 生成结果
Debugging -> Environment debuggingEnvironments.txt
Include Directories includeDirs.txt
Library Directories libDirs.txt
Additional Dependencies (Debug) libsDebugAll.txt
Additional Dependencies (Release) libsReleaseAll.txt

六. 参考

  1. Building PCL’s dependencies from source on Windows
  2. Compiling PCL from source on Windows
  3. Using PCL in your own project
  4. Point Cloud Library
  5. 第二章 PCL基础(下篇)

微信公众号

1791506160_orig

请关注微信公众号获取最新消息及更新、意见反馈寻求帮助