【视觉SLAM笔记】第7章 视觉里程计1

一、理论

7.1 视觉SLAM中的特征点法(Feature-based Method)

这是一种经典且应用极其广泛的视觉SLAM方法,可以把它理解为计算机模仿人类认知环境的方式。


一、核心思想与比喻

想象一下你进入一个陌生的房间,想要记住这个房间的样子并知道自己在哪里。你很可能会:

  1. 寻找显著地标

    :你会注意到墙上的画、桌上的花瓶、窗户的角落等特别的点。这些就是“特征点”。

  2. 记住地标的样子

    :你会记住这幅画长什么样,花瓶是什么颜色和形状。这就是“特征描述”。

  3. 移动并再次观察

    :你走到房间另一侧,再次寻找刚才看到的地标。当你看到同样的那幅画时,你就能根据它在你视野中的变化,大致判断出自己移动了多远、转了多少角度。这就是“跟踪与运动估计”。

  4. 构建心理地图

    :通过不断观察这些地标,你会在脑海中形成一个它们之间相对位置的地图。这就是“建图”。

  5. 纠正误差

    :当你走了一圈又回到起点时,你发现眼前的景象和记忆中的起点一模一样。这时,你可能会修正一下自己刚才对路径的估计,让起点和终点完美重合。这就是“回环检测与优化”。

特征点法SLAM做的就是同样的事情:从图像中提取稳定、可区分的“角点”(特征点),然后通过匹配和跟踪这些点在不同图像中的位置,来计算相机的运动并构建由这些点组成的三维地图。


二、详细工作流程

特征点法通常分为两个主要部分:前端(Frontend) 和 后端(Backend)

(这是一个流程示意图,下面将详细解释每个模块)

1. 前端 (Visual Odometry, VO)

前端负责处理实时的图像数据,快速估算出相机的局部运动局部地图。它更关注“邻近帧”之间的关系。

