视觉slam十四讲学习笔记(六)视觉里程计 1

news2024/12/23 15:21:36

本文关注基于特征点方式的视觉里程计算法。将介绍什么是特征点,如何提取和匹配特征点,以及如何根据配对的特征点估计相机运动。

目录

前言

一、特征点法

1 特征点

2 ORB 特征

FAST 关键点

BRIEF 描述子

3 特征匹配

二、实践:特征提取和匹配

三、2D-2D: 对极几何

1 对极约束

2 本质矩阵

3 单应矩阵

四、实践:对极约束求解相机运动

五、三角测量

总结


前言

1. 理解图像特征点的意义, 并掌握在单幅图像中提取出特征点,及多幅图像中匹配特征点的方法。

2. 理解对极几何的原理,利用对极几何的约束,恢复出图像之间的摄像机的三维运动。

3. 理解 PNP 问题,及利用已知三维结构与图像的对应关系,求解摄像机的三维运动。

4. 理解 ICP 问题,及利用点云的匹配关系,求解摄像机的三维运动。

5. 理解如何通过三角化,获得二维图像上对应点的三维结构。

哔哩哔哩课程链接:视觉SLAM十四讲ch7_1_哔哩哔哩_bilibili


一、特征点法

特征点法通常是指在计算机视觉和图像处理中使用的一种方法,其目的是检测和描述图像中的关键特征点。这些特征点可以是图像中独特或显著的位置,如角点、边缘点等,它们在不同图像中具有相似性,因此可以用来进行图像匹配、目标跟踪、三维重建等应用。

特征点法的一般步骤包括以下几个方面:

  1. 特征点检测: 通过一些算法检测图像中的关键特征点,这些特征点通常是在局部区域内显著的位置,例如角点、边缘点等。常用的特征点检测算法包括Harris角点检测、Shi-Tomasi角点检测、SIFT(尺度不变特征变换)、SURF(加速鲁棒特征)等。

  2. 特征点描述: 对于检测到的特征点,需要提取其特征描述子,以便后续匹配。这些描述子通常是能够表征特征点周围局部结构的向量或矩阵。常用的特征描述算法包括SIFT描述子、SURF描述子、ORB(Oriented FAST and Rotated BRIEF)描述子等。

  3. 特征点匹配: 在不同图像中,通过比较特征点的描述子,找到相似的特征点对,从而建立图像间的对应关系。匹配可以使用一些距离度量或相似性度量来完成。

  4. 应用: 特征点法的应用非常广泛,包括图像配准、目标跟踪、三维重建、拼接图像、物体识别等领域。

特征点

VO 的主要问题是如何根据图像来估计相机运动。然而,图像本身是一个由亮度和色彩组成的矩阵,如果直接从矩阵层面考虑运动估计,将会非常困难。所以,习惯于采用这样一种做法:首先,从图像中选取比较有代表性的点。这些点在相机视角发生少量变化后会保持不变,所以会在各个图像中找到相同的点。然后,在这些点的基础上,讨论相机位姿估计问题,以及这些点的定位问题。在经典 SLAM 模型中,把它们称为路标。而在视觉 SLAM 中,路标则是指图像特征(Features)。

  • 特征是图像信息的另一种数字表达形式
  • 特征点在相机运动之后保持稳定。
  • 特征点是图像里一些特别的地方

可以作为图像特征的部分:角点、边缘、区块。

人工设计的特征点能够拥有如下的性质:

1. 可重复性Repeatability):相同的“区域”可以在不同的图像中被找到。

2. 可区别性Distinctiveness):不同的“区域”有不同的表达。

3. 高效率Efficiency):同一图像中,特征点的数量应远小于像素的数量。

4. 本地性Locality):特征仅与一小片图像区域相关。

特征点由关键点Key-point)和描述子Descriptor)两部分组成。

