视觉SLAM实践入门——(11)用对极约束求解相机运动

《SLAM十四讲》7.4 对极约束求解相机运动(代码详解) 先上完整代码,稍后进行详细解释 完整代码包括上一章讲到的ORB特征检测与匹配部分,在这里ORB部分的内容封装到了函数find_feature_matches()中。 关于该代码的介绍《十四讲》中的原话是:“上一节实践部分的程序提供了特征匹配,而这次我们就使用匹配好的特征点来计算 E,F 和 H,进而分解 E 得到 R,t。整个程序使用 OpenCV 提供的算法进行求解。我们把上一节的特征提取封装成函数,以供后面使用。” #include <iostream> #include <openc 阅读详情

使用对极约束求解相机运动的步骤:

1、提取ORB特征,匹配点对

2、根据匹配点对计算基础矩阵 E

3、分解 E,得到相机位姿 R,t

使用估计的 R,t 可以验证各个特征点对的对极约束误差(理论上误差精确为0)

 

经过验证,使用点对计算的 E,与使用R,t恢复的 E,各元素相差一个同一个非0常数,满足本质矩阵的尺度不变性;通过计算F = K^{-T}EK^{-1} 验证 F,发现前后计算的 F 并不相等,原因还没找到

由于 E 本身具有尺度等价性,它分解得到的 R,t 也有一个尺度等价性。而 R ∈ SO(3) 自身具有约束,所以 t 具有一个尺度。因此在分解过程中,对 t 乘以任意非零常数,分解都是成立的,一般将 t 归一化处理,让它的长度等于 1。能够对 t 长度的归一化,直接导致了单目视觉的尺度不确定性

单目初始化不能只有纯旋转,必须要有一定程度的平移。从 E 分解到 R,t 的过程中,如果相机发生的是纯旋转,导致 t 为零,那么,得到的E 也将为零,这将导致无法求解 R。不过,此时可以依靠 H 求取旋转,但仅有旋转时,无法用三角测量估计特征点的空间位置。如果初始化时平移太小,会使得位姿求解与三角化结果不稳定,从而导致失败。相对的,如果把相机左右移动而不是原地旋转,就容易让单目 SLAM 初始化

当可能存在误匹配的情况时,会倾向于使用随机采样一致性(Random Sample Concensus, RANSAC)来求,而不是最小二乘。RANSAC 是一种通用的做法,适用于很多带错误数据的情况,可以处理带有错误匹配的数据

 

#include <iostream>
using namespace std;

#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
using namespace cv;

void OrbFeaturesMatch(const Mat &img1, const Mat &img2,
			vector<KeyPoint> &kp1, vector<KeyPoint> &kp2,
			vector<DMatch> &matches)
{
	Mat desc1, desc2;
	
	Ptr<FeatureDetector> detector = ORB::create();
	Ptr<DescriptorExtractor> desc = ORB::create();
	Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
	
	//1、检测角点
	detector->detect(img1, kp1);
	detector->detect(img2, kp2);
	//2、计算描述子
	desc->compute(img1, kp1, desc1);
	desc->compute(img2, kp2, desc2);
	//3、匹配点对
	vector<DMatch> match;
	matcher->match(desc1, desc2, match);
	//4、检测误匹配
	double minDist = 10000, maxDist = 0;
	for(int i = 0; i < (int)match.size(); i++)
	{
		double dist = match[i].distance;
		
		minDist = minDist > dist ? dist : minDist;
		maxDist = maxDist < dist ? dist : maxDist;
	}
	
	cout << "minDist and maxDist = " << minDist << " and " << maxDist << endl;
	
	double matchDist = max(30.0, minDist * 2);
	for(int i = 0; i < (int)match.size(); i++)
		if(match[i].distance <= matchDist)
			matches.push_back(match[i]);			
}

