视觉环境搭建

写在前面的废话

最近终于确定了毕业论文的题目,还是关于视觉和三维重建,于是兴冲冲地着手搭起工作环境。距离上一篇博客发布已经过去一年多了,实在很是我的风格。
随便谷歌一下,有很多基于高博《视觉SLAM十四讲》的安装教程。可惜时过境迁,各种版本更新,想要完整搭好环境还是费了一番心力。
谨以此篇,献给过两天可能就把系统搞崩溃的自己吧。

搭建流程

  1. win10 和 Ubuntu 16.04 双系统
  2. Eigen线性代数库
  3. Sophus李代数库
  4. OpenCV视觉库
  5. G2O图优化库
  6. PCL点云库

1. win10 和 Ubuntu 16.04 双系统

在这里强调Ubuntu的版本其实不必要,但还是要选择适合自己设备的版本。比如《视觉SLAM》推荐的14.04版,装到我的ThinkPad X1 Carbon 5th 上就变板砖了——网卡驱动不适配,上不了网。你猜我是怎么发现的。具体流程如下:

  • 压缩一部分硬盘空间给新系统:

许多教程里推荐40G以上,想想毕竟是毕业设计任重道远,此处我分了100G左右。方法是:右键“此电脑”->“管理”->”磁盘管理“->选个空间大的磁盘右键->”压缩卷“->输入要压缩的大小,稍微等几秒,这部分磁盘空间变成”未分配“,就OK了。

  • 准备一个U盘做启动盘:

据说要大于8G。很多教程推荐windows下安装一个UltraISO软件刻录Ubuntu镜像,然后我就很愉快的试了一下并失败了,报错mount CD-ROM。于是就投入我的大Mac怀抱,电脑多了果然没坏处。MacOS下用dd命令制作启动盘的方法如下:

1) 下载Ubuntu镜像

2) 插入U盘,查看盘符。终端下代码为:

1
$ diskutil list

比如我的叫disk3

3) 将ISO转换为IMG文件,复制内容到剪贴板。该命令会生成一个.IMG的磁盘镜像文件,但是MAC OSX会默认追加一个的.dmg,即生成的文件后缀是.img.dmg,这个后缀没关系,忽略可以。

1
$ hdiutil convert -format UDRW -o /path/to/generate/img/file /path/to/your/iso/file

4) 卸载U盘,准备写入镜像

1
2
3
$ diskutil unmountDisk /dev/disk3
Unmount of all volumes on disk1 was successfultDisk

5) 镜像写入

1
$ sudo dd if=ubuntu.img.dmg of=/dev/disk3 bs=1m

此处要是写错了盘符就哭去吧。

6) 漫长的等待

我的U盘大概写了30分钟,总之就是很久。然后弹出一个报错窗口,大概是说”您的电脑读不了这个U盘“,嗯,恭喜你的Linux启动盘已经做好了。

  • 安装双系统

其实在安装前还执行了关闭win10的快速启动,进入BIOS关掉Network Secure等步骤,但是我已经忘了,溜了溜了。推荐大家关掉win10的BitLocker,否则每次进入win10要输入一串48位的解锁码。
插上U盘,重启电脑,选择U盘启动,安装Ubuntu…此处省略一万步。

2. Eigen线性代数库

这个是G2O的依赖库,没有它就装不好G2O。很多教程里推荐的安装方法是:

1
$ sudo apt-get install libeigen3-dev

这个安装上最新版本的,有坑,你猜我怎么知道的。此处推荐安装Eigen 3.3.1版本,方法为:

1) 官网下载Eigen 3.3.1 tar.bz2 格式压缩文件。
文件名:eigen-eigen-f562a193118d.tar.bz2

2) 将文件解压到/usr/local/include目录下,在/usr/local/include目录下得到文件eigen-eigen-f562a193118d

1
$ sudo tar -xvjf eigen-eigen-f562a193118d.tar.bz2 -C /usr/local/include

3) 更改文件名为eigen3