比方说,当谈论 SIFT 特征时,是指“提取 SIFT 关键点,并计算 SIFT 描述子”两件事情。关键点是指该特征点在图像里的位置,有些特征点还具有朝向、大小等信息。描述子通常是一个向量,按照某种人为设计的方式,描述了该关键点周围像素的信息。描述子是按照“外观相似的特征应该有相似的描述子”的原则设计的。因此,只要两个特征点的描述子在向量空间上的距离相近,就可以认为它们是同样的特征点。

2 ORB 特征

OpenCV 提供的 ORB 特征点检测结果。

ORB 特征亦由关键点描述子两部分组成。它的关键点称为“Oriented FAST”,是一种改进的 FAST 角点,什么是 FAST 角点我们将在下文介绍。它的描述子称为 BRIEF(Binary Robust Independent Elementary Features)。因此,提取 ORB 特征分为两个步骤:

1. FAST 角点提取:找出图像中的角点。相较于原版的 FAST, ORB 中计算了特征点的主方向,为后续的 BRIEF 描述子增加了旋转不变特性。

2. BRIEF 描述子:对前一步提取出特征点的周围图像区域进行描述。

FAST 关键点

FAST(Features from Accelerated Segment Test)是一种用于快速检测图像中角点的特征点检测算法。FAST 算法主要用于实时应用,它在速度和计算效率上表现出色,并且在相对平滑的图像中能够准确地检测到关键点。

以下是 FAST 算法的主要特点和步骤:

  1. 加速度段测试(Accelerated Segment Test): FAST 算法使用一种称为加速度段测试的策略来判断一个像素是否是关键点。在这个测试中,选择了一个中心像素点和周围的16个像素点,然后根据这些像素点的灰度值与中心像素的灰度值进行比较,以判断中心像素是否是一个关键点。这个测试是基于一种简单的圆形区域的像素采样。

  2. 非极大值抑制: 在加速度段测试的结果中,如果中心像素是一个关键点,就会产生一些相邻的像素点也可能被认为是关键点。为了防止重复检测,FAST 算法进行非极大值抑制,只选择那些在某个阈值下,灰度值超过相邻像素灰度值的中心像素点作为最终的关键点。

  3. 参数选择: FAST 算法中有一个重要的参数,即阈值。阈值的选择影响到算法的灵敏度,可以根据具体应用场景进行调整。

FAST 算法的优点在于其计算速度快,适用于实时应用,但缺点是对图像噪声和纹理较敏感。在一些情况下,FAST 可以用于快速初始化特征点,然后通过其他方法(例如,通过机器学习方法或描述子匹配)来提高准确性。FAST 算法常常用于计算机视觉领域中的实时特征点检测,如图像拼接、物体跟踪和视觉SLAM(Simultaneous Localization and Mapping)等应用中。

FAST 是一种角点,主要检测局部像素灰度变化明显的地方,以速度快著称。它的思想是:如果一个像素与它邻域的像素差别较大(过亮或过暗), 那它更可能是角点。相比于其他角点检测算法,FAST 只需比较像素亮度的大小,十分快捷。它的检测过程如下

1. 在图像中选取像素 p,假设它的亮度为 Ip

2. 设置一个阈值 T(比如 Ip 20%)

3. 以像素 p 为中心, 选取半径为 3 的圆上的 16 个像素点。

4. 假如选取的圆上,有连续的 N 个点的亮度大于 Ip + T 或小于 Ip T,那么像素 p可以被认为是特征点 (N 通常取 12,即为 FAST-12。其它常用的 N 取值为 9 11,他们分别被称为 FAST-9FAST-11)

5. 循环以上四步,对每一个像素执行相同的操作。

针对 FAST 角点不具有方向性和尺度的弱点,ORB 添加了尺度和旋转的描述。尺度不变性由构建图像金字塔,并在金字塔的每一层上检测角点来实现。而特征的旋转是由灰度质心法(Intensity Centroid)实现的。

BRIEF 描述子

