配置GCNv2_SLAM所需的环境并实现纯cpu运行项目的全过程记录。

前排提醒:本文所述安装方式只在没有显卡的虚拟机上通过了测试,有显卡的主机涉及到CUDA等显卡依赖项版本问题,本文可能不适用

1. 环境说明

GCNv2_SLAM是比较出名的基于RGB-D传感器的SLAM系统之一,对应的论文和github如下:

不过,对新手不友好的一点是,项目github的readme里面并没有详细的描述如何安装依赖项和运行这个项目(毕竟论文开源代码的目标人群都是会SLAM的),在慕雪搜索相关资料的时候还遇到了大量水文,给本来就不太了解opencv和pytorch的我造成了更大的困扰。

不过,最终我还是搜索到了几篇写的很不错的导引文章,里面详细说明了如何在纯CPU环境中运行这个项目,包括安装依赖项的全过程。

本文是对上述博客的汇总和记录,同时我还将GCNv2_SLAM的运行环境制作成了dockerfile,可以在支持docker的linux桌面环境中运行。该镜像只在parallels的ubuntu-22.04-arm64虚拟机中测试过,不保证对其他环境也适用。

你可以在我的github中找到修改过后的项目和dockerfile:https://github.com/musnows/GCNv2_SLAM/tree/cpu;构建docker镜像和使用docker容器运行GCNv2项目的引导可见:musnows/GCNv2_SLAM/docker/README

前期准备:

  • ubuntu-18.04-desktop虚拟机或支持docker的ubuntu-desktop虚拟机;
  • 一个能正常clone到github项目的网络环境(不然会很烦);

话不多说,开整!

2. 安装依赖项

项目运行主要要手动安装4个依赖项,以及数不清的apt包。

2.1. 基础apt包安装

运行之前先更新一下环境

1
2
sudo apt-get update -y
sudo apt-get upgrade -y

首先是要用的到的工具包(这些都用得上)

1
2
3
4
5
6
7
8
# 工具包
sudo apt-get install -y \
apt-utils \
curl wget unzip zip \
cmake make automake \
openssh-server \
net-tools \
vim git gcc g++

随后是python工具组

1
2
3
4
5
6
7
sudo apt-get install -y \
python-dev \
python-pip \
python3-dev \
python3-pip \
python-all-dev \
python3-all-dev

还需要安装x11相关的依赖包

1
2
3
4
5
6
7
8
# x11 for gui
sudo apt-get install -y \
libx11-xcb1 \
libfreetype6 \
libdbus-1-3 \
libfontconfig1 \
libxkbcommon0 \
libxkbcommon-x11-0

2.2. Pangolin 6.0

安装pangolin之前先安装如下依赖包

1
2
3
4
5
6
7
8
9
# pangolin
sudo apt-get install -y \
libgl1-mesa-dev \
libglew-dev \
libboost-dev \
libboost-thread-dev \
libboost-filesystem-dev \
libpython2.7-dev \
libglu1-mesa-dev freeglut3-dev

随后使用如下命令来编译安装Pangolin,Github地址:Pangolin-0.6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 下载
wget -O Pangolin-0.6.tar.gz https://github.com/stevenlovegrove/Pangolin/archive/refs/tags/v0.6.tar.gz
# 解压
tar -zxvf Pangolin-0.6.tar.gz

pushd Pangolin-0.6
rm -rf build
mkdir build && cd build
# 编译安装
cmake -DCPP11_NO_BOOST=1 ..
make -j$(nproc)
make install
# 刷新动态库
ldconfig
popd

image.png

随后使用如下命令检查是否安装成功

1
2
3
4
5
# 检查安装成功(能不能编译demo)
cd Pangolin-0.6/examples/HelloPangolin
mkdir build && cd build
cmake ..
make

一切正常的话,应该能编译成功。

1
2
3
4
5
root@ubuntu-linux-22-04-02-desktop:/work/docker/Pangolin-0.6/examples/HelloPangolin/build# make
Scanning dependencies of target HelloPangolin
[ 50%] Building CXX object CMakeFiles/HelloPangolin.dir/main.o
[100%] Linking CXX executable HelloPangolin
[100%] Built target HelloPangolin