1
$ sudo mv /usr/local/include/eigen-eigen-f562a193118d /usr/local/include/eigen3

至此Eigen就装好了,想测试一下?如果后面能装好G2O就说明它是好的。

3. Sophus李代数库

Eigen库提供了几何模块,但是没有提供李代数的支持。一个较好的李代数库是由Strasdat维护的Sophus库。Sophus库支持三维运动的SO(3)、SE(3),此外还支持二维运动的SO(2)、SE(2)和相似变换Sim(3)等内容。它是直接在Eigen库基础上开发的,因此我们不需要安装额外的依赖库。额,我也不知道为啥装这个,反正挺简单的就装着玩儿呗。步骤如下:

1
2
3
4
5
6
7
$ git clone http://github.com/strasdat/Sophus.git
$ cd XXXX #进入Sophus库文件目录下
$ mkdir build #新建build文件夹
$ cd build #进入build文件夹
$ cmake .. #build上一层目录下执行CMake命令
$ make #编译

4. OpenCV视觉库

这个也是坑多到我都忘了。。。总之就是没有安装最新版本,下文借鉴于
一篇教程

1) 官网下载 opencv-3.2.0.zip 解压。进入目录

1
2
$ unzip opencv-3.2.0.zip
$ cd ~/opencv-3.2.0

2) 安装OpenCV所需的库

1
2
$ sudo apt-get install build-essential
$ sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev

3) 编译opencv

1
2
3
4
5
6
$ cd ~/opencv-3.2.0
$ mkdir release
$ cd release
$ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
$ make
$ sudo make install

据说身在墙内会遇到ippicv_linux_20151201.tgz下载不成功的问题,可以到网上找到这个文件,下载后放入opencv-3.2.0目录下的/3rdparty/ippicv/downloads/linux-8b449a536a2157bcad08a2b9f266828b里面就可以了。然后继续从第4行开始执行,直至结束。

4) 测试opencv(C++)

a. 创建工作目录

1
2
3
$ mkdir ~/opencv-lena
$ cd ~/opencv-lena
$ gedit DisplayImage.cpp

b. 编辑如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char** argv )
{
if ( argc != 2 )
{
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
Mat image;
image = imread( argv[1], 1 );
if ( !image.data )
{
printf("No image data \n");
return -1;
}
namedWindow("Display Image", WINDOW_AUTOSIZE );
imshow("Display Image", image);
waitKey(0);
return 0;
}

c. 创建CMake编译文件

1
$ gedit CMakeLists.txt

写入如下内容

1
2
3
4
5
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
add_executable( DisplayImage DisplayImage.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )

d. 编译

1
2
3
$ cd ~/opencv-lena
$ cmake .
$ make

e. 执行

此时opencv-lena文件夹中已经产生了可执行文件DisplayImage,下载lena.jpg放在opencv-lena下,运行

1
$ ./DisplayImage lena.jpg

5. G2O图优化库

这个坑尤其多,首先它依赖于一版靠谱的Eigen,但是很多教程都默认已经装好了,好在此时我们已经搞定了Eigen;其次,按照官方的安装方法,不出意外的又遇到新版本问题,报错Qt5不拉不拉的。谷歌了一波发现Ubuntu 16.04支撑Qt4的,所以要找回以前有效的版本。以下方法摘自另一篇教程

1) 下载g2o

1
$ git clone https://github.com/RainerKuemmerle/g2o/

2) 切换到有效版本再安装g2o

注意有效版本是:8ba8a03f7863e1011e3270bb73c8ed9383ccc2a2

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cd g2o
$ git log |grep 8ba8a*
$ git checkout 8ba8a03f7863e1011e3270bb73c8ed9383ccc2a2
$ sudo apt-get install libqt4-dev
$ sudo apt-get install qt4-qmake
$ sudo apt-get install libqglviewer-dev
$ sudo apt-get install libsuitesparse-dev
$ mkdir build
$ cd build
$ cmake ../
$ make -j8
# 最后还得安装一下
$ sudo make install