步骤分解:

  1. 特征提取 (Feature Extraction)

  • SIFT (Scale-Invariant Feature Transform)

    :效果好,对尺度、旋转、光照不变性强,但计算量巨大。

  • SURF (Speeded Up Robust Features)

    :SIFT的加速版,速度更快。

  • ORB (Oriented FAST and Rotated BRIEF)

    :目前的主流选择。它结合了FAST角点检测(速度极快)和BRIEF特征描述(计算高效),并加入了旋转不变性。是速度和性能的优秀折衷。

  • 目标

    :在图像中寻找稳定、可重复检测的关键点,通常是角点或斑点(Blob)。这些点在不同视角、光照下都能被找到。

  • 常用算法

  • 特征描述 (Feature Description)

    • SIFT/SURF 描述子

      :通常是128维或64维的浮点数向量。

    • BRIEF (Binary Robust Independent Elementary Features)

      :二进制描述子,由一系列0和1组成。计算和匹配速度极快(使用汉明距离),非常适合实时应用。ORB算法使用的就是改良版的BRIEF。

    • 目标

      :为每个提取出的特征点生成一个唯一的“身份ID”(一个向量),称为描述子 (Descriptor)。这样我们才能在另一张图中认出它。

    • 常用算法

  • 特征匹配/跟踪 (Feature Matching/Tracking)

    • 暴力匹配 (Brute-Force Matching)

      :计算帧A中每个特征的描述子,与帧B中所有特征描述子之间的距离,取距离最近的作为匹配对。

    • 快速近似最近邻 (FLANN)

      :一种更高效的匹配方法,尤其适用于高维描述子(如SIFT)。

    • 光流法 (Optical Flow)

      :如KLT (Kanade-Lucas-Tomasi) 算法,它不依赖描述子,而是假设相邻帧之间像素灰度不变,通过寻找像素的运动来跟踪特征点。适用于帧率较高的视频。

    • 目标

      :在连续的两帧图像(或当前帧与地图点)之间,找到成对的、代表空间中同一点的特征。

    • 方法

  • 运动估计 (Motion Estimation / Pose Estimation)

    • 2D-2D (对极几何)

      :在系统初始化时,我们只有两张图像中的2D像素坐标。通过匹配点对,可以求解本质矩阵 (Essential Matrix) 或 基础矩阵 (Fundamental Matrix),然后分解它们得到 R 和 t。但这存在尺度不确定性。

    • 3D-2D (PnP)

      :当系统运行起来后,我们已经有了一部分地图点(3D坐标)和当前帧的图像(2D坐标)。此时可以通过匹配的3D-2D点对,使用PnP (Perspective-n-Point) 算法直接求解相机的位姿。

    • 3D-3D (ICP)

      :如果两帧都已有深度信息(例如RGB-D相机),可以通过匹配的3D点云,使用ICP (Iterative Closest Point) 算法求解位姿。

    • 目标

      :根据匹配好的特征点对,计算出相机从上一帧到当前帧的旋转 (Rotation) 和 平移 (Translation),即位姿变换。

    • 常见情况

  • 三角化 (Triangulation)

    • 目标

      :当通过运动估计得到两个关键帧的位姿后,可以利用这两帧中匹配的特征点,来计算出这些特征点在空间中的三维坐标,从而创建新的地图点。这就像从两个不同位置观察同一个物体来确定其距离。

    2. 后端 (Backend Optimization)

    后端不处理每一帧图像,而是接收前端输出的关键帧 (Keyframes) 和地图点。它更关注“全局”的一致性和精度,负责优化整个轨迹和地图。

    步骤分解:

    1. 后端优化 (Optimization)

    • BA将相机位姿和所有三维地图点都视为待优化的变量。

    • 它构建一个巨大的优化问题,目标是最小化所有地图点在各个关键帧上的重投影误差 (Reprojection Error)——即地图点的三维坐标根据相机位姿投影回图像的像素位置,与当初观测到的特征点位置之间的差值。

    • BA是SLAM中精度最高的优化方法,但计算量极大。通常只在关键帧上进行,或采用稀疏化的方法(如只优化位姿,即Pose Graph)。

    • 问题

      :前端的计算会不可避免地引入累积误差。走得越远,估计的位姿与真实位姿的偏差越大。

    • 目标

      :最小化全局误差,得到一个全局一致的相机轨迹和地图。

    • 核心技术:捆集调整 (Bundle Adjustment, BA)
  • 回环检测 (Loop Closure Detection)

    • 词袋模型 (Bag-of-Words, BoW)

      :一种非常主流的方法。它将特征描述子类比为“单词”,将一帧图像看作由这些单词组成的“文档”。通过比较当前帧和历史关键帧的“文档相似度”,可以高效地判断是否到达旧地。

    • 当检测到回环时,就在轨迹图(Pose Graph)中添加一条“回环约束边”。

    • 目标

      :识别出相机是否回到了一个曾经访问过的地方。这是消除累积误差的关键。

    • 方法

  • 全局优化与建图 (Full BA / Pose Graph Optimization)

    • 位姿图优化 (Pose Graph Optimization)

      :将每个关键帧视为一个节点,帧间运动估计和回环约束作为边,构建一个图。然后调整所有节点(位姿),使得边的约束误差最小。这比Full BA快得多。

    • 优化完成后,整个轨迹和地图的累积误差会被消除,得到一个全局一致的结果。

    • 触发

      :当检测到回环时。

    • 过程

      :后端会进行一次大规模的全局优化。


    三、优缺点总结

    优点
    1. 高精度和鲁棒性

      :经过后端优化(尤其是回环优化)后,精度非常高。

    2. 对光照变化不敏感

      :特征点(如SIFT, ORB)本身具有一定的光照不变性,比直接法更鲁棒。

    3. 技术成熟,理论完善

      :是研究最早、最深入的SLAM方法,有大量开源方案和文献。

    4. 不需要很强的纹理

      :只要有足够的角点,即使在纹理较弱的区域(如白墙上的零星物体)也能工作,而直接法可能会失败。

    缺点
    1. 计算量大

      :特征提取和匹配是主要的耗时步骤,对计算资源要求较高。

    2. 稀疏地图

      :构建的地图是由离散的三维点组成的稀疏点云,丢失了图像中大量的非特征点信息。无法直接用于导航或渲染。

    3. 特征缺失场景失效

      :在纹理极度稀疏(如纯白墙壁、走廊)或动态模糊严重的场景,如果提取不到足够且稳定的特征点,系统会直接崩溃。

    4. 信息丢弃

      :只利用了图像中几百个特征点,丢弃了99%以上的像素信息。


    四、经典算法代表

    • PTAM (Parallel Tracking and Mapping)

      :开创性地提出了跟踪和建图并行化的思想,即前端和后端的分离,是现代特征点法SLAM框架的鼻祖。

    • ORB-SLAM 系列 (1, 2, 3)

      :目前特征点法的集大成者和事实上的标准。它使用ORB特征,是一个完整且强大的SLAM系统,包含了跟踪、建图、回环检测和重定位,支持单目、双目和RGB-D相机。

    总之,特征点法是视觉SLAM领域的基石,它以其高精度和鲁棒性,在许多应用中仍然是首选方案。理解其工作流程对于深入学习SLAM至关重要。

    7.2 特征点:关键点(Keypoint)和描述子(Descriptor)

    在现代计算机视觉和SLAM中,“特征点”这个词通常是一个复合概念,它精确地由关键点(Keypoint)描述子(Descriptor) 两部分组成。

    我们可以用一个简单的比喻来理解:制作一张个人档案卡

    • 特征点 (Feature Point) = 完整的个人档案卡
    • 关键点 (Keypoint) = 档案卡上的“地址”信息
    • 描述子 (Descriptor) = 档案卡上的“外貌描述”信息

    让我们来详细拆解这两部分。


    一、关键点 (Keypoint):The "Where"

    关键点回答了**“特征在哪里?”**这个问题。

    • 核心定义

      :它指的是特征在图像中的位置。最基本的信息就是像素坐标 (x, y)

    • 作用

      :它的主要任务是在整张图像中(包含数百万个像素)找到那些**“与众不同”且“稳定”**的点。如果让我们去描述一个房间,我们不会去描述白墙的正中间,因为那里毫无特色。我们会选择墙角、画框的角点等。关键点检测算法做的就是这件事。

    • 包含的额外信息

      :为了让特征更具鲁棒性,一个关键点除了位置坐标外,通常还包含:

      • 尺度 (Scale)

        :这个特征是在哪个图像缩放级别上找到的?这使得我们能够匹配一个近处物体和它在远处的同一个点(即尺度不变性)。

      • 方向 (Orientation)

        :这个特征的主方向是什么?通过计算这个方向,即使图像旋转了,我们也能将特征“摆正”再进行描述,从而实现旋转不变性

    总而言之,关键点是一个数据结构,它告诉你一个有价值的特征点在图像中的位置、大小和方向。


    二、描述子 (Descriptor):The "What"

    描述子回答了**“这个特征长什么样?”**这个问题。

    • 核心定义

      :它是一个向量(一串数字),用来量化和描述关键点周围邻域的图像信息。它就像这个关键点的“数学指纹”。

    • 作用

      :它的唯一任务就是提供可区分性。当我们在两张不同的图像中都找到了关键点后,我们需要一种方法来判断图像A中的Keypoint_1是否和图像B中的Keypoint_8是同一个现实世界中的点。我们通过比较它们的描述子来实现。如果两个描述子的“距离”(如欧氏距离或汉明距离)足够近,我们就认为它们是匹配的。

    • 生成方式

      :算法会分析关键点周围的一个小图像块(patch),提取其中的梯度、亮度、颜色等信息,然后按照特定的规则生成一个固定长度的向量。

      • 例如,SIFT描述子是一个128维的浮点数向量。

      • 例如,ORB描述子是一个256位的二进制向量(由256个0或1组成)。

    总而言之,描述子是关键点的身份标识,使得特征可以在不同的图像中被识别和匹配。


    三、为什么两者缺一不可?

    它们共同协作,解决了SLAM前端中的核心问题:

    1. 没有关键点,只有描述子

      :这在计算上是不可行的。你不可能为图像中的每一个像素都计算一个描述子,那计算量将是天文数字。关键点的作用就是高效地筛选出值得描述的区域,把计算量从百万级降低到几百级。

    2. 没有描述子,只有关键点

      :你在图像A中找到了一堆角点(位置),在图像B中也找到了一堆角点(位置)。但是,你怎么知道A中的哪个角点对应B中的哪个角点呢?你无法建立它们之间的联系,也就无法计算相机的运动。描述子提供了匹配的依据。

    举例:ORB特征点

    ORB (Oriented FAST and Rotated BRIEF) 是这个概念的完美体现,它的名字就揭示了其构成:

    1. 关键点部分 (Oriented FAST)

    • 使用 FAST (Features from Accelerated Segment Test) 算法在图像中快速地检测出角点位置 (x, y)

    • 然后计算这些角点的方向 (Orientation),赋予其旋转不变性。

    • 至此,关键点(Keypoint)就生成了。
  • 描述子部分 (Rotated BRIEF)

    • 对于每一个由FAST生成的关键点,使用改进版的 BRIEF (Binary Robust Independent Elementary Features) 算法来生成一个256位的二进制描述子

    • 在生成时,会利用上一步算出的方向信息,将BRIEF“旋转”到主方向上,使其具备旋转不变性。

    • 至此,描述子(Descriptor)也生成了。

    最终,一个ORB特征点 = (一个FAST关键点) + (一个与其对应的BRIEF描述子)

    总结

    组成部分

    角色

    包含信息

    解决的问题

    关键点 (Keypoint)

    定位器 (Locator)

    像素坐标(x, y)、尺度、方向

    在哪里

    寻找特征?(检测问题)

    描述子 (Descriptor)

    识别器 (Identifier)

    描述周围图像外观的向量

    这个特征长什么样?(匹配问题)

    特征点 (Feature Point)

    完整的观测单元

    关键点 + 描述子

    在不同视角下稳定地跟踪同一个物理点

    7.3 ORB 特征提取

    ORB是目前视觉SLAM领域中速度与性能之间的一个标杆,是实时应用的首选。理解它的工作原理至关重要。

    一、核心思想与目标

    ORB的设计目标非常明确:成为SIFT和SURF的一个快速且免费的替代品

    • SIFT/SURF

      :效果好,鲁棒性强,但计算量大,且在当时(ORB提出时)有专利限制。

    • ORB

      :要实现高速计算,同时保持良好的性能(特别是旋转不变性和一定的尺度不变性)。

    它的名字已经完美地概括了其技术核心:

    • Oriented FAST

      :用于关键点提取。它在FAST角点检测算法的基础上,增加了方向和尺度信息。

    • Rotated BRIEF

      :用于特征描述。它改进了BRIEF描述子,使其具备了旋转不变性。

    下面,我们按照算法的执行流程,一步步拆解。


    二、详细工作流程

    ORB特征提取主要分为两大步:关键点提取特征描述

    第1步:关键点提取 (Oriented FAST)

    这一步的目标是,在图像中快速找到稳定且带有方向信息的关键点。

    1.1 尺度不变性:构建图像金字塔 (Image Pyramid)

    • 问题

      :原始的FAST角点不具备尺度不变性。同一个物体,近看时特征大,远看时特征小,FAST可能在不同距离下检测不到同一个角点。

    • 解决方案

      :对原始图像进行降采样,生成一系列不同分辨率的图像,构成一个金字塔

      • 金字塔的底层是原始图像。

      • 每一层图像都是由上一层图像按一个固定的比例(如1.2)缩小得到的。

      • ORB会在金字塔的每一层图像上都进行角点检测。

    • 效果

      :这样,一个较大的特征可以在金字塔的高层(低分辨率图像)被检测到,而一个较小的特征可以在金字塔的底层(高分辨率图像)被检测到,从而实现了有限的尺度不变性

    1.2 角点检测:FAST (Features from Accelerated Segment Test)

    在金字塔的每一层图像上,执行FAST角点检测。

    • 原理

    1. 在图像中选择一个像素点 p

    2. 以 p 为中心,考虑其周围半径为3的圆上的16个像素点。

    3. 如果这个圆上有连续的N个点(通常N=9或12)的亮度值都同时比中心点 p 的亮度值(超过一个阈值t),或者都同时p(低于一个阈值t),那么就认为p是一个角点。

  • 优点

    :计算极其简单快速,因为它只涉及像素亮度的比较。

  • 1.3 关键点筛选:用Harris响应值排序

    • 问题

      :FAST检测出的角点数量可能非常多,而且很多角点的“质量”并不高(例如,很多点会聚集在一条边上)。

    • 解决方案

    1. 对所有检测到的FAST角点,计算其Harris角点响应值。Harris响应值可以衡量一个角点的“角点程度”,响应值越高的点,角点特性越明显。

    2. 根据Harris响应值从高到低进行排序。

    3. 选取响应值最高的 前N个 角点作为最终的关键点。

  • 效果

    :这样既限制了特征点的总数,又保证了留下来的都是质量较高的关键点。

  • 1.4 方向计算:强度质心法 (Intensity Centroid)

    • 问题

      :到目前为止,我们得到的关键点只有位置和尺度信息,但没有方向。没有方向,特征就不具备旋转不变性。

    • 解决方案

      :使用强度质心法来确定每个关键点的方向。

    1. 在关键点周围定义一个图像块 (patch)

    2. 计算这个图像块的矩 (moment)。一阶矩 M_10 和 M_01 分别表示x和y方向上的像素强度总和。

    3. 计算图像块的质心 (Centroid) C,其坐标为 (M_10/M_00, M_01/M_00)。(M_00是零阶矩,即块内所有像素的强度和)。

    4. 定义一个从几何中心 O 指向质心 C 的向量 OC

    5. 这个向量 OC 的方向,就被定义为该关键点的主方向

  • 效果

    :无论图像如何旋转,这个根据像素强度分布计算出的质心方向是相对稳定的,从而赋予了关键点旋转不变的基础。

  • 至此,我们得到了一个完整的“关键点”(Keypoint),它包含了位置、尺度和方向信息。


    第2步:特征描述 (Rotated BRIEF)

    这一步的目标是,为上一步得到的每一个关键点,生成一个唯一的、可用于匹配的“指纹”——描述子。

    2.1 BRIEF描述子基础

    • 原理

      :BRIEF (Binary Robust Independent Elementary Features) 是一种二进制描述子

    1. 在关键点周围的一个固定大小的图像块(Patch)内。

    2. 按照一种预定义的模式 (pattern),选取 n 对像素点 (p, q)(例如 n=256)。

    3. 进行 n 次比较:如果 p 的亮度大于 q 的亮度,则结果为1;否则为0。

    4. 将这 n 次比较的结果(0或1)串联起来,形成一个 n 位的二进制字符串。这个字符串就是BRIEF描述子。

  • 优点

    • 计算快

      :只做亮度比较。

    • 存储小

      :256位只需要32个字节。

    • 匹配快

      :比较两个二进制描述子,只需计算它们的汉明距离(Hamming Distance,即两个字符串中不同位的个数),这可以通过CPU的XOR(异或)指令和POPCNT(计算1的个数)指令超高速完成。

  • 致命弱点

    不具备旋转不变性。如果图像旋转,选取的像素点对 (p, q) 就会跑到完全不同的位置,生成的描述子会天差地别。

  • 2.2 旋转不变性:Steered BRIEF

    • 解决方案

      :这正是ORB的精髓所在。

    1. 利用在第1.4步中计算出的关键点主方向 θ

    2. 对于一个给定的关键点,获取其周围的图像块。

    3. 在生成BRIEF描述子之前,将预定义的那个像素点对的采样模式 (pattern),按照主方向 θ 旋转

    4. 用旋转后的新采样模式去选取像素点对并进行比较,生成最终的描述子。

  • 效果

    :无论原始图像如何旋转,由于采样模式总是会先“校正”到主方向上,因此它采样的总是相对固定的区域,从而保证了生成的描述子在旋转下保持一致。这就是 "Rotated BRIEF" 的由来,有时也叫 "Steered BRIEF"。

  • 至此,我们得到了一个完整的“ORB特征点”,它由一个带方向的关键点和一个旋转不变的二进制描述子组成。


    三、总结

    步骤

    子步骤

    核心技术/方法

    目的

    1. 关键点提取 (Oriented FAST)

    1.1 构建金字塔

    图像降采样

    实现尺度不变性

    1.2 角点检测

    FAST算法

    快速找出候选角点位置

    1.3 关键点筛选

    Harris响应值

    筛选出高质量、分布好的角点

    1.4 计算方向

    强度质心法

    赋予关键点旋转不变的基础

    2. 特征描述 (Rotated BRIEF)

    2.1 描述子生成

    BRIEF二进制比较

    生成高效的、可匹配的“指纹”

    2.2 实现旋转不变性

    Steered BRIEF (模式旋转)

    使BRIEF描述子具备旋转不变性

    ORB通过这一系列巧妙的组合与优化,成功地在保持高速运算的同时,实现了对旋转和一定尺度变化的鲁棒性,成为了视觉SLAM领域中的一个经典且实用的特征提取算法。

    7.4 ORB特征匹配

    ORB特征匹配的核心优势在于其极高的速度,这主要得益于ORB特征本身的设计。

    一、核心问题与目标

    假设我们已经对两张图像(比如 Image_A 和 Image_B)都提取了ORB特征点。现在我们手上有两组特征点集:

    • Features_A

       = {Feature_A1Feature_A2, ..., Feature_Am}

    • Features_B

       = {Feature_B1Feature_B2, ..., Feature_Bn}

    其中,每个特征点都包含一个关键点(位置信息)和一个256位的二进制描述子

    匹配的目标是:找到所有成对的 (Feature_Ai, Feature_Bj),使得 Feature_Ai 和 Feature_Bj 对应于三维空间中的同一个物理点

    二、匹配方法:暴力匹配 (Brute-Force Matcher)

    由于ORB描述子的高效性,最常用且最直接的匹配方法就是暴力匹配。它的思想非常简单粗暴但有效。

    基本流程:

    1. 取出一个特征

      :从 Features_A 中取出第一个特征点 Feature_A1 的描述子 Descriptor_A1

    2. 遍历计算距离

      :将 Descriptor_A1 与 Features_B 中所有特征点的描述子 (Descriptor_B1Descriptor_B2, ..., Descriptor_Bn) 逐一进行比较,计算它们之间的距离

    3. 找到最近的邻居

      :在 Features_B 中找到与 Descriptor_A1 距离最小的那个描述子,假设是 Descriptor_Bj。这个 Feature_Bj 就成了 Feature_A1 的最佳匹配候选

    4. 重复过程

      :对 Features_A 中的每一个特征点,都重复步骤1-3,为它们各自找到在 Features_B 中的最佳匹配候选。

    三、距离度量:汉明距离 (Hamming Distance)

    关键点:如何衡量两个ORB描述子之间的“距离”?

    由于ORB描述子是二进制字符串(例如 101100...),我们使用汉明距离来度量它们的相似性。

    • 定义:汉明距离是指两个等长字符串之间,对应位置上不同字符的个数

    • 例子

      • Desc_1

         = 10110

      • Desc_2

         = 00101

      • 比较:第1位不同,第4位不同,第5位不同。

      • 汉明距离 = 3

    • 物理意义:汉明距离越小,说明两个描述子越相似,它们代表同一个物理点的可能性就越大。

    • 计算优势:在计算机中,计算汉明距离极其快速。可以通过两个字节的**按位异或(XOR)**操作,然后使用 POPCNT 指令(Population Count,计算一个二进制数中‘1’的个数)来瞬间完成。

      // 伪代码
      distance = popcnt(descriptor1 XOR descriptor2);

      这比计算浮点数向量(如SIFT描述子)的欧氏距离要快上几个数量级。

    四、提高匹配质量:筛选误匹配

    暴力匹配会产生大量的匹配对,但其中包含了许多误匹配(Outliers)。为了提高后续运动估计的准确性,必须对这些初步的匹配结果进行严格的筛选。

    常用的筛选策略有以下几种:

    1. 阈值筛选

    最简单的筛选方法。我们设定一个汉明距离的阈值(例如,30或60,取决于描述子的位数)。只有当最佳匹配对的汉明距离小于这个阈值时,我们才认为它是一个有效的匹配。

    • 优点

      :简单快速。

    • 缺点

      :阈值难以设定。太严格会滤掉正确的匹配,太宽松则会引入误匹配。

    2. 交叉验证 (Cross Check)

    这是一种更可靠的方法。

    • 流程

    1. 正向匹配

      :和之前一样,为 Features_A 中的每个特征 A_i,在 Features_B 中找到最佳匹配 B_j

    2. 反向匹配

      :反过来,为 Features_B 中的那个 B_j,在 Features_A 中找到它的最佳匹配 A_k

    3. 验证

      :只有当 A_k 和最初的 A_i 是同一个特征点时,我们才接受 (A_i, B_j) 这个匹配对。

  • 逻辑

    :如果 A_i 最喜欢 B_j,同时 B_j 也最喜欢 A_i,那么它们很可能是一对“真爱”。这可以有效滤除那些“单相思”的模糊匹配。

  • 3. Lowe's Ratio Test (比率测试)

    这是由SIFT论文提出的一种非常经典且有效的筛选方法,同样适用于ORB。

    • 流程

    1. 对于 Features_A 中的一个特征 A_i,在 Features_B 中不仅要找到距离最近的邻居 B_j (best_match),还要找到距离次近的邻居 B_k (second_best_match)

    2. 计算这两个距离的比率:ratio = distance(A_i, B_j) / distance(A_i, B_k)

    3. 如果这个比率小于一个阈值(通常设为0.7或0.8),则接受这个匹配 (A_i, B_j)

  • 逻辑

    :如果最佳匹配明显好于次佳匹配(即 ratio 很小),说明这个匹配是具有高度区分性的,不太可能是因为特征模糊而随机匹配上的。反之,如果最佳和次佳距离差不多(ratio 接近1),说明这个特征在目标图像中有很多相似的“长相”,很容易搞混,应该舍弃。

  • 4. RANSAC (Random Sample Consensus)

    这是一种更高级的、基于模型的筛选方法,通常在运动估计的环节中结合使用。

    • 流程

    1. 随机采样

      :从所有的初步匹配对中,随机抽取一小组(例如,求解基础矩阵需要8对,PnP需要4对)。

    2. 计算模型

      :使用这一小组匹配,计算一个相机运动模型(如基础矩阵F或位姿T)。

    3. 内点统计

      :用这个模型去检验所有其他的匹配对。如果一个匹配对符合这个模型(例如,它的重投影误差很小),就称之为内点 (Inlier)

    4. 迭代与评估

      :重复以上步骤多次,找到那个能够产生最多内点的模型。

    5. 最终筛选

      :被这个最佳模型支持的所有匹配对(即所有内点)被认为是最终的正确匹配,其余的则被视为外点 (Outlier) 并剔除。

  • 优势

    :非常鲁棒,能够从含有大量(甚至超过50%)误匹配的数据中提炼出正确的匹配和运动模型。

  • 五、总结

    ORB特征匹配的完整流程通常如下:

    1. 初步匹配

    • 采用暴力匹配(Brute-Force)

    • 使用汉明距离作为度量标准。

    • 对 Image_A 中的每个特征,在 Image_B 中寻找最佳匹配。

  • 匹配筛选

    • 第一轮(简单筛选)

      :应用交叉验证Ratio Test来快速剔除大量明显的误匹配。

    • 第二轮(模型筛选)

      :将筛选后的匹配对送入RANSAC流程,在计算相机运动的同时,最终确定哪些是真正几何一致的正确匹配(内点)。

    这个流程兼顾了速度(得益于二进制描述子和汉明距离)和鲁棒性(得益于Ratio Test和RANSAC等强大的筛选策略),使其成为实时视觉SLAM系统中不可或缺的一环。

    7.5  2D-2D:对极几何

    八点法求解详细步骤 以求解基础矩阵 F 为例

    以求解基础矩阵 E 为例

    由本质矩阵E恢复出相机的旋转R和平移t

    7.6 单应矩阵

    7.7 三角测量

    我们来深入讲解视觉SLAM中一个至关重要的步骤——三角测量(Triangulation),也常被称为三角化

    一、核心思想:为什么需要三角测量?

    想象一下你用一只眼睛(单目相机)看世界。当你看到一个物体时,你能知道它在你视野中的哪个方向,但你无法仅凭这一眼就确定它离你多远。这个物体可能是一个近处的小东西,也可能是一个远处的大东西,它们在你的视网膜上可能成像为同样的大小。

    这就是单目视觉的深度不确定性。一个图像上的像素点,对应着空间中从相机光心出发的一条射线(Ray),这个物理点可能在这条射线上的任何位置。

    三角测量的目的,就是为了解决这个问题,确定这个点的三维深度。

    如何做到呢?很简单,再从另一个位置看它一眼!

    当你从第二个位置观察同一个点时,你会得到第二条射线。在理想情况下,这两条射线会在空间中交于一点——这个点就是那个物体的真实三维位置。这个利用不同视角的观测来确定三维点位置的过程,就是三角测量。

    核心比喻:用两只眼睛定位
    我们的双眼就是天生的三角测量系统。左右眼从略微不同的位置观察同一个物体,大脑通过融合这两幅有视差的图像,就能估算出物体的远近。相机移动后进行三角测量,本质上就是模仿这个过程。


    二、三角测量的数学原理

    要进行三角测量,我们必须知道以下三个要素

    1. 观测1

      :点P在图像1中的像素坐标 p1

    2. 观测2

      :同一个点P在图像2中的像素坐标 p2

    3. 位姿变换

      :从相机1到相机2的相对运动,即旋转 R 和平移 t

    如上图所示:

    • O1

      和 O2 分别是两次拍照时的相机光心。

    • P

       是空间中的一个三维点。

    • p1

       和 p2 是点 P 在两个相机成像平面上的投影。

    • 我们已知 p1p2 以及从 O1 到 O2 的变换 (R, t)

    我们的目标是求解 P 的三维坐标。

    设 P 在相机坐标系1下的坐标为 (X, Y, Z)。我们通常将其表示为齐次坐标 P1 = [X, Y, Z, 1]^T
    设 p1 和 p2 已经转换到归一化平面上(即相机焦距为1的平面),坐标分别为 x1 和 x2

    根据针孔相机模型,我们有:
    s1 * x1 = P (在相机1坐标系下)
    s2 * x2 = R * P + t (在相机2坐标系下)

    其中 s1 和 s2 分别是点P在两个相机坐标系下的深度,也就是我们要求的关键未知量。

    将第一个式子代入第二个,得到:
    s2 * x2 = s1 * R * x1 + t

    这是一个关于 s1 和 s2 的方程。我们可以通过求解这个方程(通常通过最小二乘法)来得到深度值,进而计算出 P 的三维坐标。


    三、在SLAM系统中的角色与流程

    三角测量是特征点法SLAM中从2D图像特征生成3D地图点(路标)的唯一途径。它在SLAM流程中扮演着承上启下的关键角色,尤其是在系统初始化地图点创建阶段。

    流程如下:

    1. 系统初始化

    • 相机启动,拍摄第一帧图像(Frame 1)。

    • 相机移动一段距离,拍摄第二帧图像(Frame 2)。

    • 步骤A (特征匹配)

      :在Frame 1和Frame 2之间提取并匹配特征点。我们得到了一系列匹配对 {p1, p2}

    • 步骤B (运动估计)

      :利用这些匹配对,通过求解本质矩阵(E)基础矩阵(F),来计算出从Frame 1到Frame 2的相对位姿 (R, t)

    • 步骤C (三角测量)

      :现在,我们同时拥有了匹配点对 {p1, p2} 和相对位姿 (R, t)。万事俱备,可以对所有匹配成功的特征点进行三角测量,计算出它们的初始三维坐标。

    • 结果

      :我们得到了第一批三维路标点(Landmarks)和一个由两个关键帧位姿组成的初始地图。SLAM系统成功启动!

  • 创建新地图点

    • 系统稳定运行后,相机会不断产生新的关键帧。

    • 当一个新的关键帧被创建时,系统会将其与过去的某个关键帧(例如,共视程度最高的)进行特征匹配。

    • 对于那些匹配成功,但尚未对应任何地图点的特征,系统就会利用这两个关键帧的(已知的)位姿和特征点的2D坐标,再次进行三角测量,从而在地图中创建新的三维路标点,实现地图的增量式构建。


    四、实践中的挑战与考量

    理论上,两条射线相交于一点。但在现实中,由于噪声的存在(特征点定位误差、相机位姿估计误差),这两条射线几乎不可能完美相交,而是会在空间中异面

    • 解决方案

      :实际的算法通常是求解一个最小二乘问题,即寻找一个三维点 P,使得它到两条射线的距离之和最小。或者,找到两条异面射线的公垂线段,并取其中点作为 P 的估计值。

    另一个至关重要的问题是平移基线(Baseline)的长度。

    • 基线太短 (相机移动距离太小)

      • 现象

        :两条射线几乎是平行的。

      • 问题

        :微小的角度误差会导致深度估计产生巨大的偏差。想象一下两条几乎平行的线,它们的“交点”可以在非常远的地方,位置极不稳定。

      • 后果

        :三角化得到的深度信息非常不可靠。

    • 基线太长 (相机移动距离太大)

      • 现象

        :两帧图像的视角差异巨大。

      • 问题

        :同一个物体在两张图中的外观、光照可能变化很大,导致特征匹配变得非常困难,甚至失败。

      • 后果

        :无法找到足够的匹配点来进行三角化。

    最佳实践
    因此,SLAM系统通常采用关键帧机制。它不会在连续的每一帧之间都进行三角化,而是会选择那些与上一关键帧相比,既有足够视差(平移基线),又能保证稳定特征匹配的帧作为新的关键帧,来进行三角化和地图点创建。这是一种在深度精度匹配成功率之间的权衡。

    最后,还有一个重要的约束:

    • 手性约束 (Cheirality Constraint) 或 深度正性约束:一个被正确三角化的点,其深度在两个相机坐标系下都必须是正值。也就是说,这个点必须位于两个相机的前方。这是一个非常有效的几何约束,可以用来剔除大量错误的匹配和不合理的解。

    总结

    项目

    描述

    目标

    从多个2D图像观测中恢复一个点的3D空间位置,解决深度不确定性问题。

    输入

    1. 至少两个视角下的2D特征点坐标。
    2. 这两个视角之间的相对相机位姿(旋转R和平移t)。

    输出

    该特征点对应的三维空间坐标(即一个路标/地图点)。

    在SLAM中的作用地图初始化

    新地图点创建的核心步骤,是连接2D图像和3D地图的桥梁。

    核心挑战

    噪声导致射线不相交、平移基线长短的权衡。

    关键技术

    最小二乘求解、关键帧选择策略、手性约束检查。

    7.8  深度滤波器

    深度滤波器(Depth Filter)是现代视觉SLAM(特别是直接法和半直接法)中一个非常核心且精妙的概念。它是一种概率化、迭代式的深度估计方法。

    我们先用一个比喻来理解它的核心思想,然后再深入技术细节。

    一、核心思想与比喻:谨慎的侦探

    想象一下,你是一个侦探,正在试图通过一系列模糊的线索来确定一个秘密物品的藏匿距离

    • 传统三角测量:就像一个冲动的侦探。他只拿到两条线索(两张照片),立刻画两条线,说:“交点就在这里!这就是答案!” 如果线索稍微有点偏差(噪声),这个交点的位置可能错得离谱。

    • 深度滤波器:则像一个谨慎、理性的侦探。他的做法是:

    1. 初始假设(Initialization)

      :拿到第一条线索(第一张照片的某个像素),他不会下任何结论。他会说:“根据我的经验,这个物品的距离可能在1米到100米之间的任何位置。但我不确定,所以这个范围内的可能性都差不多。” 他建立了一个关于“距离”的概率分布,初始时这个分布非常宽(不确定性很大)。

    2. 收集新证据并更新(Update)

      :他拿到第二条线索(第二张照片)。他利用这个新线索,重新评估了物品的可能距离。他说:“哦,结合新线索,现在看起来物品在5米到10米的可能性最大。” 他用新证据更新了他的概率分布,这个分布变窄了(不确定性减小)。

    3. 持续迭代(Iteration)

      :他不断获取新的线索(后续的相机帧),每一次都用来更新他的判断。概率分布会变得越来越窄,越来越尖锐,集中在一个很小的距离范围内。

    4. 最终确认(Convergence)

      :当他对距离的判断非常有信心时(概率分布的方差小于一个阈值),他才会拍板:“我确定了!物品就在7.3米远的地方!” 这个估计值才被采纳为地图点。

    深度滤波器做的就是这件事:它为图像中的一个像素点维护一个关于其深度的概率分布,并利用后续的图像帧不断地观测和更新这个分布,直到其不确定性收敛到足够小为止。


    二、为什么需要深度滤波器?(相比三角测量的优势)

    对于特征点法SLAM,三角测量工作得很好,因为它处理的是高辨识度的角点,在不同图像中匹配相对容易。但对于直接法或半直接法SLAM,它们处理的是普通像素(比如墙上的一个点),这些点缺乏独特性。

    此时,三角测量会遇到两个致命问题:

    1. 小基线问题

      :相机刚开始移动时,基线(两次拍照的距离)很短,三角测量的深度误差极大。深度滤波器通过融合多帧信息,能很好地处理小基线运动。

    2. 匹配模糊性

      :在一个普通像素的极线上搜索匹配点时,可能会找到很多个长得都很像的图像块。三角测量会随机选一个,很可能出错。深度滤波器则会认为“这些可能都是对的”,并用这种不确定性来更新其概率模型,更加鲁棒。


    三、深度滤波器的工作流程

    深度滤波器通常是针对单个像素(或像素块)独立运行的。其工作流程分为三步:

    第1步:初始化 (Initialization)
    • 当系统决定要跟踪一个新的像素点时(通常是图像中梯度较大的地方),深度滤波器被创建。

    • 由于对该点的深度一无所知,系统会给它一个非常宽泛的初始深度范围。

    • 关键技术:逆深度参数化 (Inverse Depth Parametrization)。滤波器不直接估计深度 d,而是估计它的倒数 ρ = 1/d

      • 为什么用逆深度?
    1. 能表示无穷远点

      :当 d -> ∞ 时,ρ -> 0。这是一个有限的、良态的数值,可以用高斯分布很好地建模。而 d 无法用有限的均值和方差来表示无穷远。

    2. 不确定性更符合高斯分布

      :在固定的相机运动下,一个像素在另一帧图像上的投影不确定性(以像素为单位),与它的逆深度大致成线性关系,而与深度本身是非线性的。这使得使用高斯分布(即均值和方差)来建模逆深度变得非常合适,也为使用卡尔曼滤波等工具铺平了道路。

  • 初始状态

    :滤波器被初始化为一个高斯分布 N(μ, σ^2),其中均值 μ 可以是根据经验猜测的某个逆深度值,而方差 σ^2 会被设得非常大,表示极高的不确定性。

  • 第2步:传播与更新 (Propagation & Update)

    这是滤波器的核心循环。当一个新的相机帧到来时:

    1. 投影与搜索

    • 根据已知的相机运动和上一步的深度分布(一个深度范围,而不是一个定值),我们可以计算出这个像素点在新图像中可能出现的位置范围。这个范围就是极线上的一段线段

    • 系统会在这段极线线段上进行搜索,寻找与原始像素块最匹配的区域(例如,通过计算SSD或NCC等相关性得分)。

  • 测量与更新

    • 旧的信念 (Prior)

      N(μ_old, σ_old^2)

    • 新的观测 (Measurement)

      N(ρ_obs, σ_obs^2)

    • 新的信念 (Posterior)

      N(μ_new, σ_new^2)

    • 一旦找到最佳匹配,就相当于完成了一次局部的三角测量,得到了一个关于逆深度的新测量值ρ_obs 和它的不确定性 σ_obs^2

    • 贝叶斯更新

      :滤波器会像一个一维卡尔曼滤波器一样,将这个新的测量值融合进现有的概率分布中。

    • 更新后,新的均值 μ_new 会更接近真实值,而新的方差 σ_new^2 会比 σ_old^2 更小(不确定性降低)。

    第3步:收敛或移除 (Convergence / Removal)
    • 滤波器会持续执行第2步的更新过程。

    • 收敛 (Convergence)

      :如果经过多帧的更新后,逆深度分布的方差 σ^2 小于一个预设的阈值,我们就认为这个点的深度已经估计得足够准确了。此时,这个点被“提升”为成熟的地图点(在SVO中称为Seed),并被正式加入到地图中,用于后续的相机位姿跟踪。

    • 移除 (Removal)

      :如果在一定数量的帧内,滤波器的方差仍然很大,或者在搜索时总是找不到好的匹配(例如,点被遮挡或移出视野),那么这个滤波器就会被丢弃,因为它可能对应一个不稳定的点。


    四、优缺点总结

    优点
    1. 鲁棒性强

      :能够很好地处理小基线运动和匹配模糊性,比单次三角测量可靠得多。

    2. 精度高

      :通过融合多帧信息,最终得到的深度估计精度很高。

    3. 生成半稠密地图

      :可以为图像中任何有梯度的像素估计深度,从而生成比稀疏特征点法更稠密的地图。

    缺点
    1. 计算成本

      :为成百上千个像素维护和更新滤波器,计算开销较大。

    2. 收敛延迟

      :一个点的深度需要经过多帧才能确定,存在一定的延迟。

    3. 对光度一致性敏感

      :因为匹配是基于像素块的亮度值,所以对光照变化、相机自动曝光等很敏感。

    经典应用

    • SVO (Semi-direct Visual Odometry)

      :是深度滤波器方法的经典代表作。它跟踪稀疏的特征点,但同时为这些特征点周围的像素建立深度滤波器,以创建半稠密的地图。

    • DSO (Direct Sparse Odometry)

      :虽然DSO的后端优化方式不同,但其前端初始化新点时也借鉴了类似的思想,需要观测多帧来确定一个点的初始深度。

    总而言之,深度滤波器是一种优雅而强大的概率化方法,它将时间维度上的多帧信息有效地融合起来,以高精度、高鲁棒性的方式解决了单个像素的深度估计问题,是现代直接法和半直接法SLAM能够成功的关键技术之一。

    7.9 3D-2D: PnP

    我们来详细讲解视觉SLAM中一个极其重要的位姿估计算法:PnP (Perspective-n-Point)

    一、核心问题:PnP解决的是什么?

    想象一下你正在玩一个增强现实(AR)游戏,你希望在你的桌面上放一个虚拟的皮卡丘。为了让皮卡丘看起来像是真的站在桌子上,程序必须知道你的手机(相机)相对于桌子(世界)的确切位置和朝向(姿态)

    PnP就是解决这个问题的核心算法。

    PnP问题的标准定义是:

    当我们知道 n个 三维空间点(3D) 在世界坐标系下的坐标,以及它们在相机拍摄的一张 图像(2D) 上的投影像素坐标时,如何求解相机在世界坐标系下的 位姿(Pose),即 旋转(Rotation) 和 平移(Translation)

    7.10 最小化重投影误差求解PnP

    我们来深入、系统地讲解如何通过最小化重投影误差(Minimizing Reprojection Error)来求解PnP问题。这通常被称为非线性优化BA(Bundle Adjustment)式的方法,是所有PnP解法中精度最高的一种。

    雅可比矩阵(Jacobian Matrix)J的推导,以及误差e关节空间点P的导数推导

    7.11 3D-3D:ICP

    代码笔记

    orb_cv.cpp  使用OpenCV进行特征点提取与匹配

    该C++程序使用OpenCV库,完整地演示了一个经典的特征点匹配流程。这是许多计算机视觉应用(如图像拼接、三维重建、视觉SLAM)的 foundational step。

    程序的主要工作流程如下:

    1. 特征检测 (Feature Detection):程序首先加载两张输入的图像。然后,它使用ORB(Oriented FAST and Rotated BRIEF) 算法在每张图像中检测出数百个“关键点”(Keypoints)。这些关键点是图像中具有独特性、易于识别和跟踪的角点或斑点。

    2. 特征描述 (Feature Description):对于检测出的每一个关键点,程序会计算一个描述子(Descriptor)。ORB算法使用BRIEF描述子,它是一种二进制字符串,相当于该关键点邻域图像块的一个紧凑“指纹”。

    3. 特征匹配 (Feature Matching):程序使用暴力匹配(Brute-Force Matcher) 的方法来寻找两张图像之间的对应关系。它会取出第一张图的每个描述子,然后与第二张图的所有描述子逐一比较,找出最相似(即汉明距离最小)的一个作为匹配对。

    4. 匹配筛选 (Match Filtering):由于噪声和场景重复性,暴力匹配会产生一些错误的匹配对。程序采用了一种常用的启发式方法来筛选匹配结果:只保留那些匹配质量足够好(即汉明距离足够小)的匹配对。判断标准是,一个匹配的距离不应远大于所有匹配中的“最佳匹配”的距离。

    5. 结果可视化 (Visualization):最后,程序将匹配结果直观地展示出来。它会并排显示两张原始图像,并用线条连接起被认为是匹配成功的关键点。程序分别展示了筛选前的所有匹配和筛选后的“好”匹配,以便用户直观地评估筛选算法的效果。

    orb_self.cpp 手动实现ORB特征描述子计算和暴力匹配

    该C++程序从零开始手动实现了ORB (Oriented FAST and Rotated BRIEF)特征的关键部分,包括描述子的计算和匹配过程。它旨在深入展示ORB算法的内部工作原理,而不是依赖OpenCV的高层封装。

    程序的主要工作流程如下:

    1. 特征点检测:程序使用OpenCV内置的FAST算法来快速检测图像中的角点。这构成了ORB特征点的位置基础。

    2. 方向计算与描述子生成 (手动实现 ComputeORB):这是程序的核心部分。

    • 方向计算

      :为了使描述子具有旋转不变性,程序首先为每个FAST角点计算一个主方向。它采用强度质心法 (Intensity Centroid),计算角点周围图像块的质心,并以角点中心指向质心的向量作为该点的主方向。

    • rBRIEF描述子计算

      :然后,程序计算**旋转感知的BRIEF (rBRIEF)**描述子。它使用一组预定义的、固定的256个点对。对于每个关键点,这些点对会根据该关键点的主方向进行旋转。然后,通过比较旋转后点对的亮度大小(p < q ?),生成一个256位的二进制字符串,即该关键点的描述子。

  • 特征匹配 (手动实现 BfMatch)

    • 程序实现了一个暴力匹配算法来寻找两组描述子之间的对应关系。

    • 它遍历第一张图的每个描述子,并与第二张图的所有描述子进行比较,找出汉明距离最小的一个。

    • 为了提高计算汉明距离的效率,程序使用了Intel的SSE指令 _mm_popcnt_u32,它可以硬件级别快速计算一个32位整数中“1”的个数。

    • 匹配结果会经过一个简单的阈值筛选,只有汉明距离小于某个固定值(如40)的匹配才被认为是有效的。

  • 结果可视化:最后,程序使用OpenCV的drawMatches函数将找到的匹配对在两张图像之间用线条连接起来,并显示结果。

  • pose_estimation_2d2d.cpp 使用OpenCV进行2D-2D特征匹配并估计相机运动

    该C++程序完整地演示了从两张2D图像估计相机相对运动的经典流程。这是视觉SLAM中进行相机位姿初始化的关键步骤,也称为“对极几何”。

    程序的主要工作流程如下:

    1. 特征匹配

    • 程序首先加载两张图像。

    • 调用find_feature_matches函数,使用ORB算法在两张图上分别检测关键点并计算描述子。

    • 然后使用暴力匹配(Brute-Force)汉明距离找到描述子之间的对应关系。

    • 最后,通过一个基于最小距离的启发式筛选,剔除可能错误的匹配,得到一组较为可靠的匹配点对。

  • 运动估计

    • 核心的运动估计在pose_estimation_2d2d函数中完成。

    • 它首先利用匹配点对和相机内参,调用OpenCV的findEssentialMat函数计算本质矩阵 (E)。本质矩阵蕴含了两视图之间的相对旋转和平移信息,并且不依赖于场景结构。

    • 程序还演示了如何计算基础矩阵 (F) 和 单应矩阵 (H),这两者是与本质矩阵相关的概念,但F不包含内参信息,H主要适用于平面场景。

    • 得到本质矩阵E后,程序调用recoverPose函数。这个函数从E中分解出相对的旋转矩阵 (R) 和 平移向量 (t)。由于数学上的模糊性,分解会产生四组可能的解,recoverPose内部通过三角化和“切平面前方检查”来确定唯一正确的解。

    单目视觉尺度不确定性,对两张图像的t归一化固定尺度,或者令初始化时所有的特征点平均深度为1来固定尺度(控制场景规模大小,计算在数值上更稳定)。单目初始化不能只有纯旋转,必须要有一定程度的平移。初始化后就可以用3D-2D计算相机运动了。单目slam情况下经常选择让相机进行左右平移以顺利地进行初始化。

    triangulation.cpp 三角测量

    该C++程序演示了通过三角测量(Triangulation)从两个视图中恢复三维点结构的完整流程。这是单目视觉SLAM中初始化地图点或者进行三维重建的关键步骤。

    程序的主要工作流程如下:

    1. 特征匹配与位姿估计

    • 程序首先在两张输入的图像之间寻找ORB特征点的匹配对。

    • 然后,利用这些2D-2D的匹配点,通过计算本质矩阵(E)并对其进行分解,来估计出第二张图像相对于第一张图像的相对位姿(旋转矩阵R和平移向量t)。

  • 三角测量 (triangulation函数)

    • 这是程序的核心。对于每一组匹配的特征点,我们现在已知它们在两张图像上的2D坐标,以及两台相机之间的相对位置关系 (R, t)

    • 程序利用这些信息,调用OpenCV的triangulatePoints函数来为每个匹配对计算出其对应的三维空间点坐标

    • 这个过程在几何上相当于从两个相机中心向各自的2D观测点发出射线,这两条射线的交点(或最近点)就是该特征点的三维位置。

  • 结果验证与可视化

    • 为了验证三角测量结果的正确性,程序将计算出的三维点重投影回两个相机视图中。

    • 在第一个视图中,它直接使用计算出的3D点的Z坐标(即深度)来为原始特征点着色。

    • 在第二个视图中,它先将3D点通过 R 和 t 变换到第二个相机的坐标系下,然后用新的深度为原始特征点着色。

    • 通过在图像上绘制这些带颜色(表示深度)的圆圈,可以直观地看到恢复出的三维结构。如果三角化正确,这些点应该有合理的深度分布(例如,近处的点和远处的点颜色不同)。

    三角测量的矛盾: 增大平移可能导致匹配失效;而平移太小,则三角化精度不够。

    pose_estimation_3d2d.cpp

    演示了从2D图像和3D点云数据估计相机位姿(PnP问题),并对比了三种不同的求解方法:OpenCV的内置PnP求解器、手动实现的高斯-牛顿优化法,以及使用g2o图优化库的方法。

    该程序解决的是经典的PnP (Perspective-n-Point)问题,即根据一组已知的3D空间点及其在2D图像上的投影,来求解相机的位姿(旋转和-平移)。它通过三种不同的方法实现并对比了这一过程。

    1. 数据准备

    • 程序首先通过特征匹配在两张连续的图像之间找到对应点。

    • 利用第一张图像的深度图,将第一张图中的特征点反投影到三维空间,获得一组在第一帧相机坐标系下的3D点

    • 这些3D点在第二张图像中对应的特征点,则构成了它们的2D投影

    • 这样,程序就构建了一系列的3D-2D匹配对,这是所有PnP算法的输入。

  • 方法一:OpenCV solvePnP

    • 程序首先调用OpenCV内置的高度优化的solvePnP函数。这是一个直接的、非迭代的求解器(如P3P, EPnP等,内部可能结合RANSAC),能够快速给出一个相机位姿的解。这通常用作后续优化的初始值。

  • 方法二:手动实现高斯-牛顿法

    • 计算重投影误差:将3D点根据当前位姿估计投影到图像上,与观测到的2D点作比较。

    • 计算误差关于位姿的雅可比矩阵

    • 构建并求解线性方程组HΔx=b来获得位姿的更新量。

    • 使用Sophus库来更新SE(3)位姿。

    • 程序接着从零开始实现了基于高斯-牛顿的非线性优化算法来求解PnP。这个过程也常被称为光束法平差 (Bundle Adjustment, BA),尽管在这个例子中只优化了相机位姿而3D点是固定的。

    • 它迭代地进行以下步骤:

  • 方法三:使用g2o图优化库

    • 顶点

      :一个 VertexPose,代表未知的相机位姿 SE3d

    • :多个 EdgeProjection,每条边代表一个3D-2D观测,连接到VertexPose。每条边负责计算其对应的重投影误差和雅可比矩阵。

    • 最后,程序使用g2o库来解决同一个问题。它将PnP问题建模为一个

    • 构建完图后,调用g2o的优化器进行求解。g2o封装了复杂的优化流程,使得用户只需关注顶点和边的定义。

    核心对比:该程序清晰地展示了从“使用高级API”到“手动实现底层算法”再到“使用通用优化框架”三种解决问题的层次。solvePnP最简单快捷,手动实现的高斯-牛顿法最能揭示算法细节,而g2o则提供了一个通用、强大且可扩展的框架来解决更复杂的优化问题。

    pose_estimation_3d3d.cpp

    该程序解决的是3D-3D位姿估计问题,也常被称为点云配准 (Point Cloud Registration) 或 ICP (Iterative Closest Point) 问题的核心步骤。它旨在找到一个最佳的刚体变换(旋转R和平移t),使得一个3D点集(源点云)经过该变换后,能与另一个3D点集(目标点云)尽可能地重合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值