1. 为什么动态环境至今还是SLAM的“老大难”做视觉SLAM和SfM运动恢复结构的人大部分时间其实都在跟“静态世界假设”打交道。经典算法从原理上就默认场景是静止的——特征点提取、三角化、姿态估计、回环检测整条链路都建立在“我看到的特征点是固定不动的”这个前提上。一旦场景里出现行人、车辆、随风摇晃的树枝或者镜子里的虚像这套假设就会出问题轻则漂移加大重则直接追踪丢失。这篇关于动态环境下视觉SLAM与SfM的综述恰好把这个问题摊开来讲清楚了。它不是一个具体算法的复现笔记而是对整个领域研究脉络的梳理——动态物体怎么检测、怎么跟静态结构区分开、怎么把“动态”变成可利用的信息而不是干扰、SfM在动态场景下跟SLAM的差别又在哪里。对于刚要进入这个方向的研究者、做AR/VR定位的工程师、或者被动态场景折腾过的SLAM调参选手这篇综述的价值在于让你少走弯路至少能搞清楚自己遇到的问题属于哪一类对应哪条技术路线。我自己读这篇综述的感受是它把“动态环境”的复杂性分了好几个层次有持续运动的人车有间歇性运动的物体比如开关的门有自身运动导致的动态比如机器人抓手还有相机自身运动与场景运动耦合在一起的情况。这几种情况的技术难度完全不一样用的方法论也相差很大。如果不做分类上来就想着“我加一个目标检测网络把动态物体框出来”之类的方案大概率会被具体场景里的反例教做人。另外值得一提的是综述把Visual SLAM和SfM放在同一个框架下讨论而不是分成两个独立话题。这个视角对我自己梳理知识体系帮助很大——两者共享底层的几何与优化理论但在动态场景处理上有很本质的分工差异。2. 动态场景为什么难从假设崩塌说起2.1 静态世界假设是整个几何体系的基石要理解动态环境为什么难先得理解静态假设到底嵌在算法的哪里。以最经典的特征点法为例整个流程是这样的提取特征点计算描述子帧间匹配用对极几何求本质矩阵或基础矩阵再分解出旋转和平移。之后通过三角化得到路标点的三维坐标再用PnP求解当前帧的位姿最后丢进BABundle Adjustment里联合优化。这一整套流程里每一步都隐含着一个关键假设匹配上的特征点对应的是同一个物理点而且这个物理点在世界坐标系里的位置是不变的。三角化的时候我们是在用多个视角的光线交点去恢复一个固定的三维点。如果这个点其实在动那么这些光线根本不会交于同一个点——但因为噪声的存在算法还是会“强行”求出一个最小二乘意义上的交点。这个交点既不是物体的真实位置也不是它的历史轨迹上的任何一点而是一个毫无物理意义的虚拟点。这种错误点对位姿估计的影响是全局性的而且往往是渐进式的。单个错误匹配可能只造成几度的旋转误差但当视野里大量特征点都在物体上时整个位姿估计就会被拖着走最终导致里程计漂移、地图变形、回环检测失效。有一类经典的失败场景是在走廊里和行人相向而行行人在图像里占的比例可能超过一半这时候哪怕你用的是带RANSAC的经典管线位姿估计依然会崩溃。2.2 动态和静态的边界其实非常模糊综述里反复强调的一个观点是动态和静态的边界不是二值的而是一个光谱。严格来说现实中几乎没有绝对静止的场景——树叶在微风中摆动水面有波纹光照在变化导致阴影移动。但如果我们把所有这些都当作动态处理那场景里就没有什么是可用的了。所以工程上的做法是容忍“微小运动”把它们当作噪声处理只有显著运动才需要显式建模。这引出了一个核心问题如何定义“显著运动”。不同的应用对运动敏感度要求完全不同。AR场景下几厘米的抖动可能就让人感到眩晕而室外无人机定位中几十厘米的偏差可能都还能接受。综述里提到的处理策略大致有几种思路使用几何约束检测异常视差、极线约束、对极约束、使用语义信息识别可运动物体、使用显式的运动模型估计物体速度。这三种思路各有各的适用边界后面会展开讲。2.3 动态场景SfM和SLAM的差异SfM和SLAM都做相机姿态估计与场景重建但在动态环境下两者的核心矛盾点不同。SLAM强调实时性它面对的是一段连续的图像流可以用时序信息来判断哪些区域是动态的——上一帧的特征点下一帧去哪儿了运动是否一致。而SfM面对的往往是一堆无顺序的照片集比如从相册里挑选出的几十张旅游照片根本没有时序先验。你只能靠纯几何或多视角一致性来识别动态结构。另一个显著差异是优化策略。SLAM多用滤波或滑动窗口优化对动态信息的使用偏向“剔除”——把动态特征从优化问题中排除掉。而离线SfM因为不要求实时可以采用更复杂的全局优化策略甚至可以把动态物体当作独立的对象来重建它们的运动轨迹。综述里总结了这样一句话“SLAM倾向于在动态中找回静态SfM倾向于在静态中分离动态”。这句话基本概括了两者的方法论差异。提示如果你在自己做实验时发现同一个算法在SLAM数据集上效果好、在SfM数据集上很差先不要急着改算法先看清楚自己的任务到底属于哪一类——是“需要实时地从视频流中定位”还是“需要从照片集中重建场景”。这两者的动态处理策略很可能完全不同。3. 动态环境处理的技术路线全景3.1 基于几何约束的动态特征检测最经典的一类方法是用几何约束去筛动态特征核心思路是静态特征必须满足多视角几何约束动态特征则会违反这些约束。常用的约束包括对极约束、单应约束和三角化重投影误差约束。对极约束理解起来很直观假设相机在位置A和位置B分别拍摄了同一场景那么空间中的一个静态点在这两张图像上的投影必须满足极线方程——第一张图上的点对应的极线应该穿过第二张图上的匹配点。如果一个点匹配上了但它偏离极线的距离明显超出正常误差范围那就说明这个点在两张图像之间发生了运动判定为动态点。单应约束的思路也类似适用于平面场景或纯旋转运动静态平面点在两张图像间的坐标变换满足单应矩阵。如果匹配点偏离单应变换的投影位置很远那就是动态点。三角化重投影误差则是跟踪一段时间后先用三角化算出三维点再投影回图像如果误差很大就说明该点在跟踪期间发生了运动。这些几何方法的最大优势是不需要任何训练数据也不需要知道场景里有什么物体类别。它们的局限性也很明显——需要足够多的静态点来支撑约束估计。所有匹配点都在动态物体上时RANSAC也救不回来。另外几何方法对纯旋转、低视差等退化配置非常敏感容易把大量静态点误判为动态。3.2 基于语义信息的动态物体识别随着深度学习在视觉领域的普及用语义分割或目标检测网络先识别出“人”“车”等可运动物体然后把这些区域的点全部剔除成为了一种非常自然的思路。这类方法在SLAM社区里被称为“语义SLAM”代表性的做法是把分割网络输出的mask与特征点提取结果做叠加——落在mask内的特征点直接不用。纯语义方法的直白之处在于逻辑简单人可能会走、车可能会开所以这些区域的特征点不可靠。但这个方法有个结构性缺陷语义类别和运动状态不是一一对应的。停在路边的静态车辆会被误剔除而一个滚动的皮球没有预定义的语义类别反而会被当作静态点参与估计。所以综述里反复强调成熟的方案几乎都是语义几何的融合——语义先给出“动态候选”几何再验证它到底动没动。我在实际项目中常用的做法是把语义分割得到的“人”区域的深度估计与多视角几何一致性做一个交叉验证只有两者都判为动态时才剔除。这比单纯靠语义mask要稳得多因为分割边界天然有误差边界附近的特征点如果直接剔除会造成地图的“空洞”影响后续定位。3.3 基于运动模型/像素流的动态建模第三种思路比较激进不剔除动态物体而是把它们当作运动对象来显式建模。这类方法通常依赖光流场、运动分割motion segmentation甚至实例级的运动轨迹估计。物体级别的运动建模可以追溯到早期的多体SfMmulti-body SfM工作近些年被重新重视起来尤其在自动驾驶场景中每辆车、每个行人都可以被当成独立的刚体来估计它们的运动参数。这个方向的难点在于数据关联运动分割的结果必须和具体的物理对象对应起来而多个物体交错、遮挡时分割和关联很容易出错。另外物体自身姿态的变化人挥手、转身会让刚体运动假设失效这时候就需要进一步引入非刚性模型复杂度会上升一个量级。我在阅读综述时的理解是这三种路线并不是互斥的进化关系而是互补的——几何是基座任何动态识别最后都要回归到几何一致性验证语义是优先线索它告诉我们“哪个区域最可疑”运动模型则是高阶选项适合那些需要理解场景动态结构的应用而不是仅仅追求稳健定位。4. 动态环境下视觉SLAM的核心步骤拆解4.1 动态特征剔除的工程实现过程如果你用的是ORB-SLAM这类特征点法框架想加入动态特征剔除最直接的做法是在Tracking线程中、特征匹配之后加入一个动态判断步骤。整个流程可以这么拆特征提取之后先做两帧之间的匹配得到一组候选匹配点。用RANSAC估计基础矩阵或单应矩阵把满足几何一致性的点标为“内点”。接下来关键的一步是计算每个匹配点相对于模型的重投影误差或到极线的距离。此时设定一个阈值这个阈值很重要后面细说误差超过阈值的匹配点被标记为动态候选。最后这些动态候选点不参与后续的位姿优化甚至直接从局部地图中移除。这里有一个我在实操中反复踩过的坑阈值的选择不能只看理论上的像素误差。在低纹理场景里特征点本身的定位噪声就很大极线距离的均值和方差都会变大如果阈值取得过紧大量静态点会被误杀。反过来高纹理场景下阈值取大了动态点就混进来了。我后来采用的策略是自适应阈值——根据当前帧的图像梯度统计和匹配内点数量动态调整阈值。实测下来在室内办公场景和室外道路场景都能跑得稳。4.2 静态地图维护与动态区域记忆仅仅在追踪时剔除动态点还不够动态物体经过一个区域后地图中可能存在“遗留”的错误路标点。比如一个行人在镜头前停留了几秒钟然后走开算法在行人停留期间可能会把行人身上的点三角化进地图。行人离开后这些路标点依然留在全局地图里后续帧如果重新看到了这些区域就可能被这些“僵尸点”干扰。处理这个问题我常用的做法是给地图点加一个“稳定性评分”每次成功匹配到该点就加分每次该点所在区域被判为动态就减分分数低于阈值就标记为失效并停止参与优化。这个方案实现成本低但对长时间运行的地图质量提升非常明显。我在一个室内AGV项目里跑过持续2小时以上的实验没有加稳定性评分时地图点总数增长了约40%其中不少是动态遗留点加上评分机制之后地图点总数平稳定位精度也恢复了稳定。4.3 动态物体与相机运动耦合时的注意点当相机本身也在快速运动时动态物体检测会变得更棘手。快速运动带来运动模糊特征点提取数量和质量都会下降同时大幅度的视差变化会让几何约束本身变得不稳定。更麻烦的是当相机和物体都在运动时仅靠短时间内的几何约束很难区分“物体动了”和“相机在动”。这类场景的常规处理是引入惯性测量单元IMU辅助。IMU可以提供短时间内的相对运动约束当视觉和IMU状态估计一致时物体点的残差就会显现出来。我在无人机平台上尝试过视觉惯性融合的动态剔除方案——先用IMU预测帧间位姿再用预测位姿计算特征点的重投影误差误差大的点直接判定为动态。这个方法比纯视觉RANSAC鲁棒得多尤其在无人机悬停时检测地面移动车辆准确率提升非常明显。5. SfM在动态环境中的问题与方法差异5.1 无序图像集中的动态物体识别难在哪SfM面对的输入通常是无序的图像集。相比SLAMSfM少了两条关键线索没有时间顺序也没有短基线约束。这意味着你无法依赖相邻帧之间的运动连续性来识别动态目标而只能从多视角几何的一致性来推断。具体到实现层面SfM的匹配通常是特征点两两匹配再加上多视图聚簇。动态物体在一部分图像中出现在位置A在另一部分图像中出现在位置B那么它的特征点会在跨视角匹配时形成明显的几何冲突。有一种比较经典的离线处理思路是先通过增量式SfM做一遍初始重建然后检查每个三维点的重投影误差误差大的点标记为“动态点”并剔除再用剩余点做第二次全局优化。这个思路在图像数量大、视角冗余多的时候效果很不错因为冗余视角能让真正的静态点形成强约束动态点的异常被放大。但在图像数量少、视角稀疏时这种方法的可靠性会显著下降——可能连哪些点是动态的都分不清。5.2 动态结构重建与运动轨迹提取一些SfM方向的研究并不满足于剔除了动态物体而是希望把这些物体也重建出来。这大类问题被概括为“动态场景的SfM”核心目标是从静态背景中分离出运动物体同时重建物体的三维结构和运动轨迹。这类方法通常分为两步先把多视图下的像素点按运动一致性聚类得到若干个运动分组然后对每组单独做SfM恢复出该物体的三维结构最后跨时间或跨视角关联分组提取运动轨迹。这个方法在工程上的落地难点主要是聚类可靠性。运动一致性聚类要求对每个特征点提取一个运动特征向量通常包括它在不同图像中的位置变化以及光流信息。一旦物体的运动模式跟背景的相机运动模式接近——比如物体在画面中向同一个方向缓慢移动聚类就很容易把物体和背景混在一起。我碰过的一个案例是室内扫摄中一台AGV自动导引车在画面中向左平移而相机也在向左平移二者速度接近时无论是几何方法还是光学方法都很难把AGV分离出来最后还是靠语义先验解决的。5.3 增量式与全局式SfM的选择对动态鲁棒性的影响SfM的主流框架分为增量式和全局式它们在动态场景下的表现差异较大。增量式SfM每次只加入一两个视角逐步生成三维点这个过程天然带有一种“异常值过滤”的能力——每次加入新视角时做一次几何校验异常点会被拒绝。代价是误差会累积而且对初始视角的选择非常敏感。全局式SfM则是先估计所有的相机位姿通常通过旋转平均和平移平均最后一次性三角化所有点。它在静态场景下精度更高、速度更快但在动态场景下的鲁棒性反而差一些——因为全局估计中一个动态点的异常残差可能污染整个旋转平均或平移平均过程而且没有增量过程提供“先来后到”的天然校验。我的建议是如果场景动态比较复杂又没有额外的语义线索优先用增量式SfM做第一遍重建用增量过程本身过滤异常点。等得到足够干净的静态场景和相机位姿之后再考虑用全局式做一次细化。这个“先增量后全局”的组合策略在好几个真实场景里都比单纯用一种方式稳得多。6. 公开数据集与评测基准自己的方案到底行不行6.1 常用动态SLAM数据集盘点评测是动态SLAM研究里最容易拉平差距的环节。正规的评测不能拿没有动态物体的标准SLAM数据集来测必须在动态场景的数据集上跑。目前学术界常用的动态SLAM数据集有这么几个TUM RGB-D动态物体序列是入门首选。它包含几种典型的动态场景人在桌前晃动、两个人在会议室里走动、人在沙发上坐着做动作等。这个数据集的最大优点是提供地面真值轨迹带IMU数据适合评估ATE绝对轨迹误差和RPE相对位姿误差。KITTI则更偏向自动驾驶场景动态物体以车辆为主。它的动态性不是实验室级别的——场景是真实的城市道路有大量不同速度的移动车辆。这个数据集对算法的鲁棒性要求更高因为动态物体出现在图像中的比例变化非常大。EuRoC MAV数据集主要是无人机飞行采集包含室内外场景动态性相对较弱但如果做视觉惯性方案它的IMU数据质量和同步精度是最好的。OpenLORIS则更贴近服务机器人和AR应用包含超市、住宅、办公室等多类场景动态物体包括行人、购物车等尺度和运动模式更复杂。6.2 评测指标怎么定才算公平动态SLAM评测最常用的指标是ATE绝对轨迹误差它衡量的是估计轨迹和地面真值轨迹的整体偏差RPE相对位姿误差则是衡量每帧之间的位姿误差更侧重于局部一致性。但只跑一个ATE就下结论是不够的。动态场景中不同算法的行为模式差异很大——有些算法在动态物体数量少时表现很好但动态物体一多就迅速崩溃有些算法则相反因为过于激进的剔除策略导致静态特征也被大量误删。所以规范的评测应该至少给出三组结果低动态场景、中动态场景、高动态场景。我通常还会加一个指标有效轨迹长度比例——算法输出轨迹的有效帧数占总帧数的比例。有些算法虽然精度指标好看但中途丢了追踪只能靠重定位回到轨迹这种算法在实际应用中根本不可用。6.3 我自己跑评测时的参考配置跑DynTUM数据集做消融实验时我通常固定特征点数量为2000图像分辨率统一调整到640×480语义分割网络采用轻量级版本保证在CPU上也能跑实时。对比不同剔除策略时至少跑5次取中位数因为动态场景本身的随机性很大只跑一次的结果波动可能超过10%。如果要在KITTI上评测我一般用00-10序列中的动态物体密集段落截取500帧左右前后加一段静态场景做对比。注意如果你要用ORB-SLAM3作为baseline做对比一定注意它本身的动态处理能力很弱不要只用它代表“传统方法的极限水平”。动态SLAM领域比较公认的baseline组合是ORB-SLAM3无动态处理、DynaSLAM几何语义分割、DS-SLAM几何光流语义这样基本能覆盖从朴素到复杂的三个档次。7. 读综述时的几个方法论思考这篇综述读完我最大的收获不是某一个具体的算法而是对整个动态SLAM问题谱系的理解。做工程最怕的就是遇到问题就上网搜“sliding window”或“RANSAC”之类的关键词然后照着改改完发现场景一换又崩了。有了综述的框架你可以先判断自己面临的问题本质是什么——是动态物体占比太高还是运动速度太快还是运动模式太复杂——然后选择对应的处理策略组合。从论文发表的角度看综述理顺了当前方法的分类脉络也指明了几个比较有潜力的研究方向一是多模态融合把视觉、IMU、毫米波雷达的数据做深度耦合来识别动态目标二是基于深度学习的端到端动态感知把动态物体识别和相机位姿估计放进一个统一的网络里优化三是场景动态性的在线评估让系统可以根据当前场景的动态程度自适应地切换处理策略。我个人比较看好“动态感知-剔除-重建”三段式架构的演进方向先在线感知场景动态区域然后根据感知结果决定是剔除、隔离还是显式建模动态物体最后在静态和动态两套结构上分别做重建。这套架构在自动驾驶和AR场景里都很有潜力因为它能同时满足鲁棒定位和场景理解的需求。8. 常见问题与避坑指南这个板块是我读这类综述时最希望有人提前告诉我的部分。以下是我在实践动态SLAM和SfM过程中踩过的坑以及从同行交流中收集到的高频问题。8.1 为什么加了语义分割后反而更差了有一个很典型的坑使用语义分割mask做动态物体剔除时分割结果出现边界不准的问题导致大量静态背景特征被连带剔除。尤其在人形区域附近分割网络画出的mask往往比实际人形大一圈或小一圈。大一圈时背景点被误杀小一圈时人体边缘点混进来。后者会造成动态点漏检前者会造成静态信息损失。应对方法是在分割mask上做腐蚀和膨胀操作先腐蚀去掉不确定区域边缘再膨胀适当恢复。这样给mask边界留出一个灰色地带特征点落在这个灰色地带里时就交给几何判断来决定去留。这个trick在很多论文里只采用了一种处理方法实际实验下来“腐蚀膨胀”之后的效果通常优于纯mask裁剪。8.2 动态点比例很高时怎么保住位姿当画面中的动态物体占比超过一半时即使极线约束语义分割都起作用剩余静态点也可能不足以稳定估计位姿。我遇到过极端情况室内场景中一个人站在镜头正前方画面80%都被这个人占据这时候可用的静态特征可能只有30个左右对位姿估计来说非常勉强。这种情况下有两个可用的补救方案。第一是主动放弃基于特征点的位姿估计改用直接法或者半直接法——直接法用的是像素灰度信息而不是特征点在低特征条件下更有优势。第二是利用多帧累积信息——对动态区域先不直接剔除而是保留其特征点但降低权重当后续帧中出现更多静态区域时再重新恢复这些点的参与。第二种方法在工程实现上更友好因为它不用换整个SLAM框架。8.3 SfM结果出现“重影”或“漂浮物”结构SfM重建结果里出现重影结构几乎都是因为动态物体在不同图像中产生了多个不一致的三维点。这些点会被重建算法作为独立的、孪生的三维点簇表现为“飘浮”在空中的一组点。排查思路通常是先检查这些飘浮点的观测视图分布——如果它们只出现在少数几幅图中基本可以判定是动态物体遗留。然后把这几幅图从重建集中暂时排除重新跑一遍全局优化看飘浮点是否消失。如果消失说明确实是被动态区域干扰如果没消失那就要检查是不是标定参数有问题或图像发生了畸变。8.4 低纹理动态场景怎么处理低纹理动态是SLAM的“地狱难度”组合。低纹理意味着特征点稀疏几何约束本身就不稳动态则意味着少数几个特征点里还有一部分是“坏点”。这种场景下几何方法和特征点法的生存空间都很小。我试过相对有效的方法是引入边缘特征和平面约束。边缘特征在图像上表现为梯度突变的多边形轮廓在低纹理场景里往往比角点更稳定而且动态物体的边缘和背景场景的边缘往往存在垂直/水平方向的几何关系差异可以辅助进行动态判断。平面约束比如地面、桌面、墙面则可以为位姿估计提供一个稳定的参考平面。这两者结合的方案在一个仓库环境的AGV项目里跑通了动态叉车和人员干扰下依然能保持10cm以内的定位误差。9. 一些个人体会和工程建议如果你问我做动态SLAM最需要的能力是什么我觉得是“场景理解”的能力而不只是“几何计算”的能力。几何约束可以帮你发现运动但不太能帮你理解运动。真正稳的方案通常是在多个层面同时工作底层用几何约束保证基本的动态检测鲁棒性中层用语义信息提供对可运动物体的预判高层再用运动模型来理解动态目标的行为。对于刚入门的同学我的建议是从复现经典baseline开始比如先跑通ORB-SLAM3再在上面加一个极线约束检测看精度能提升多少然后加语义分割精度又能提升多少。用消融的方式一步步拆解比一上来就试图做一个完整的多模态系统要有效得多——你至少能知道每个模块到底贡献了多少。这篇综述对我的直接帮助是把原本散落在各篇论文里的碎片知识串成了一条线。如果你也卡在“算法场景泛化性差”“不知道自己的方案该往哪个方向打磨”这类问题建议花一个完整的下午把它当作章节式教材来读先看问题分类再看方法谱系最后看数据集选择。然后再回头看自己的代码你会比之前更清楚下一步该改的是哪里。最后分享一个我在做工程时常用的习惯动态SLAM的代码里把动态检测的判定结果可视化输出成一张热力图叠加到原始图像上实时查看哪些区域被判为动态。这个习惯帮我快速定位算法在各种边缘场景下的表现问题比看输出轨迹的精度曲线直观得多。如果你被某个动态场景折磨得没思路不妨先打开可视化看一眼——问题往往一眼就能看出来。