3) 测试运行g2o_viewer

1
2
3
4
# cd 到 bin 文件夹
$ cd ..
$ cd bin
$ ./g2o_viewer

6. PCL点云库

这个不是很难,主要麻烦在一些依赖库。以下内容引自又一篇教程

1) 下载pcl

1
$ git clone https://github.com/PointCloudLibrary/pcl.git

2) 准备一些依赖库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sudo apt-get update
$ sudo apt-get install git build-essential linux-libc-dev
$ sudo apt-get install cmake cmake-gui
$ sudo apt-get install libusb-1.0-0-dev libusb-dev libudev-dev
$ sudo apt-get install mpi-default-dev openmpi-bin openmpi-common
$ sudo apt-get install libflann1.8 libflann-dev
$ sudo apt-get install libeigen3-dev
$ sudo apt-get install libboost-all-dev
$ sudo apt-get install libvtk5.10-qt4 libvtk5.10 libvtk5-dev
$ sudo apt-get install libqhull* libgtest-dev
$ sudo apt-get install freeglut3-dev pkg-config
$ sudo apt-get install libxmu-dev libxi-dev
$ sudo apt-get install mono-complete
$ sudo apt-get install qt-sdk openjdk-8-jdk openjdk-8-jre

我其实没有全部都装,比如libeigen3-dev,很明显咱们已经装过了Eigen。但是,为了完整性,其实是我不想挑选了,总之大家择其善者而从之吧。

3) 安装pcl

1
2
3
4
5
6
7
$ cd pcl
$ mkdir release
$ cd release
$ cmake -DCMAKE_BUILD_TYPE=None -DCMAKE_INSTALL_PREFIX=/usr \
-DBUILD_GPU=ON -DBUILD_apps=ON -DBUILD_examples=ON \
-DCMAKE_INSTALL_PREFIX=/usr ..
$ make

这一步得等个几十分钟。。。然后执行以下

1
$ sudo make install

4) 测试pcl

以下内容是原创,鼓掌。

a. 创建工作目录

1
2
3
$ mkdir ~/pcl-test
$ cd ~/pcl-test
$ gedit pcd_write.cpp

b. 编辑如下代码

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
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int
main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ> cloud;
// Fill in the cloud data
cloud.width = 5;
cloud.height = 1;
cloud.is_dense = false;
cloud.points.resize (cloud.width * cloud.height);
for (size_t i = 0; i < cloud.points.size (); ++i)
{
cloud.points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
cloud.points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
cloud.points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
}
pcl::io::savePCDFileASCII ("test_pcd.pcd", cloud);
std::cerr << "Saved " << cloud.points.size () << " data points to test_pcd.pcd." << std::endl;
for (size_t i = 0; i < cloud.points.size (); ++i)
std::cerr << " " << cloud.points[i].x << " " << cloud.points[i].y << " " << cloud.points[i].z << std::endl;
return (0);
}

c. 创建CMake编译文件

1
$ gedit CMakeLists.txt

写入如下内容

1
2
3
4
5
6
7
8
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(MY_GRAND_PROJECT)
find_package(PCL 1.3 REQUIRED COMPONENTS common io)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(pcd_write_test pcd_write.cpp)
target_link_libraries(pcd_write_test ${PCL_COMMON_LIBRARIES} ${PCL_IO_LIBRARIES})

d. 编译

1
2
3
4
5
$ cd ~/pcl-test
$ mkdir build
$ cd build
$ cmake ..
$ make

e. 执行

此时pcl-test/build文件夹中已经产生了可执行文件pcd_write_test,运行

1
$ ./pcd_write_test

如果看到下面内容大概就是安装成功了。

1
2
3
4
5
6
Saved 5 data points to test_pcd.pcd.
0.352222 -0.151883 -0.106395
-0.397406 -0.473106 0.292602
-0.731898 0.667105 0.441304
-0.734766 0.854581 -0.0361733
-0.4607 -0.277468 -0.916762

以上。写教程比装环境更累。