随后执行./HelloPangolin运行程序(需要在GUI环境中执行),如果出现了一个三色正方体的弹窗就是ok了

image.png

2.3. OpenCV 3.4.5

先安装依赖项

1
2
3
4
5
6
7
8
9
10
# 解决:Unmet dependencies.Try'apt--fix-broken install'with no packages(or specify a solution)
sudo apt --fix-broken install
sudo apt-get update
sudo apt-get upgrade
# 安装依赖项
sudo apt-get install -y \
build-essential libgtk2.0-dev \
libavcodec-dev libavformat-dev \
libjpeg.dev libtiff5.dev libswscale-dev \
libcanberra-gtk-module

opencv的依赖项libjasper包在arm64和amd64上有区别,如果是amd64环境,使用如下命令安装。命令已在ubuntu18.04虚拟机中测试通过,就是security.ubuntu.com可能会因为网络问题无法联通,多试几次就OK了。

1
2
3
4
5
6
7
# amd64
# 添加新源后继续安装
sudo apt-get install -y software-properties-common
# 下面这条命令实测在arm64上不能用,先不要执行
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt-get -y update
sudo apt-get install -y libjasper1 libjasper-dev

如果是arm64,使用上面的命令安装会出现404错误,在本站另外一篇博客中有记录。

1
2
3
4
5
6
Err:6 http://security.ubuntu.com/ubuntu xenial-security/main arm64 Packages
404 Not Found [IP: 185.125.190.83 80]
Fetched 106 kB in 2s (44.6 kB/s)
Reading package lists... Done
E: Failed to fetch http://security.ubuntu.com/ubuntu/dists/xenial-security/main/binary-arm64/Packages 404 Not Found [IP: 185.125.190.83 80]
E: Some index files failed to download. They have been ignored, or old ones used instead.

在arm64上需要借助老版本的清华源来安装,将如下命令写入脚本文件使用sudo执行。

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env bash
set -e
# arm64 ubuntu 18.04
echo -e "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial main multiverse restricted universe\n\
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial-security main multiverse restricted universe\n\
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial-updates main multiverse restricted universe\n\
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial-backports main multiverse restricted universe\n\
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial main multiverse restricted universe\n\
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial-security main multiverse restricted universe\n\
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ xenial-updates main multiverse restricted universe" >> /etc/apt/sources.list && \
apt-get -y update
apt-get install -y libjasper1 libjasper-dev
arm64成功安装libjasper的命令行输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@ubuntu-linux-22-04-02-desktop:/# apt-get install -y libjasper1 libjasper-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
libjasper-runtime
The following NEW packages will be installed:
libjasper-dev libjasper1
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 613 kB of archives.
After this operation, 1327 kB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports xenial-security/main arm64 libjasper1 arm64 1.900.1-debian1-2.4ubuntu1.3 [111 kB]
Get:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports xenial-security/main arm64 libjasper-dev arm64 1.900.1-debian1-2.4ubuntu1.3 [502 kB]
Fetched 613 kB in 1s (758 kB/s)
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 2.)
debconf: falling back to frontend: Readline
Selecting previously unselected package libjasper1:arm64.
(Reading database ... 67223 files and directories currently installed.)
Preparing to unpack .../libjasper1_1.900.1-debian1-2.4ubuntu1.3_arm64.deb ...
root@ubuntu-linux-22-04-02-desktop:/#

安装好了依赖项后,使用如下命令编译opencv,Github地址:opencv的3.4.5版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 下载和解压
wget -O opencv-3.4.5.tar.gz https://github.com/opencv/opencv/archive/refs/tags/3.4.5.tar.gz
tar -zxvf opencv-3.4.5.tar.gz
# 开始编译和安装
pushd opencv-3.4.5
rm -rf build
mkdir build && cd build
# 构建和编译安装,-j4代表4线程并发
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
make -j$(nproc)
make install
# 刷新动态库
ldconfig
popd

使用如下命令检测opencv是否安装成功

