☰
DynaSLAM视觉SLAM动态场景解决方案:从源码编译到RGB-D数据集运行全指南
2026/10/14 4:38:06 网站建设 项目流程

做视觉SLAM的同学,应该都见过这样一个场景:在人流密集的走廊里,ORB-SLAM2的轨迹开始飘,地图点像被风吹散的蒲公英。动态物体一直是视觉里程计的大头难题,而DynaSLAM就是这个领域绕不开的开源项目之一。它把Mask R-CNN的分割结果和几何一致性验证揉进ORB-SLAM2,定位的同时把行人、车辆这类动态区域里的特征点剔掉,只让静态结构参与位姿估计和建图。

这篇文章基于Ubuntu18.04,把DynaSLAM从源码编译到跑通RGB-D数据集的完整过程捋一遍,包括依赖选型、Mask R-CNN权重处理、编译踩坑、运行评估和参数经验。适合刚接触动态SLAM的研究生、转做机器人感知的工程师,以及想评估语义-几何融合方案的同学。如果你正在纠结“怎么把深度学习模型塞进传统SLAM框架”,这个项目也是一个很好的解剖样本。

1. 项目整体拆解:DynaSLAM到底做了什么

1.1 两路检测:语义分割与几何验证

DynaSLAM对每一帧图像的处理可以拆成两条并行线索。第一路是语义分割,用Mask R-CNN识别画面里可能运动的物体类别,比如行人、自行车、汽车,生成像素级的分割掩码。拿到掩码之后不是简单把整块区域扔了,而是把落在掩码内部的ORB特征点从跟踪和建图流程里冻结掉。第二路是几何一致性验证,利用连续帧之间的极线约束,把那些语义分支没有识别出来的运动点再捞一遍。一个静态特征点在多帧之间应该满足基础矩阵的几何关系,不满足的就被判定为动态点并剔除。两路结果合并之后才交给ORB-SLAM2,位姿估计只基于剩余静态特征点。

为什么一定要双保险?纯语义派的缺点是“静止的行人也是行人”,把坐着不动的人全删了,既损失了可用于定位的特征,还可能因为局部特征过少导致跟踪失败。纯几何派的缺点在于刚起步的物体运动幅度小,短时间看不出来,等看出来了轨迹也早偏了。DynaSLAM把两条路互补起来,这也解释了为什么它在密集动态场景下的精度能明显优于单纯用ORB-SLAM2或者单纯用语义分割的方案。

1.2 三种传感器模式怎么选

DynaSLAM原生支持单目、RGB-D、双目三种传感器模式,配置难度和输出内容差别不小。

版本输入数据动态剔除依据静态背景修复适用场景
Monocular单目图像序列语义分割 + 几何验证无纯定位精度研究
RGB-D彩色图 + 深度图语义分割 + 几何验证 + 深度约束支持背景修复教学与评估首选
Stereo左右目图像语义分割 + 几何验证 + 视差约束无有双目硬件的场景

我最推荐第一次配置直接走RGB-D模式。一方面公开数据集里RGB-D序列最齐全,另一方面RGB-D版本能直接输出剔除动态物体后的静态稠密地图,还能对比背景修复前后的可视化效果,成就感最强。单目版本需要额外标定尺度,双目标定又依赖硬件的基线参数,新手容易卡在数据准备环节。

1.3 编译后你会得到什么

跑完整个流程之后,程序会输出相机轨迹文件(比如CameraTrajectory.txt、KeyFrameTrajectory.txt),RGB-D模式还会保存每一帧的掩码结果、去除动态物体后的背景图像,以及用于评估的轨迹数据。配合常用的轨迹评估工具,可以方便地与ORB-SLAM2、ORB-SLAM3做ATE、RPE的量化对比。这个“拿来就能产出可评估结果”的完成度,是这个仓库非常适合学习的原因之一。

2. 配置前的关键决策:版本与依赖选型

2.1 硬件与系统基线