void estimateMoving(const vector<KeyPoint> &kp1, const vector<KeyPoint> &kp2, const vector<DMatch> &matches, Mat &R, Mat &t)
{
	//取出匹配点对坐标
	vector<Point2f> p1, p2;
	for(int i = 0; i < matches.size(); i++)
	{
		//DMatch中有3个成员,queryIdx,trainIdx,distance
		//queryIdx是特征点第一张图的索引,trainIdx是特征点在第二张图的索引
		p1.push_back(kp1[matches[i].queryIdx].pt);
		p2.push_back(kp2[matches[i].trainIdx].pt);
	}
	
	//1、计算基础矩阵、本质矩阵、单应矩阵
	Mat fundamentalMat = findFundamentalMat(p1, p2, CV_FM_8POINT);	//8点法
	cout << "fundamentalMat :\n" << fundamentalMat << endl;
	
	double focalLength = 520.9;
	Point2d principalPoint(325.1, 249.7);
	Mat essentialMat = findEssentialMat(p1, p2, focalLength, principalPoint);
	cout << "essentialMax :\n" << essentialMat << endl;
	
	//场景不是平面时,单应矩阵意义不大
	Mat homographyMat = findHomography(p1, p2, RANSAC, 3);	//RANSAC:随机采样一致性,最大允许重投影错误阈值是3
	cout << "homographyMat :\n" << homographyMat << endl;

	//2、分解矩阵,求解相机运动R,t
	recoverPose(essentialMat, p1, p2, R, t, focalLength, principalPoint);
	cout << "R :\n" << R << endl;
	cout << "t :" << t.t() << endl;
}

Point2d pixelToNor(const Point2d &p, const Mat &k)
{
	//像素坐标 = 内参矩阵 * 归一化坐标:p = K * x(齐次坐标运算)
	//下式计算的原理:x = fx * p_x + cx,y = fy * p_y + cy(记像素坐标(x, y),归一化坐标(p_x, p_y))
	//p_x = (x - cx) / fx,p_y = (y - cy) / fy
	return Point2d((p.x - k.at<double>(0, 2)) / k.at<double>(0, 0), (p.y - k.at<double>(1, 2)) / k.at<double>(1, 1));
}

int main(int argc, char **argv)
{
	if(argc != 3)
	{
		cout << "input 2 images" << endl;
		return -1;
	}
	
	Mat img1 = imread(argv[1], CV_LOAD_IMAGE_COLOR);
	Mat img2 = imread(argv[2], CV_LOAD_IMAGE_COLOR);

	//1、匹配特征点
	vector<KeyPoint> kp1, kp2;
	vector<DMatch> matches;
	OrbFeaturesMatch(img1, img2, kp1, kp2, matches);
	
	//2、估计相机运动
	Mat R, t;
	estimateMoving(kp1, kp2, matches, R, t);

	//3、验证本质矩阵的尺度不变性
	Mat tx = (	Mat_<double>(3, 3) << 
		0					, -t.at<double>(2, 0)	, t.at<double>(1, 0)	,
		t.at<double>(2, 0)	, 0						, -t.at<double>(0, 0)	,
		-t.at<double>(1, 0)	, t.at<double>(0, 0)	, 0						);	//t映射的反对称矩阵
	Mat E(tx*R);
	cout << "E : \n" << E << endl;	//tx*R 与前面输出的 E ,各元素之间相差一个非零常数

	//4、验证对极约束	
	Mat k = (Mat_<double>(3, 3) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1);
	for(int i = 0; i < (int)matches.size(); i++)
	{
		//取匹配点对的像素坐标
		Point2d p1(kp1[matches[i].queryIdx].pt.x, kp1[matches[i].queryIdx].pt.y);
		Point2d p2(kp2[matches[i].trainIdx].pt.x, kp2[matches[i].trainIdx].pt.y);
		
		//计算归一化坐标的(x, y)
		Point2d y1 = pixelToNor(p1, k);
		Point2d y2 = pixelToNor(p2, k);
		
		//构造归一化坐标
		Mat x1 = (Mat_<double>(3, 1) << y1.x, y1.y, 1);
		Mat x2 = (Mat_<double>(3, 1) << y2.x, y2.y, 1);
		
		printf("对第%03d个特征点的对极约束误差为:", i);
		cout << x2.t() * E * x1 << endl;
	}
	
	return 0;
}

 

三角测量——用相机运动估计特征点的空间位置 经过对极约束的求解,现在已知R,t,我们想求解两个特征点的深度z1,z2。(在单目相机模型中,深度被抹去了,因此若想建图需要求解‘z’),即,两条线在两个平行的平面中,而两个平面互相平行。因此我们会选择两条线最近的的近似为p点,也就是。当然,由于噪声的存在,我们估得的R,t不一定精确使式子成立,所以更常见的做法是求。使用对极约束估计了相机运动后,接下来利用相机运动估计特征点的空间位置,使用的方法就是。的一个方程,可以根据它直接求得。该式左侧为零,右侧可看成。的存在,两条线可能会出现。 阅读详情

相关推荐

视觉SLAM十四讲笔记(超级通俗易懂哦~)