1
2
3
4
5
6
root@ubuntu-linux-22-04-02-desktop:/work/docker/pkg/opencv-3.4.5/build# pkg-config --modversion opencv
3.4.5
root@ubuntu-linux-22-04-02-desktop:/work/docker/pkg/opencv-3.4.5/build# pkg-config --cflags opencv
-I/usr/local/include/opencv -I/usr/local/include
root@ubuntu-linux-22-04-02-desktop:/work/docker/pkg/opencv-3.4.5/build# pkg-config --libs opencv
-L/usr/local/lib -lopencv_dnn -lopencv_ml -lopencv_objdetect -lopencv_shape -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_imgproc -lopencv_flann -lopencv_core

可以试试编译测试demo代码,注意需要在GUI环境中执行

1
2
3
4
5
6
# 检测是否安装成功
cd opencv-3.4.5/samples/cpp/example_cmake
mkdir build && cd build
cmake ..
make
./opencv_example

如果成功运行,会弹出一个hello opencv的弹窗。如果你的环境有摄像头,则会出现摄像头画面,如果没有摄像头,则为黑屏画面。

image.png

如果运行这个demo的时候遇到了Failed to load module "canberra-gtk-module"错误,是因为缺少了一个软件包,安装一下就可以了(上文安装包中已经列出)。

1
sudo apt-get install libcanberra-gtk-module

image.png

2.4. Eigen 3.7

Eigen包在gitlab里面下载:gitlab.com/libeigen/eigen/-/releases/3.3.7

1
2
3
4
5
6
7
8
9
# 下载
wget -O eigen-3.3.7.tar.gz https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz
tar -zxvf eigen-3.3.7.tar.gz
# 开始编译和安装
cd eigen-3.3.7
mkdir build && cd build
cmake ..
make
make install

注意需要执行cp命令拷贝一下头文件到另外一个目录中

1
2
3
4
# 在很多程序中include时经常使用#include <Eigen/Dense>而不是使用#include <eigen3/Eigen/Dense>
# 因此安装后需要将头文件从 /usr/local/include/eigen3/ 复制到 /usr/local/include
# 后续小节会有C++测试代码说明
sudo cp -r /usr/local/include/eigen3/Eigen /usr/local/include

这里给出一个cpp的demo代码来测试是否安装成功(直接g++编译就可以了)

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
#include <iostream>
//需要将头文件从 /usr/local/include/eigen3/ 复制到 /usr/local/include
#include <Eigen/Dense>
//using Eigen::MatrixXd;
using namespace Eigen;
using namespace Eigen::internal;
using namespace Eigen::Architecture;
using namespace std;
int main()
{
cout<<"*******************1D-object****************"<<endl;
Vector4d v1;
v1<< 1,2,3,4;
cout<<"v1=\n"<<v1<<endl;

VectorXd v2(3);
v2<<1,2,3;
cout<<"v2=\n"<<v2<<endl;

Array4i v3;
v3<<1,2,3,4;
cout<<"v3=\n"<<v3<<endl;

ArrayXf v4(3);
v4<<1,2,3;
cout<<"v4=\n"<<v4<<endl;
}

运行结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@ubuntu-linux-22-04-02-desktop:/work/docker/pkg/eigen-3.3.7/build# g++ test.cpp -o test_eigen
root@ubuntu-linux-22-04-02-desktop:/work/docker/pkg/eigen-3.3.7/build# ./test_eigen
*******************1D-object****************
v1=
1
2
3
4
v2=
1
2
3
v3=
1
2
3
4
v4=
1
2
3

2.5. Pytorch 1.0.1 (libtorch)

原博客中安装的是1.4.0,但是在我测试的arm环境中1.4.0有非常多的错误,这里直接采用GCNv2 Github中给出的1.0.1版本进行安装。

安装之前需要保证环境中有python3(测试环境为3.6.9)并安装pyyaml包

1
2
sudo apt-get install python3-dev python3-pip
pip3 install pyyaml

随后克隆pytorch并编译libtorch动态库

1
2
3
git clone --recursive -b v1.0.1 https://github.com/pytorch/pytorch
cd pytorch && mkdir build && cd build
python3 ../tools/build_libtorch.py