先说硬件。最好有独立显卡,显存4GB起步、8GB比较舒服。Mask R-CNN虽然只是做推理,但每一帧都要过一遍网络,显存不足会直接OOM。没有GPU也不是不能玩,后面会提到纯几何模式,效果会缩水但代码能跑通。磁盘预留15GB左右,用来放源码、权重、数据集和解压中间文件。

系统为什么要锁定Ubuntu18.04?因为这个项目验证过的组合就是GCC7、Python3.6、OpenCV3.4这一套,在Ubuntu18.04上最顺。Ubuntu20.04也能装,但要额外处理Python3.8和TensorFlow1.x的兼容性问题,我见过不少人在这一步被劝退。第一次上手,尽量别在系统版本上发挥创造力。

2.2 一套验证过的依赖清单

我自己在多个环境里试过,最后稳定复现的版本组合是这样:

组件版本选择理由
Ubuntu18.04.6项目发布时的主流验证环境
GCC7.5.0系统自带,不需要额外升级
CMake3.10.2系统自带足够
OpenCV3.4.10与ORB-SLAM2代码兼容最稳
Eigen3.3.7apt仓库直接装
Pangolin0.6老版本变量名更匹配项目
Python3.6.13虚拟环境创建
TensorFlow-GPU1.15.0Mask R-CNN官方支持的版本线
Keras2.2.5Matterport Mask R-CNN验证过的版本
CUDA10.1与TensorFlow 1.15匹配
cuDNN7.6.5与CUDA 10.1配套
numpy1.16.6TensorFlow 1.15依赖旧接口

这个组合看起来保守,但每一步背后都有教训。TensorFlow 2.x的Keras API变化很大,Mask R-CNN代码不经过大改跑不起来;numpy一旦高过1.19,TF1.15加载时基本都会报错。版本锁死,是DynaSLAM配置里最重要的经验。

2.3 两个最隐蔽的版本坑

第一个坑是OpenCV版本。如果你系统里装过ROS,大概率会有一个3.2残留;如果手滑装了OpenCV 4.5,编译时满屏的cv::命名空间和模块路径报错。DynaSLAM主程序其实只用了OpenCV的core、imgproc、features2d这类基础模块,3.4.10和4.x的差异主要体现在头文件位置和部分API签名。与其一行行改代码,不如直接统一到3.4.10。

第二个坑是Python和C++的绑定方式。DynaSLAM并不是把Mask R-CNN导出成C++模型去推理,而是在C++里内嵌Python解释器,调用Mask R-CNN脚本跑分割,再把结果以图片文件形式交给C++主程序。这意味着编译时必须保证CMake找到的Python,和你安装TensorFlow那个Python是同一个解释器。如果CMake找到的是系统/usr/bin/python3,而你的虚拟环境是conda的python3.6,运行阶段会出现极其诡异的崩溃。我后面会专门展示怎么锁死Python路径。

3. 完整配置流程实录

3.1 安装基础依赖

先把系统需要的编译工具和库一次装齐。打开终端,执行:

sudo apt-get update sudo apt-get install -y build-essential cmake pkg-config \ libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev \ libglew-dev libglfw3-dev libeigen3-dev libboost-all-dev \ libprotobuf-dev protobuf-compiler \ libgoogle-glog-dev libgflags-dev libblas-dev liblapack-dev libsuitesparse-dev

逐一说明这些包是干什么的:build-essential负责编译;pkg-config帮CMake找到库;libgtk2.0-dev和avcodec/swscale是OpenCV的GUI和视频读写依赖;glew和glfw是Pangolin画OpenGL窗口用的;eigen3是SLAM里最基础的线性代数库;boost以及suitesparse、blas、lapack是g2o这类图优化库的底层依赖。装完syscheck一下,确保cmake和gcc版本正常。

3.2 编译OpenCV 3.4.10

OpenCV建议源码编译,从这里开始就不要再用apt装了。下载OpenCV 3.4.10源码后执行:

mkdir build && cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D WITH_CUDA=OFF \ -D BUILD_opencv_python3=ON .. make -j8 sudo make install

关掉CUDA模块的原因很简单:DynaSLAM用不到OpenCV的CUDA加速,开着反而容易出现编译依赖问题。把Python3模块编进去是为了让后续Mask R-CNN脚本与C++主程序使用同一套OpenCV底层,减少莫名其妙的API行为差异。