第二讲 初识SLAM 传感器 Sensors 两类传感器: 安装于环境中的:二维码,GPS, 携带于机器人本体的: 对比激光和相机两大类传感器,激光建图基本上已经研究清楚,视觉SLAM还没有稳定可靠运行 摄像头:轻便、便宜、信息丰富 缺点:遮挡、受光照影响、计算量大、 单目,双目,深度相机(TOF/结构光) ...

qq_41883714的博客 2万+

slam入门3:2D-2D对极几何中的对极约束公式详细解释(参考 视觉slam十四讲)

声明:下面一些内容引用了高翔的视觉slam十四讲, 感谢作者。 对于我这种刚入门的小白(cai bi)来说,对极约束公式中的某些步骤理解起来还是有些难度的,下面把个人对相关内容的理解写下来,以备日后翻阅。 一、对极约束推导 以下图为例,我们希望求取两帧图像 I1 , I2 之间的运动,设第一帧到第二帧的运动为R, t。两个相机中心分别为 O1 , O2 。现在,考虑 I1 中有一个特征点 p...

Zkangsen的博客 2980

视觉SLAM常见面试题 (上)

1、 视觉SLAM方法一般分为 特征点法、直接法、和光流法,简述概念,及优缺点。 特征点法 ——根据提取和匹配特征点来估计相机运动,优化的是重投影误差,对光照变化不敏感,是比较成熟的方案。常见的开源方案:ORB_SLAM 优点: ① 特征点本身对光照、运动、旋转比较不敏感,所以较稳定 ② 相机运动较快(相对直接法来说)也能跟踪成功,鲁棒性较好 ③ 研究时间较久,方案较成熟 缺点: ① 关键点提取、...

hly453的博客 3251

通过对极几何求解相机运动

关于对极几何部分(无论看哪个都发现公式比较难懂…数学基因不足的忧伤),参考: 对极几何-两视图对极约束 基础矩阵 这是我认为讲的比较清楚的对极几何原理。 看到以上的原理得出的重要结论: 1、对极约束的重要结果就是从匹配的点中得出基础矩阵F 2、从基础矩阵F中分解得到相机的选择矩阵R和平移向量t ...

ouyangandy的博客 659

【视觉SLAM】4b-特征点法估计相机运动之PnP 3D-2D

透视n点(Perspective-n-Point,PnP)问题是计算机视觉领域的经典问题,用于求解3D-2D的点运动。换句话说,当知道NNN个世界坐标系中3D空间点的坐标以及它们在图像上的投影点像素坐标时,可以使用PnP算法来估计相机在世界坐标系的姿态。P3P是最简化的PnP形式,即最少只需3个点即可估计当前的相机姿态(解不唯一)。总体来说,PnP的求解方法有P3P、直接线性变换(Direct Linear Transformation,DLT)、EPnP(Efficient PnP)和UPnP等。

CCC的专栏 2225

slam是什么意思?一文带你读懂SLAM

  SLAM是Simultaneous localization and mapping缩写,意为“同步定位与建图”,主要用于解决机器人在未知环境运动时的定位与地图构建问题,为了让大家更多的了解SLAM,以下将从SLAM的应用领域、SLAM框架、SLAM分类(基于传感器的SLAM分类)来进行全面阐述,本文仅对没有接触过SLAM的新人进行的科普。   一、SLAM的典型应用领域 机器人定位导...

SLAMTEC的博客 3万+

视觉SLAM总结——视觉SLAM十四讲笔记整理

SLAM笔记整理基础知识点1. 特征点、描述子、特征匹配相关问题 基础知识点 1. 特征点、描述子、特征匹配 这是整个SLAM系统最开始的部分,先提取特征点和描述子,然后进行特征匹配,通过匹配的特征点才求取的相关变换矩阵,这里容易搞混特征点和描述子的概念。 (1)特征点 Harris角点:就是一个根据特征小窗口在不同方向上的移动,不同的变化形式即为不同特征(角点、边界),转化到数学公式里面最后就是...

weixin_44580210的博客 8941

视觉SLAM笔记五之详解对极几何:对极约束、本质矩阵、单应矩阵

视觉SLAM笔记五之详解对极几何:对极约束、本质矩阵、单应矩阵

yohnyang的博客 2368

三维重建笔记_相机标定(相机矩阵求解)基本概念汇总