这里就有难题啦!整个pytorch的库加上sub-modules一共有3gb之大,要想从github上安稳克隆下来可不简单。这里给大家分享一个百度云盘的链接,是所有子模组都被成功clone之后的压缩包。

1
2
通过网盘分享的文件:pytorch.full.1.0.1.tar.gz
链接: https://pan.baidu.com/s/1XHeYcHH5CMKmacFodFzqeA 提取码: 4h2g

下载了这个压缩包,使用tar -zxvf解压后,使用如下命令检查一下子模组是否完整,如果完整的话这个命令不会有任何输出。不完整它会继续下载子模组

1
git submodule update --init --recursive

在执行python3 ../tools/build_libtorch.py之前还需要进行两处代码的修改,这里直接给出sed命令,在pytorch库的根目录执行。

1
2
sed -i "s/yaml.load(\(.*\))/yaml.load(\1, Loader=yaml.FullLoader)/g" aten/src/ATen/cwrap_parser.py
sed -i "s/yaml.load(\(.*\))/yaml.load(\1, Loader=yaml.FullLoader)/g" tools/cwrap/cwrap.py

两个代码文件中都只有一处要修改的地方,分别是pytorch/tools/cwrap/cwrap.py文件里面的91行和pytorch/aten/src/ATen/cwrap_parser.py的18行。