3.3 编译Pangolin

Pangolin是ORB-SLAM2家族通用的可视化库。DynaSLAM原版文档里用的Pangolin版本比较老,建议在代码托管平台找历史版本,签出v0.6:

git clone <Pangolin仓库地址> cd Pangolin git checkout v0.6 mkdir build && cd build cmake .. make -j8 sudo make install

注意如果系统里已经通过ROS装过Pangolin,新旧版本会抢资源,建议编译安装到/usr/local覆盖旧版本。装完之后可以用一个小程序或者直接编译主工程来验证。

3.4 创建Python虚拟环境并安装深度学习栈

这一步适合用conda或virtualenv隔离环境,避免污染系统Python。我常用conda:

conda create -n dynaslam python=3.6 -y conda activate dynaslam pip install tensorflow-gpu==1.15.0 keras==2.2.5 pip install numpy==1.16.6 scipy==1.2.1 Pillow==6.2.2 matplotlib==3.1.3 scikit-image==0.16.2 cython==0.29.21

装完后立刻验证:

python -c "import tensorflow as tf; print(tf.__version__)" python -c "import keras; print(keras.__version__)"

这两条能通过,后续网络部分就稳了一半。上述版本号不是随手写的:Keras2.2.5是Matterport的Mask R-CNN验证过的版本,Keras2.3以上会碰到API断裂;numpy锁定在1.16.6是因为TF1.15内部还在用numpy旧接口,版本太高会出现多个module系统报错。

3.5 下载源码、词典与预训练权重

接下来做三件事:拉代码、解压词典、放权重。

git clone <DynaSLAM原版仓库地址> cd DynaSLAM tar -xf Vocabulary/ORBvoc.txt.tar.gz -C Vocabulary/

ORB-SLAM2家族的代码启动时都会查找Vocabulary/ORBvoc.txt这个词典文件,解压位置错了会直接起不来。解压出来的文件如果叫ORBvoc.txt,路径就是正确的。

然后下载Mask R-CNN的预训练权重,文件大约几百MB,放到src/python/mask_rcnn/logs/目录下,名字保持mask_rcnn_coco.h5。这个路径是脚本默认的模型目录,放错的话运行时会提示找不到权重。如果还想用RGB-D模式的静态背景修复功能,还需要下载对应的inpainting模型权重,按README里的路径说明放置。

3.6 锁定CMakeLists中的Python路径

这一步直接决定运行阶段会不会崩溃。打开DynaSLAM根目录下的CMakeLists.txt,找到Python相关配置,改成你的虚拟环境绝对路径:

set(PYTHON_INCLUDE_DIR "/你的conda路径/envs/dynaslam/include/python3.6m") set(PYTHON_LIBRARY "/你的conda路径/envs/dynaslam/lib/libpython3.6m.so") set(PYTHON_EXECUTABLE "/你的conda路径/envs/dynaslam/bin/python3.6")

这样编译出来的可执行文件在运行时,Py_Initialize启动的就是同一个解释器,后续import tensorflow时不会跨版本加载。另外,源码里凡是涉及Mask R-CNN输出目录、权重路径的常量,比如MaskNet.cpp里的ROOT_DIR、IMAGE_DIR、MASK_DIR,都建议改成你自己的绝对路径。路径中一定不要出现中文,也不要有空格。

3.7 编译主工程

mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make -j$(nproc)

编译过程如果报错,大概率集中在Thirdparty里的DBoW2和g2o。这时候别急着整目录删除重来,先把Thirdparty下对应子目录的build文件清理掉,单独编译一次,再回来编译主工程。我在第一次配置时就是载在g2o的依赖顺序上,多试几次就顺了。

3.8 准备数据并跑通第一条序列

用公开RGB-D数据集里的walking_xyz动态序列。原版README里写了下载入口,序列文件比较大,建议放机械硬盘或者固态剩余空间充足的位置。下载后需要自己生成彩色图和深度图的时间戳关联文件,标准做法是用数据集官方提供的associate.py脚本:

python associate.py rgb.txt depth.txt > associations.txt

把associations.txt放到Examples/RGB-D/associations/目录下。然后执行:

export PYTHONPATH=/你的DynaSLAM路径/src/python ./Examples/RGB-D/dynaslam_rgbd_tum \ Vocabulary/ORBvoc.txt \ Examples/RGB-D/TUM3.yaml \ /data/rgbd_dataset_walking_xyz \ Examples/RGB-D/associations/associations.txt

启动后终端会先打印加载Mask R-CNN权重的日志,这一步通常要等几十秒,然后开始逐帧输出mask生成、特征点剔除、位姿估计的信息。我实际跑的时候一帧大约需要几秒,整个序列几百帧,跑完需要十几分钟,正好可以去做别的事。

3.9 纯几何模式的编译开关

如果没有GPU,或者想先把整个流程跑通再上深度学习,可以编译纯几何模式。原仓库通常会提供一个不调用语义分割分支的可执行文件,或者通过CMake选项关闭Mask R-CNN。这个模式只依赖多视图几何剔除动态点,速度大幅提升,但在低纹理、动态物体占比高的场景下效果会明显下降。我的建议是:第一次实验先确保完整版能跑通,纯几何模式作为对照实验很有价值,但不要省掉语义环节。

4. 实验效果评估与参数调优

4.1 动态序列上能达到什么精度

我在公开动态序列上跑下来的情况大致如下表,不同commit的数值可能有出入,但趋势很稳定:

模式轨迹误差趋势动态场景表现
ORB-SLAM2误差大,几十厘米级地图被动态点污染,轨迹漂移明显
纯几何模式较明显下降,厘米级多数动态点被去掉,快速运动仍有残留
完整版DynaSLAM进一步下降动态区域干净,静态地图完整度最高

如果你的对比实验里ORB-SLAM2也跑得很好,很可能是你选的序列动态物体占比太低。DynaSLAM的优势一定要在密集动态场景下才能体现,测试时选择人流往复走动的序列,效果差异一目了然。

4.2 想调参数,先看这几个

Mask R-CNN的置信度阈值:默认在0.7附近,阈值太高容易漏检,太低会误删静态区域。我跑密集人群时习惯降到0.5,具体要看你的场景。

类别过滤:如果目标环境里只有人,可以在脚本里把类别过滤成person,避免误删动物或车辆带来的额外损失。

ORB特征数量:ORBextractor.nFeatures默认是1000,动态场景下被剔除的点多,建议先提高到2000,给静态区域留足余量。

几何验证阈值:这个参数控制“多大的极线误差算动态点”,调太松会把慢速运动点放进来,调太紧会把正常视差判成动态。它是保底机制,新手不建议乱动,先把语义部分跑好再回头调这个。

4.3 为什么它跑不快

Mask R-CNN的推理一帧大约0.3到0.6秒,加上图像读写、特征提取、掩码文件IO、C++与Python之间的切换,整帧耗时被拉到秒级。这不是暴力优化就能解决的,因为DynaSLAM的定位本来就是离线评估和地面真值建图,实时性不是它的目标。想在实车或机器人上实时跑,思路是把语义模块替换成轻量分割网络,并让mask通过共享内存在模块间传递而不是每次写文件,第6节会展开聊。

5. 常见问题速查与避坑实录

5.1 编译期问题速查

现象原因解决办法
cmake提示找不到OpenCVOpenCV_DIR路径没指对在CMakeLists中显式指定OpenCV_DIR为/usr/local/lib/cmake/opencv3
链接时报cv:: undefined referenceOpenCV版本混杂或链接了多个OpenCV确保系统只有一个OpenCV,检查CMake缓存里的OpenCV_INCLUDE_DIRS
Pangolin编译缺GLFW缺少窗口依赖安装libglfw3-dev,并确认拉的是Pangolin v0.6而不是最新master
找不到libpythonCMake自动探测到错误的Python手动指定-DPYTHON_LIBRARY配合Python虚拟环境

5.2 运行期问题速查