BRIEF(Binary Robust Independent Elementary Features)是一种用于图像特征描述的算法。它主要用于生成图像中检测到的关键点的二进制描述子,用于在图像匹配和目标识别等任务中进行特征匹配。

以下是 BRIEF 描述子的主要特点和步骤:

  1. 二进制描述子生成: BRIEF 描述子的主要思想是通过在关键点周围选择一组固定的、随机的像素对,并比较它们的灰度值来生成二进制字符串。这些比较结果被编码成二进制位,形成一个二进制向量,称为 BRIEF 描述子。

  2. 随机选择的像素对: BRIEF 算法在每个关键点周围随机选择一组像素对,这些像素对的选择对于最终的描述子起到关键作用。这种随机性带来了描述子的差异性,使其更具区分性。

  3. 描述子长度: BRIEF 描述子的长度由用户指定,通常为一个定长的二进制字符串。较长的描述子可能提供更好的区分性,但也需要更多的存储和计算资源。

  4. 不变性: BRIEF 描述子相对于尺度和旋转是不变的。这是通过在图像尺度空间中选择随机像素对的方法实现的。

尽管 BRIEF 描述子具有计算速度快、存储需求低的优势,但它对图像噪声和干扰较为敏感。为了提高鲁棒性,通常会与其他算法一起使用,例如在关键点检测中可以与 FAST 等方法结合使用。

总体而言,BRIEF 描述子在实时图像处理和计算资源受限的场景中表现良好,特别适用于嵌入式系统和移动设备等应用。

3 特征匹配