这里的修改是因为pyyaml库的变动(环境中安装的pyyaml版本为6.0.1),需要传入第二个参数Loader。原有的代码是没有传入的,编译的时候会出现如下错误,日志中的重点就是 TypeError: load() missing 1 required positional argument: 'Loader' 缺少参数的报错。

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
Traceback (most recent call last):
File "/work/pytorch/cmake/../aten/src/ATen/gen.py", line 465, in <module>
generate_outputs()
File "/work/pytorch/cmake/../aten/src/ATen/gen.py", line 390, in generate_outputs
for file in cwrap_files
File "/work/pytorch/cmake/../aten/src/ATen/gen.py", line 391, in <listcomp>
for d in cwrap_parser.parse(file)]
File "/work/pytorch/aten/src/ATen/cwrap_parser.py", line 18, in parse
declaration = yaml.load('\n'.join(declaration_lines))
TypeError: load() missing 1 required positional argument: 'Loader'
caffe2/CMakeFiles/ATEN_CPU_FILES_GEN_TARGET.dir/build.make:132: recipe for target 'aten/src/ATen/CPUByteType.cpp' failed
make[2]: *** [aten/src/ATen/CPUByteType.cpp] Error 1
CMakeFiles/Makefile2:3522: recipe for target 'caffe2/CMakeFiles/ATEN_CPU_FILES_GEN_TARGET.dir/all' failed
make[1]: *** [caffe2/CMakeFiles/ATEN_CPU_FILES_GEN_TARGET.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
[ 15%] Building CXX object third_party/protobuf/cmake/CMakeFiles/libprotobuf.dir/__/src/google/protobuf/wrappers.pb.cc.o
[ 15%] Linking CXX static library ../../../lib/libprotobuf.a
[ 15%] Built target libprotobuf
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2
Traceback (most recent call last):
File "../tools/build_libtorch.py", line 30, in <module>
subprocess.check_call(command, universal_newlines=True, env=my_env)
File "/usr/lib/python3.6/subprocess.py", line 311, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/work/pytorch/tools/build_pytorch_libs.sh', '--use-nnpack', '--use-qnnpack', 'caffe2']' returned non-zero exit status 2.

说实话,个人认为pyyaml库的这个变动非常不合理,版本更迭后,一个强制需要传入的参数应该给出缺省值才对。如果它给出了缺省值,那么这里的代码即便没有传入也不会报错了。

修改了这两处代码后,执行python3 ../tools/build_libtorch.py,不出意外的话编译就成功啦。

image.png

原博主使用的pytorch 1.4.0需要解决的问题比我这里更多,如果你想通过pytorch 1.4.0来编译libtorch,请参考本文最开头贴出的博客。

3. 编译GCNv2_SLAM

接下来我们就可以编译正主啦!首先克隆代码

1
git clone https://github.com/jiexiong2016/GCNv2_SLAM.git

3.1. 修改build.sh编译项目

修改项目根目录下的build.sh,将TORCH_PATH修改为pytorch中的torch/lib/tmp_install/share/cmake/Torch目录。

1
cmake .. -DCMAKE_BUILD_TYPE=Release -DTORCH_PATH=/work/gcnv2slam/pytorch/torch/lib/tmp_install/share/cmake/Torch

修改了之后,应该就可以执行./build.sh来编译项目了。

比较奇怪的是我的环境中并没有cuda也依旧能在不修改任何代码的情况下编译成功。

最开始的时候,我遇到了一个难题,参考的博客中大多数都用的pytorch 1.4.0,里面都提到了修改TORCH_PATHpytorch/torch/share/cmake/Torch目录,但是在我的pytorch 1.0.1里面压根没有这个目录。

本来都要放弃了,最终在GCNv2项目的github里面找到了说明,主要的修改点是jiexiong2016/GCNv2_SLAM/commit/21cc44894这一笔提交,readme里面描述如下

The built libtorch library is located at pytorch/torch/lib/tmp_install/ in default.

Update: Have added support for master branch of pytorch or version larger than 1.0.1. For newer version, set TORCH_PATH to pytorch/torch/share/cmake/Torch

说白了就是在1.0.1版本中的TORCH_PATH是在pytorch/torch/lib/tmp_install/里面的,更新的pytorch版本是在pytorch/torch/share目录,而1.0.1版本中不存在pytorch/torch/share目录。

3.2. 修改代码来实现纯CPU运行

3.2.1. 修改GCNextractor.cc

第一处修改点在GCNv2_SLAM/src/GCNextractor.cc文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//第一处原代码216行:
const char *net_fn = getenv("GCN_PATH");
net_fn = (net_fn == nullptr) ? "gcn2.pt" : net_fn;
module = torch::jit::load(net_fn);
//修改为:
torch::DeviceType device_type;
device_type = torch::kCPU;
torch::Device device(device_type);
const char *net_fn = getenv("GCN_PATH");
net_fn = (net_fn == nullptr) ? "gcn2.pt" : net_fn;
module = torch::jit::load(net_fn,device);

//第二处原代码226行:
device_type = torch::kCUDA;
//修改为:
device_type = torch::kCPU;

修改后的截图如下

image.png

3.2.2. 修改GCN2下pt文件

其实pt文件是不影响编译的,可以在编译完成后再修改

修改GCNv2_SLAM/GCN2下gcn2_320x240.pt、gcn2_640x480.pt和gcn2_tiny_320x240.pt中的内容。需要先解压文件

1
unzip gcn2_320x240.pt

解压出来之后会有GCNv2_SLAM/GCN2/gcn/code/gcn.py文件,将里面的cuda:0修改成cpu,批量替换就可以了,每个文件里面都是8处。

image.png

替换了之后,重新压缩pt文件,先删了原本的,重新压缩

1
2
3
rm -rf gcn2_320x240.pt
zip -r gcn2_320x240.pt gcn
rm -rf gcn #删除刚刚的gcn文件夹

这只是一个例子,其他几个gcn2压缩包都要用相同的方式修改!

1
2
3
4
5
6
7
unzip gcn2_640x480.pt
rm -rf gcn2_640x480.pt
# 修改下面这个文件
# GCNv2_SLAM/GCN2/gcn2_480x640/code/gcn2_480x640.py
# 重新压缩
zip -r gcn2_640x480.pt gcn2_480x640
rm -rf gcn2_480x640
1
2
3
4
5
6
7
unzip gcn2_tiny_320x240.pt
rm -rf gcn2_tiny_320x240.pt
# 修改文件
# gcnv2slam/GCNv2_SLAM/GCN2/gcn2_tiny/code/gcn2_tiny.py
# 重新压缩
zip -r gcn2_tiny_320x240.pt gcn2_tiny
rm -rf gcn2_tiny

3.2.3. 重新编译

修改之后重新编译项目,没有问题,编译成功了。

1
2
3
4
5
6
7
8
9
10
11
12
Configuring and building ORB_SLAM2 ...
mkdir: cannot create directory 'build': File exists
Build type: Release
-- Using flag -std=c++11.
TORCH_PATH set to: /work/gcnv2slam/pytorch/torch/lib/tmp_install/share/cmake/Torch
-- Torch version is: 1.0.0
-- Configuring done
-- Generating done
-- Build files have been written to: /work/gcnv2slam/GCNv2_SLAM/build
[ 91%] Built target ORB_SLAM2
[100%] Built target rgbd_gcn
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM#

image.png

4. 使用TUM训练集运行项目

4.1. 下载数据集

下载地址:cvg.cit.tum.de/data/datasets/rgbd-dataset/download

下载fr1/desk数据集,这是一个桌子的RGBD数据

image.png

在GCNv2_SLAM工程下新建datasets/TUM,将数据集下载到其中

1
2
3
4
5
6
7
# 新建datasets/TUM数据集文件夹
mkdir -p datasets/TUM
cd datasets/TUM
# 下载数据集到datasets/TUM文件夹内
wget -O rgbd_dataset_freiburg1_desk.tgz https://cvg.cit.tum.de/rgbd/dataset/freiburg1/rgbd_dataset_freiburg1_desk.tgz
# 解压数据集
tar -xvf rgbd_dataset_freiburg1_desk.tgz

然后还需要下载一个associate.py脚本来处理一下数据集才能正常运行

下载地址:svncvpr.in.tum.de,同时在我的Github仓库也做了留档。

1
wget -O associate.py https://svncvpr.in.tum.de/cvpr-ros-pkg/trunk/rgbd_benchmark/rgbd_benchmark_tools/src/rgbd_benchmark_tools/associate.py

这个脚本只能用python2运行,需要下载numpy库(环境中python2是2.7.17)

1
2
3
4
5
# 容器内库安装
apt-get install -y python-pip
pip install numpy
# 在数据文件夹里执行命令
python associate.py rgbd_dataset_freiburg1_desk/rgb.txt rgbd_dataset_freiburg1_desk/depth.txt > rgbd_dataset_freiburg1_desk/associate.txt

注意下载numpy库的时候不要用镜像源,否则无法安装。直接下就行了。

1
2
3
4
5
6
7
8
9
10
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM/datasets/TUM# pip install numpy                            
Collecting numpy
Downloading https://files.pythonhosted.org/packages/b7/6f/24647f014eef9b67a24adfcbcd4f4928349b4a0f8393b3d7fe648d4d2de3/numpy-1.16.6.zip (5.1MB)
100% |################################| 5.2MB 470kB/s
Building wheels for collected packages: numpy
Running setup.py bdist_wheel for numpy ... done
Stored in directory: /root/.cache/pip/wheels/cb/c2/c1/d99e8bf789c8dd07623af6be95e6a89984c85a05e31b8513c3
Successfully built numpy
Installing collected packages: numpy
Successfully installed numpy-1.16.6

执行python命令后可以看看合并成功了没有,如下应该就是没问题了。

1
2
3
4
5
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM/datasets/TUM# python associate.py rgbd_dataset_freiburg1_desk/rgb.txt rgbd_dataset_freiburg1_desk/depth.txt > rgbd_dataset_freiburg1_desk/associate.txt
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM/datasets/TUM# tail rgbd_dataset_freiburg1_desk/associate.txt
1305031472.895713 rgb/1305031472.895713.png 1305031472.892944 depth/1305031472.892944.png
1305031472.927685 rgb/1305031472.927685.png 1305031472.924814 depth/1305031472.924814.png
1305031472.963756 rgb/1305031472.963756.png 1305031472.961213 depth/1305031472.961213.png

在同一个网站下载的其他数据集也需要用相同的方式进行处理

4.2. 运行GCN2

随后进入项目的GCN2目录执行命令,我把命令中的路径都改成了相对路径

1
2
cd GCN2
GCN_PATH=gcn2_320x240.pt ./rgbd_gcn ../Vocabulary/GCNvoc.bin TUM3_small.yaml ../datasets/TUM/rgbd_dataset_freiburg1_desk ../datasets/TUM/rgbd_dataset_freiburg1_desk/associate.txt

如果运行tiny数据集,命令如下

1
2
cd GCN2
GCN_PATH=gcn2_tiny_320x240.pt ./rgbd_gcn ../Vocabulary/GCNvoc.bin TUM3_small.yaml ../datasets/TUM/rgbd_dataset_freiburg1_desk ../datasets/TUM/rgbd_dataset_freiburg1_desk/associate.txt

在mac上虚拟机安装的arn版本ubuntu22.04中用docker安装的ubuntu18.04成功运行本项目,虽然很卡,但是运行起来了!

image.png

image.png

最终结束后的输出如下

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
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM# cd GCN2/
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM/GCN2# GCN_PATH=gcn2_320x240.pt ./rgbd_gcn ../Vocabulary/GCNvoc.bin TUM3_small.yaml ../datasets/TUM/rgbd_dataset_freiburg1_desk ../datasets/TUM/rgbd_dataset_freiburg1_desk/associate.txt

ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.

Input sensor was set to: RGB-D

Loading ORB Vocabulary. This could take a while...
Vocabulary loaded!


Camera Parameters:
- fx: 267.7
- fy: 269.6
- cx: 160.05
- cy: 123.8
- k1: 0
- k2: 0
- p1: 0
- p2: 0
- fps: 30
- color order: RGB (ignored if grayscale)

ORB Extractor Parameters:
- Number of Features: 1000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7

Depth Threshold (Close/Far Points): 5.97684

-------
Start processing sequence ...
Images in the sequence: 573

New map created with 251 points
Finished!
-------

median tracking time: 1.7969
mean tracking time: 1.82306

Saving camera trajectory to CameraTrajectory.txt ...

trajectory saved!

Saving keyframe trajectory to KeyFrameTrajectory.txt ...

trajectory saved!
root@ubuntu-linux-22-04-02-desktop:/work/gcnv2slam/GCNv2_SLAM/GCN2#

同时我在vmware16安装的ubuntu18.04虚拟机中也运行了本项目,速度更慢。宿主机配置为牙膏厂的i5-10400+16GB内存,虚拟机分配了8核8GB。

image.png

image.png

4.3. 简单分析一下结果

在mac m3 16G上parallels安装的arm64版本ubuntu22.04虚拟机(4核8G)中用docker运行的ubuntu18.04容器,容器内运行gcn2_320x240.pt的速度如下,约合0.55hz

1
2
median tracking time: 1.7969
mean tracking time: 1.82306

在vmware16安装的amd64版本ubuntu18.04的虚拟机(8核8G)中,运行gcn2_320x240.pt的速度如下,约合0.21hz。没想到比arm的速度还慢!

1
2
median tracking time: 4.70296
mean tracking time: 4.62603

作为对比,GCNv2论文中提到了两个平台的运行结果,翻译如下

“GCNv2和我们改进了SLAM方法的GCN-SLAM,在配备Intel i7-7700HQ和移动版NVIDIA 1070的笔记本电脑上运行约80 Hz。为了实现更高的帧率,以满足Jetson TX2上实时推理的需求,我们引入了GCNv2的一个较小版本,称为GCNv2-tiny,在此版本中,我们从conv2开始将特征图的数量减少了一半。GCNv2-tiny运行在40 Hz,使用GCNv2-tiny的GCN-SLAM在TX2上运行为20 Hz,非常适合部署在无人机上。”

image.png

只能说纯CPU运行的效果也太差了!应该是因为GCNv2_SLAM项目有用到神经网络,所以没有显卡的话速度会非常慢。

5. The end

折腾了好几天,才成功把GCNv2_SLAM需要的环境给配置好,可惜最终用CPU运行的效果也太差了,不知道有没有办法优化一下。

另外,我似乎没搜到GCNv2_SLAM在较新一点的带N卡的电脑(比如30系以后的N卡)中运行的教程博客,如果想用GPU来运行一下本项目,估计又是一个大麻烦事……