运行时Segmentation Fault,这是出现频率最高的问题。多半是Python路径不匹配,或者PYTHONPATH设置错误导致PyImport失败后的空指针。解决方法是编译前锁死CMakeLists里的Python路径,运行时再export PYTHONPATH,并在代码启动处临时打印Python版本验证。

提示找不到权重文件mask_rcnn_coco.h5,说明权重没放在ROOT_DIR/logs目录下,或者ROOT_DIR常量还指向仓库里的示例路径。改成你的绝对路径就能解决。

GPU显存OOM,Mask R-CNN推理很吃显存。推理batch一般已经是1,如果还OOM就关掉其他占用显存的进程,或者换到显存更大的机器。实在不行就切纯几何模式保底。

TensorFlow报错找不到cudnn/cublas,这是CUDA和cuDNN版本与TF1.15不匹配。我用的是CUDA 10.1配cuDNN 7.6.5,这个组合非常稳。

5.3 mask结果异常速查

mask一直是全黑的,说明脚本没有正确执行,单独把脚本拉出来对一张图跑一遍,看报错信息。

mask轮廓特别粗糙,这是图像缩放尺寸导致的正常现象,对结果影响不大。

mask覆盖范围明显偏大,多半是置信度阈值太低,或者训练模型的类别分割框偏保守。低阈值会放大误删风险,调的时候注意观察静态区域是否被连带剔除。

5.4 轨迹评估异常速查

轨迹绝对误差大但整体形状正确,对单目是尺度问题,对RGB-D要检查深度图有没有做时间戳对齐。

动态序列跑出来和ORB-SLAM2差别不大,基本可以断定语义分支没启用。检查可执行文件名是dynaslam开头还是普通rgbd_tum,以及启动日志中有没有出现“Loading Mask R-CNN”字样。

跑到一半丢失跟踪,多半是动态物体占比太高,静态特征点太少。提高ORB特征数量,适当放松几何验证阈值,会有明显改善。

6. 个人经验与扩展玩法

6.1 我的最终配置组合

我最后留下的是Ubuntu 18.04加OpenCV 3.4.10加Pangolin 0.6加Python 3.6加TensorFlow 1.15加Keras 2.2.5,前后折腾了整整两天。最大的教训就是版本一定要一次性锁死,别混着apt里的旧OpenCV和conda里的新Python库一起用。如果你只是验证算法,建议直接复用这组版本,把所有依赖编译好再跑通一条RGB-D序列,之后再考虑升级。

6.2 跑自己的数据集

想用自己的数据,需要准备RGB-D相机采集的图像序列,然后改Examples/RGB-D下的yaml参数为你的相机内参。用官方associate.py把彩色图和深度图的时间戳对齐,生成associations.txt。这里最容易被忽略的是YAML里的fps参数,填错会导致时间戳映射错乱。路径统一用英文,不要有中文目录。

如果只有单目相机,也能跑,但单目尺度不可观,动态剔除的结果评估会受影响。单目模式更适合看轨迹形状,不适合直接比较绝对误差。

6.3 值得动手的改进方向

如果你想在这个项目基础上做点自己的东西,我建议从这几个方向下手。

第一,把Mask R-CNN替换成轻量实例分割网络,比如YOLACT,速度能提升到接近实时,代价是掩码边缘精度下降。第二,把mask的输出方式从文件IO改成共享内存或直接进程间通信,能砍掉大量磁盘读写时间。第三,在语义层加入“人静止时保留特征点”的策略,因为站着不动的人其实可以作为临时静态特征辅助定位。第四,把动态点剔除结果保存成label真值,用来评估其他动态SLAM算法,这个思路在学术论文里很常见。

最后分享一个小经验。配置DynaSLAM最忌“边装边试”,先在这套固定版本矩阵里复原出基线,再逐个升级组件,出了问题也容易定位。跑通RGB-D完整版的那一刻,你能同时看到语义分割出来的干净背景,以及稳定输出的静态地图,成就感远比自己瞎调半天参数来得强。如果你也准备入动态SLAM的坑,这个项目值得花一个完整的周末。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询