特征匹配是视觉 SLAM 中极为关键的一步,宽泛地说,特征匹配解决了 SLAM 中的数据关联问题(data association),即确定当前看到的路标与之前看到的路标之间的对应系。通过对图像与图像,或者图像与地图之间的描述子进行准确的匹配,可以为后续的姿态估计,优化等操作减轻大量负担。然而,由于图像特征的局部特性,误匹配的情况广泛存在,而且长期以来一直没有得到有效解决,目前已经成为视觉 SLAM 中制约性能提升的一大瓶颈。部分原因是因为场景中经常存在大量的重复纹理,使得特征描述非常相似。在这种情况下,仅利用局部特征解决误匹配是非常困难的。

  • 最简单的特征匹配方法就是暴力匹配(Brute-Force Matcher
  • 描述子距离表示了两个特征之间的相似程度,不过在实际运用中还可以取不同的距离度量范数。
  • 用汉明距离(Hamming distance)做为度量——两个二进制串之间的汉明距离,指的是它们不同位数的个数。
  • 快速近似最近邻( FLANN 算法更加适合于匹配点数量极多的情况。

二、实践:特征提取和匹配

slambook/ch7/feature_extraction.cpp
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

int main ( int argc, char** argv )
{
    if ( argc != 3 )
    {
        cout<<"usage: feature_extraction img1 img2"<<endl;
        return 1;
    }
    //-- 读取图像
    Mat img_1 = imread ( argv[1], CV_LOAD_IMAGE_COLOR );
    Mat img_2 = imread ( argv[2], CV_LOAD_IMAGE_COLOR );

    //-- 初始化
    std::vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;
    Ptr<FeatureDetector> detector = ORB::create();
    Ptr<DescriptorExtractor> descriptor = ORB::create();
    // Ptr<FeatureDetector> detector = FeatureDetector::create(detector_name);
    // Ptr<DescriptorExtractor> descriptor = DescriptorExtractor::create(descriptor_name);
    Ptr<DescriptorMatcher> matcher  = DescriptorMatcher::create ( "BruteForce-Hamming" );

    //-- 第一步:检测 Oriented FAST 角点位置
    detector->detect ( img_1,keypoints_1 );
    detector->detect ( img_2,keypoints_2 );

    //-- 第二步:根据角点位置计算 BRIEF 描述子
    descriptor->compute ( img_1, keypoints_1, descriptors_1 );
    descriptor->compute ( img_2, keypoints_2, descriptors_2 );

    Mat outimg1;
    drawKeypoints( img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
    imshow("ORB特征点",outimg1);

    //-- 第三步:对两幅图像中的BRIEF描述子进行匹配,使用 Hamming 距离
    vector<DMatch> matches;
    //BFMatcher matcher ( NORM_HAMMING );
    matcher->match ( descriptors_1, descriptors_2, matches );

    //-- 第四步:匹配点对筛选
    double min_dist=10000, max_dist=0;

    //找出所有匹配之间的最小距离和最大距离, 即是最相似的和最不相似的两组点之间的距离
    for ( int i = 0; i < descriptors_1.rows; i++ )
    {
        double dist = matches[i].distance;
        if ( dist < min_dist ) min_dist = dist;
        if ( dist > max_dist ) max_dist = dist;
    }
    
    // 仅供娱乐的写法
    min_dist = min_element( matches.begin(), matches.end(), [](const DMatch& m1, const DMatch& m2) {return m1.distance<m2.distance;} )->distance;
    max_dist = max_element( matches.begin(), matches.end(), [](const DMatch& m1, const DMatch& m2) {return m1.distance<m2.distance;} )->distance;

    printf ( "-- Max dist : %f \n", max_dist );
    printf ( "-- Min dist : %f \n", min_dist );

    //当描述子之间的距离大于两倍的最小距离时,即认为匹配有误.但有时候最小距离会非常小,设置一个经验值30作为下限.
    std::vector< DMatch > good_matches;
    for ( int i = 0; i < descriptors_1.rows; i++ )
    {
        if ( matches[i].distance <= max ( 2*min_dist, 30.0 ) )
        {
            good_matches.push_back ( matches[i] );
        }
    }

    //-- 第五步:绘制匹配结果
    Mat img_match;
    Mat img_goodmatch;
    drawMatches ( img_1, keypoints_1, img_2, keypoints_2, matches, img_match );
    drawMatches ( img_1, keypoints_1, img_2, keypoints_2, good_matches, img_goodmatch );
    imshow ( "所有匹配点对", img_match );
    imshow ( "优化后匹配点对", img_goodmatch );
    waitKey(0);

    return 0;
}

对ch7文件夹中的cmake工程进行编译,报错:

undefined reference to `vtable for fmt::v7::format_error

链接上fmt 库:

target_link_libraries("可执行文件" ${Sophus_LIBRARIES} fmt)

未筛选的匹配中带有大量的误匹配。经过一次筛选之后,匹配数量减少了许多,大多数匹配都是正确的。这里筛选的依据是汉明距离小于最小距离的两倍,这是一种工程上的经验方法。尽管在示例图像中能够筛选出正确的匹配,但仍然不能保证在所有其他图像中得到的匹配都是正确的。因此,在后面的运动估计中,还需要使用去除误匹配的算法。

三、2D-2D: 对极几何

1 对极约束

对极约束简洁地给出了两个匹配点的空间位置关系。于是,相机位姿估计问题变为以下两步:

1. 根据配对点的像素位置,求出 E 或者 F

2. 根据 E 或者 F,求出 R, t

由于 E F 只相差了相机内参,而内参在 SLAM 中通常是已知的,所以实践当中往往使用形式更简单的 E。我们以 E 为例,介绍上面两个问题如何求解。

本质矩阵

根据定义,本质矩阵 E = t R。它是一个 3 × 3 的矩阵,内有 9 个未知数。那么,是不是任意一个 3 × 3 的矩阵都可以被当成本质矩阵呢?从 E 的构造方式上看,有以下值得注意的地方:

本质矩阵是由对极约束定义的。由于对极约束是等式为零的约束,所以对 E 乘以任意非零常数后,对极约束依然满足。把这件事情称为 E 在不同尺度下是等价的。

根据 E = t R,可以证明 [3],本质矩阵 E 的奇异值必定是 [σ, σ, 0]T 的形式。这称为本质矩阵的内在性质

另一方面,由于平移和旋转各有三个自由度,故 t R 共有六个自由度。但由于尺度等价性,故 E 实际上有五个自由度。

E 具有五个自由度的事实,表明我们最少可以用五对点来求解 E。但是,E 的内在性质是一种非线性性质,在求解线性方程时会带来麻烦,因此,也可以只考虑它的尺度等价性,使用八对点来估计 E——这就是经典的八点法(Eight-point-algorithm。八点法只利用了 E 的线性性质,因此可以在线性代数框架下求解。

3 单应矩阵

除了基本矩阵和本质矩阵,还有一种称为单应矩阵(HomographyH 的东西,它描述了两个平面之间的映射关系。

四、实践:对极约束求解相机运动

五、三角测量

三角化获得地图点深度


总结

本文内容结束,关于实践部分,预计后续更新!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1452256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络——14CDN

CDN 视频流化服务和CDN&#xff1a;上下文 视频流量&#xff1a;占据着互连网大部分的带宽 Netflix&#xff0c;YouTube&#xff1a;占据37%&#xff0c;16%的下行流量 挑战&#xff1a;规模性-如何服务~1B用户&#xff1f; 单个超级服务器无法提供服务&#xff08;为什么&am…

第7章 Page442~446 7.8.9智能指针

指向堆内存的指针&#xff0c;很容易忘了释放&#xff1a; int foo() {int* p new int(9);cout << *p << endl;return *p; } 为什么要用指针 使用堆数据有以下几个目的&#xff08;也可称为作用&#xff09;如表7-18所列 表7-18 使用堆数据的常见目的 使用堆数…

阿里云服务器租用价格表(2024更新)

2024年最新阿里云服务器租用费用优惠价格表&#xff0c;轻量2核2G3M带宽轻量服务器一年61元&#xff0c;折合5元1个月&#xff0c;新老用户同享99元一年服务器&#xff0c;2核4G5M服务器ECS优惠价199元一年&#xff0c;2核4G4M轻量服务器165元一年&#xff0c;2核4G服务器30元3…

数据结构:4_二叉树

二叉树 一.树概念及结构 1. 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个**特殊的…

让你的资金运动起来,金钱的聪明处理方式

一、教程描述 本套教程主要讲解了金融思维和财务思维&#xff0c;常见投资工具的实操技巧&#xff0c;资产配置方案的制定方法&#xff0c;等等&#xff0c;将会重构你现有的投资观念&#xff0c;提升你认知的宽度和深度&#xff0c;可以轻松读懂财经新闻&#xff0c;不仅学会…

单片机学习笔记---LED呼吸灯直流电机调速

目录 LED呼吸灯 直流电机调速 模型结构 波形 定时器初始化函数 中断函数 主程序 上一节讲了电机的工作原理&#xff0c;这一节开始代码演示&#xff01; 我们上一篇说Ton的时间长Toff时间短电机会快&#xff0c;Ton的时间短Toff时间长电机会慢 并且我们还要保证无论Ton和…

红队ATKCK|红日靶场Write-Up(附下载链接)

网络拓扑图 下载地址 在线下载&#xff1a; http://vulnstack.qiyuanxuetang.net/vuln/detail/2/ 百度网盘 链接&#xff1a;https://pan.baidu.com/s/1nlAZAuvni3EefAy1SGiA-Q?pwdh1e5 提取码&#xff1a;h1e5 环境搭建 通过上述图片&#xff0c;web服务器vm1既能用于外…

【网络安全】什么样的人适合学?该怎么学?

有很多想要转行网络安全或者选择网络安全专业的人在进行决定之前一定会有的问题&#xff1a; 什么样的人适合学习网络安全&#xff1f;我适不适合学习网络安全&#xff1f; 当然&#xff0c;产生这样的疑惑并不奇怪&#xff0c;毕竟网络安全这个专业在2017年才调整为国家一级…

【BUUCTF 加固题】Ezsql 速通

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

隐函数的求导【高数笔记】

1. 什么是隐函数&#xff1f; 2. 隐函数的做题步骤&#xff1f; 3. 隐函数中的复合函数求解法&#xff0c;与求导中复合函数求解法有什么不同&#xff1f; 4. 隐函数求导的过程中需要注意什么&#xff1f;

Day01 javaweb开发——tlias员工管理系统

任务介绍 完成部门管理和员工管理的增删改查功能 环境搭建 前端---->后端---->数据库 准备数据库表创建springboot工程&#xff08;web、mybatis、mysql驱动、lombok&#xff09;application.properties中引入mybatis配置信息&#xff0c;准备对应的实体类准备三层架…

Midjourney绘图欣赏系列(四)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

深入理解lambda表达式

深入理解ASP.NET Core中的中间件和Lambda表达式 var builder WebApplication.CreateBuilder(args); var app builder.Build(); app.Use(async (context, next) > { // Add code before request. await next(context);// Add code after request.}); 这段C#代码是用于设…

Mac M2芯片配置PHP环境

Mac M2芯片配置PHP环境 1. XAMPP2. PHPBrew(PHP版本管理)安装php7.4.33版本 3. 直接使用homebrew 安装php环境参考 1. XAMPP 官网地址 https://www.apachefriends.org/ 安装 安装完成 web server打开后&#xff0c;在打开localhost 成功&#xff01; 2. PHPBrew(PHP版本管…

node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染

文章目录 ⭐前言⭐ 功能设计与实现💖 node上传文件写入file_map映射表💖 vue3前端上传文件回显⭐ 效果⭐结束⭐前言 大家好,我是yma16,本文分享关于 node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染。 技术选型 前端:vite+vue3+antd 后端:node koa 数据库…

Python asyncio高性能异步编程 详解

目录 一、协程 1.1、greenlet实现协程 1.2、yield关键字 1.3、asyncio 1.4、async & await关键字 二、协程意义 三、异步编程 3.1、事件循环 3.2、快速上手 3.3、await 3.4、Task对象 3.5、asyncio.Future对象 3.5、concurrent.futures.Future对象 3.7、异步…

python+django+vue汽车票在线预订系统58ip7

本课题使用Python语言进行开发。基于web,代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中 使用说明 使用Navicat或者其它工具&#xff0c;在mysql中创建对应名称的数据库&#xff0c;并导入项目的sql文件&#xff1b; 使用PyChar…

软考 系统分析师系列知识点之信息系统战略规划方法(11)

接前一篇文章&#xff1a;软考 系统分析师系列知识点之信息系统战略规划方法&#xff08;10&#xff09; 所属章节&#xff1a; 第7章. 企业信息化战略与实施 第4节. 信息系统战略规划方法 7.4.7 价值链分析法 价值链分析&#xff08;Value Chain Analysis&#xff0c;VCA&am…

BulingBuling - 《研究巴菲特》 [ Buffettology ]

研究巴菲特 使沃伦-巴菲特成为世界上最著名的投资者的那些以前未曾解释过的技术 作者&#xff1a;玛丽-巴菲特 Buffettology The Previously Unexplained Techniques That Have Made Warren Buffett The Worlds Most Famous Investor By Mary Buffett 内容提要 《Buffetto…

php数据类型以及运算符

php数据类型以及运算符 1. php数据类型2. 使用举例3. 运算符 1. php数据类型 包括 String(字符串)、Integer(整型)、Float(浮点型)、Boolean(布尔型)、Array(数组)、Object(对象)、NULL(空值) 2. 使用举例 1.字符串 2.整型 3.浮点型 4.布尔型 5.数组 6.对象 7.null 3. 运算符…