目录 1. 数学知识 1.1. 单应性矩阵 1.2. SVD(奇异值分解) 1.3.矩阵范数 ||A|| 2. 相机知识 2.1.相机模型 2.2. 相机矩阵 2.3 相机标定算法--同时标定内参外参 3. 对极几何 3.1多视几何 基本矩阵 F(Fundamental matrix) 本质矩阵 E (Essential matrix) 单位矩阵 I (Ident...

惊鸿一博 1万+

[附源码]计算机毕业设计JAVA网上花店系统

附源码]计算机毕业设计JAVA网上花店系统项目运行环境配置:(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;3.tomcat。

ssm毕设程序设计 2443

AD9361 LVDS数据接口时序解析与FPGA实现

本文详细解析了AD9361 LVDS数据接口的时序特性与FPGA实现方法,重点探讨了DATA_CLK、Rx_FRAME等关键信号的时序关系及数据拼接技巧。通过Verilog代码示例和调试经验分享,帮助开发者解决跨时钟域处理、IQ数据重组等常见问题,提升射频收发系统的稳定性与性能。

weixin_29186249的博客 128

高翔《视觉SLAM十四讲》从理论到实践

目录 第1讲前言:本书讲什么;如何使用本书; 第2讲 初始SLAM:引子-小萝卜的例子;经典视觉SLAM框架;SLAM问题的数学表述;实践-编程基础; 第3讲 三维空间刚体运动:旋转矩阵;实践-Eigen;旋转向量和欧拉角;四元数;相似、仿射、射影变换;实践-Eigen几何模块;可视化演示; 第4讲 李群与李代数:李群李代数基础;指数与对数映射;李代数求导与扰动模型;实践-Sophu...

Night___Raid的博客 4419

MMORPG网络游戏开发之任务系统的架构与设计

在网路游戏中做任务已经成为游戏很重要的一个核心功能和玩法,如何做好一个灵活可扩展的任务系统的架构与设计,今天来给大家分享一些我们的设计经验。接下来我把整个的任务系统分成以下6个模块:对于单机游戏而言,这6个模块都放在客户端直接处理,对于网路游戏而言,模块1~5实现在服务端,模块6实现在客户端。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习unity的零基础小白,也有一些正在从事unity开发的技术大佬,欢迎你来交流学习。...

voidinit的专栏 3049

SLAM——ORB特征提取、对极约束(E\F)、单应矩阵和三角测量

1.特征点法 视觉SLAM主要分为视觉前端和优化后端。前端也称为视觉里程计(VO),根据相邻图像的信息估计处粗略的相机运动,给够后端提供较好的初始值。 VO的实现方法,按是否需要提取特征,可分为特征点的前端和不提特征点的直接法前端。 VO的主要问题是如何根据图像估计相机的运动:从图像选取有代表性的点(路标),在相机发生微笑变化时会保持不变,接着从各个图片找到相同的点,进而讨论相机位姿估计问题。...

Hansry的博客 1万+

Nuvoton OpenTitan开源安全芯片技术解析与应用

硬件安全模块(HSM)作为可信计算基的核心组件,其设计透明度和可验证性正成为行业焦点。RISC-V架构凭借开源特性,为构建可审计的安全芯片提供了新范式。OpenTitan项目通过开放Verilog源码和形式化证明,实现了从物理不可克隆函数(PUF)到分层安全启动的全栈透明。该方案在lowRISC Voyager开发板上实测显示,安全启动时间小于200ms,性能损耗仅7%,显著优于传统黑盒方案。目前该技术已应用于Chromebook和数据中心,其40nm工艺版本更将功耗降至5μA待机水平,为物联网和边缘计算提

weixin_36303807的博客 397

25、BDS-3卫星信号性能与PPP-B2b增强消息完整性分析

本文对BDS-3卫星信号性能及PPP-B2b增强消息的完整性进行了系统分析。评估了MEO、IGSO和GEO卫星的轨道与时钟精度,得出BDS-3总体SISRE为0.25 m,系统完整性可覆盖99.999%的误差。分析表明SIS中断主要由时钟调整和轨道机动引起,个别卫星存在因境外监测受限导致的非计划中断。通过自研解码软件对PPP-B2b增强消息进行采集与解析,实验结果显示BDS-3和GPS的平均历元完整性率均高于98.55%,其中卫星掩码和时钟校正消息的完整性率超过99.8%。研究还发现IGSO卫星相比MEO卫

quiet的专栏 143

【slam十四讲第二版】【课本例题代码向】【第七讲~视觉里程计Ⅰ】【1OpenCV的ORB特征】【2手写ORB特征】【3对极约束求解相机运动】【4三角测量】【5求解PnP】【3D-3D:ICP】

【slam十四讲第二版】【课本例题代码向】【第七讲~视觉里程计Ⅰ】】【1OpenCV的ORB特征】【2手写ORB特征】【3对极约束求解相机运动】【4三角测量】【5求解PnP】【3D-3D:ICP】

qq_45954434的博客 8988

K-BERT: Enabling Language Representation with Knowledge Graph 代码复现 直接运行

K-BERT: Enabling Language Representation with Knowledge Graph K-BERT K-BERT 代码复现

1071

【视觉SLAM十四讲】各种库的安装及代码实践

在学习高博的《视觉SLAM十四讲》的过程中,遇到了各种问题。虽说在网上都能找到对应的解决方案,但没有一篇是详细列尽遇到的问题的文章。于是,打算自己写一篇记录学习过程中遇到的一系列问题。希望能为后续的学习提供一点帮助!(自己也是新手小白,还是有很多不懂的地方。

2302_80099075的博客 6054

华为OD技术面八股文_C++_01

汇总华为OD技术面C++方向八股文真题,并提供详细解答。

qq_45776114的博客 1884

111. 如何创建 SAP ABAP 锁对象(Lock Object)和加锁以及解锁函数

至此,我们完成了 ABAP 系统锁机制和加锁解锁函数的介绍。有了这些基础知识,大家就能在实际工作中,使用 Lock Object 和加锁解锁函数,编写出支持并发访问控制的 ABAP 应用程序了。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1532

【视觉SLAM】AirDOS: Dynamic SLAM Benefits from Articulated Objects

动态对象感知 SLAM(DOS) 利用对象级信息在动态环境中实现可靠的运动估计。现有的方法主要集中在从优化中识别和排除动态对象。在本文中,我们展示了基于特征的视觉SLAM系统也可以通过利用两个观察结果从动态铰接物体的存在中受益:(1)铰接物体的每个刚性部分的3D结构随着时间的推移保持一致;(2)同一刚性零件上的点遵循相同的运动。特别是,我们介绍了AirDOS,这是一个动态的对象感知系统,它引入了刚性和运动约束来模拟铰接对象。

振华OPPO的博客世界 2294

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

视觉SLAM前端——对极约束、本质矩阵与单应矩阵

对极几何和单应性经常运用在单目视觉SLAM初始化的时候,是求解2D/2D相机运动的常用方法。

Heathens的博客 553

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 7 讲 视觉里程计1 ( 下 )

上一篇博客我解读了如何根据已经匹配上的特征点对求解相机的运动《解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 7 讲视觉里程计1 ( 中 )》,这一篇博客我们来看一下如果通过已经求得的相机运动恢复出特征点的空间位置,以及一些别的求解相机运动的方法。 三角测量 两个图像I1,I2I_1,I_2I1​,I2​,它们之间的变换矩阵已知为T12T_{12}T12​,它们图像上分别有一个特...

一点儿也不萌的萌萌 1011

视觉SLAM十四讲学习笔记-第七讲-视觉里程计-PnP和实践

专栏汇总 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-优快云博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-优快云博客 视觉SLAM十四讲学习笔记-第二讲-开发环境搭建_goldqiu的博客-优快云博客 视觉SLAM十四讲学习笔记-第三讲-旋转矩阵和Eigen库_goldqiu的博客-优快云博客 视觉SLAM十四讲学习笔记-第三讲-旋转向量、欧拉角、四元数_goldqiu的博客-优快云博客 视觉SLAM十四讲学习笔记-第三讲-相似、仿射、..

weixin_36773706的博客 4276

《视觉SLAM十四讲 第二版》笔记及课后习题(第一讲)

前言 之所以想要写这个系列的博客,是因为想要总结一下高博的《SLAM视觉十四讲第二版》的各章内容以及自己对书后习题的一些做法,也算是对自己学习过程的一个总结和回顾。那么,正式开始! 第一讲、预备知识 SLAM 是Simultaneous Localization and Mapping 的缩写,中文译作“同时定位与地图构建”。它是指搭载特定传感器的主体,在没有环境先验信息的情况下,于运动过程中建...

weixin_43619346的博客 4457
上一篇: 视觉SLAM理论入门——(8)视觉里程计之特征点法—PnP
下一篇: 视觉SLAM实践入门——(12)三角测量
floatinglong
博客等级 码龄9年 90粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值