计算机视觉-对极几何

1 基本概念

对极几何(Epipolar Geometry)描述的是两幅视图之间的内在射影关系,与外部场景无关,只依赖于摄像机内参数和这两幅视图之间的相对位姿

两视图的对极几何可以理解为图像平面与以基线为轴的平面束相交的几何关系,其中主要有几种概念:

  • 基线(base line):两个相机中心的连线CC'称为基线
  • 对极点(epipolar):ee'是对极点,是基线与两个成像平面的交点,也就是两个相机在另一个成像平面上的像点
  • 对极平面(epipolar plane):过基线的平面都称之为对极平面,其中两个相机的中心C和C',三维点X,以及三维点在两个相机成像点xx'这五点必定在同一对极平面上,当三维点X变化时,对极平面绕着基线旋转,形成对极平面束
  • 对极线(epipolar line):是对极平面和成像平面的交线,所有的对极线都相交于极点

2 基础矩阵和本质矩阵的推导

那么由对极几何的基本性质引出了对极约束的概念,对极约束是指在平面2上的p点在平面1上的对应点一定在基线I'上,这句话说明了对极约束是一个点到直线的射影映射关系。如图所示

根据对极约束可以引出本质矩阵和基础矩阵。在已知相机标定的情况下,假设有一个三维坐标点P(X,Y,Z)在两个视图上的点分别为p1,p2,由于第一个相机的中心作为世界坐标系的原点,也就是说第一个相机没有旋转R和平移t,通过小孔相机模型有:

p1=KP, p2=K(RP+t)

其中,K是相机的内参,R,t是第二个相机相对于第一个相机的旋转和平移。

p_1=KP

P=K^{-1} p_1

带入上面式子中:

p_2=K(R K^{-1}p_1+t)

两边同时乘以K^{-1}得到:

K^{-1}p_2=RK^{-1}p_1+t

为了简化,规定:

x_1=K^{-1}p_1

x_2=K^{-1}p_2

x_2=Rx_1+t

两边同时左乘向量t的反对称矩阵t×,由于t×t=0,消除t,

t_{\times} x_2=t_{\times} R x_1

两边同时乘以x_2^T

x_2^T t_{\times} x_2=x_2^T t_{\times} R x_1

由于t_{\times} x_2  是向量t和向量x2的叉积,同时垂直于向量t和向量x2,所以左边的式子为0得到:

0=x_2^T t_{\times} R x_1

再将x_1,x_2带入上面式子中:

p_2^T K^{-T} t_{\times} R K^{-1} p_1=0

上式是对极约束的一种表示,该式子中仅包含像点,相机的旋转和平移,中间的矩阵就是基础矩阵F

F=K^{-T} t_{\times} R K^{-1}

当K已知时提取中间的矩阵得到本质矩阵E,E矩阵同样表示的是对极约束的关系,只不过它不再涉及相机内参,只由两视图之间的姿态关系决定

E=t_{\times} R

F矩阵的性质有三:

  1. 3*3且自由度为7的矩阵
  2. kF 为基础矩阵,相差一个尺度自由度
  3. F矩阵的秩为2

基础矩阵的求解方法:

  1. 直接线性变换法(8点法+最小二乘法)
  2. RANSAC-估计基础矩阵

3 基础矩阵求解方法

opencv 求解API:https://docs.opencv.org/3.4.0/d9/d0c/group__calib3d.html#ga4abc2ece9fab9398f2e560d53c8c9780

Mat cv::findFundamentalMat 	( 	InputArray  	points1,
		InputArray  	points2,
		int  	method = FM_RANSAC,
		double  	param1 = 3.,
		double  	param2 = 0.99,
		OutputArray  	mask = noArray() 
	) 	


Mat cv::findEssentialMat 	( 	InputArray  	points1,
		InputArray  	points2,
		double  	focal = 1.0,
		Point2d  	pp = Point2d(0, 0),
		int  	method = RANSAC,
		double  	prob = 0.999,
		double  	threshold = 1.0,
		OutputArray  	mask = noArray() 
	) 	

8点法求解

#include <math/matrix_svd.h>
#include "math/matrix.h"
#include "math/vector.h"

typedef math::Matrix<double, 3, 3>  FundamentalMatrix;

FundamentalMatrix fundamental_8_point (math::Matrix<double, 3, 8> const& points1
                         , math::Matrix<double, 3, 8> const& points2
                        ){

    FundamentalMatrix F;
    return F;
#if 0
    /* direct linear transform */
    math::Matrix<double, 8, 9> A;
    for(int i=0; i<8; i++)
    {
        math::Vec3d p1  = points1.col(i);
        math::Vec3d p2 = points2.col(i);

        A(i, 0) = p1[0]*p2[0];
        A(i, 1) = p1[1]*p2[0];
        A(i, 2) = p2[0];
        A(i, 3) = p1[0]*p2[1];
        A(i, 4) = p1[1]*p2[1];
        A(i, 5) = p2[1];
        A(i, 6) = p1[0];
        A(i, 7) = p1[1];
        A(i, 8) = 1.0;
    }

    math::Matrix<double, 9, 9> vv;
    math::matrix_svd<double, 8, 9>(A, nullptr, nullptr, &vv);
    math::Vector<double, 9> f = vv.col(8);

    FundamentalMatrix F;
    F(0,0) = f[0]; F(0,1) = f[1]; F(0,2) = f[2];
    F(1,0) = f[3]; F(1,1) = f[4]; F(1,2) = f[5];
    F(2,0) = f[6]; F(2,1) = f[7]; F(2,2) = f[8];

    /* singularity constraint */
    math::Matrix<double, 3, 3> U, S, V;
    math::matrix_svd(F, &U, &S, &V);
    S(2,2)=0;
    F = U*S*V.transpose();

    return F;
#endif

}

int main(int argc, char*argv[])
{
    // 第一幅图像中的对应点
    math::Matrix<double, 3, 8> pset1;
    pset1(0, 0) = 0.180123 ; pset1(1, 0)= -0.156584; pset1(2, 0)=1.0;
    pset1(0, 1) = 0.291429 ; pset1(1, 1)= 0.137662 ; pset1(2, 1)=1.0;
    pset1(0, 2) = -0.170373; pset1(1, 2)= 0.0779329; pset1(2, 2)=1.0;
    pset1(0, 3) = 0.235952 ; pset1(1, 3)= -0.164956; pset1(2, 3)=1.0;
    pset1(0, 4) = 0.142122 ; pset1(1, 4)= -0.216048; pset1(2, 4)=1.0;
    pset1(0, 5) = -0.463158; pset1(1, 5)= -0.132632; pset1(2, 5)=1.0;
    pset1(0, 6) = 0.0801864; pset1(1, 6)= 0.0236417; pset1(2, 6)=1.0;
    pset1(0, 7) = -0.179068; pset1(1, 7)= 0.0837119; pset1(2, 7)=1.0;
    //第二幅图像中的对应
    math::Matrix<double, 3, 8> pset2;
    pset2(0, 0) = 0.208264 ; pset2(1, 0)= -0.035405 ; pset2(2, 0) = 1.0;
    pset2(0, 1) = 0.314848 ; pset2(1, 1)=  0.267849 ; pset2(2, 1) = 1.0;
    pset2(0, 2) = -0.144499; pset2(1, 2)= 0.190208  ; pset2(2, 2) = 1.0;
    pset2(0, 3) = 0.264461 ; pset2(1, 3)= -0.0404422; pset2(2, 3) = 1.0;
    pset2(0, 4) = 0.171033 ; pset2(1, 4)= -0.0961747; pset2(2, 4) = 1.0;
    pset2(0, 5) = -0.427861; pset2(1, 5)= 0.00896567; pset2(2, 5) = 1.0;
    pset2(0, 6) = 0.105406 ; pset2(1, 6)= 0.140966  ; pset2(2, 6) = 1.0;
    pset2(0, 7) =  -0.15257; pset2(1, 7)= 0.19645   ; pset2(2, 7) = 1.0;

    FundamentalMatrix F = fundamental_8_point(pset1, pset2);


    std::cout<<"Fundamental matrix after singularity constraint is:\n "<<F<<std::endl;

    std::cout<<"Result should be: \n"<<"-0.0315082 -0.63238 0.16121\n"
                                     <<"0.653176 -0.0405703 0.21148\n"
                                     <<"-0.248026 -0.194965 -0.0234573\n" <<std::endl;

    return 0;
}


//Created by sway on 2018/8/29.
   /* 测试8点法求取基础矩阵F
    *
    * [直接线性变换法]
    * 双目视觉中相机之间存在对极约束
    *
    *                       p2'Fp1=0,
    *
    * 其中p1, p2 为来自两个视角的匹配对的归一化坐标,并表示成齐次坐标形式,
    * 即p1=[x1, y1, z1]', p2=[x2, y2, z2],将p1, p2的表达形式带入到
    * 上式中,可以得到如下表达形式
    *
    *          [x2] [f11, f12, f13] [x1, y1, z1]
    *          [y2] [f21, f22, f23]                = 0
    *          [z2] [f31, f32, f33]
    *
    * 进一步可以得到
    * x1*x2*f11 + x2*y1*f12 + x2*f13 + x1*y2*f21 + y1*y2*f22 + y2*f23 + x1*f31 + y1*f32 + f33=0
    *
    * 写成向量形式
    *               [x1*x2, x2*y1,x2, x1*y2, y1*y2, y2, x1, y1, 1]*f = 0,
    * 其中f=[f11, f12, f13, f21, f22, f23, f31, f32, f33]'
    *
    * 由于F无法确定尺度(up to scale, 回想一下三维重建是无法确定场景真实尺度的),因此F秩为8,
    * 这意味着至少需要8对匹配对才能求的f的解。当刚好有8对点时,称为8点法。当匹配对大于8时需要用最小二乘法进行求解
    *
    *   [x11*x12, x12*y11,x12, x11*y12, y11*y12, y12, x11, y11, 1]
    *   [x21*x22, x22*y21,x22, x21*y22, y21*y22, y22, x21, y21, 1]
    *   [x31*x32, x32*y31,x32, x31*y32, y31*y32, y32, x31, y31, 1]
    * A=[x41*x42, x42*y41,x42, x41*y42, y41*y42, y42, x41, y41, 1]
    *   [x51*x52, x52*y51,x52, x51*y52, y51*y52, y52, x51, y51, 1]
    *   [x61*x62, x62*y61,x62, x61*y62, y61*y62, y62, x61, y61, 1]
    *   [x71*x72, x72*y71,x72, x71*y72, y71*y72, y72, x71, y71, 1]
    *   [x81*x82, x82*y81,x82, x81*y22, y81*y82, y82, x81, y81, 1]
    *
    *现在任务变成了求解线性方程
    *               Af = 0
    *(该方程与min||Af||, subject to ||f||=1 等价)
    *通常的解法是对A进行SVD分解,取最小奇异值对应的奇异向量作为f分解
    *
    *本项目中对矩阵A的svd分解并获取其最小奇异值对应的奇异向量的代码为
    *   math::Matrix<double, 9, 9> V;
    *   math::matrix_svd<double, 8, 9>(A, nullptr, nullptr, &V);
    *   math::Vector<double, 9> f = V.col(8);
    *
    *
    *[奇异性约束]
    *  基础矩阵F的一个重要的性质是F是奇异的,秩为2,因此有一个奇异值为0。通过上述直接线性法求得
    *  矩阵不具有奇异性约束。常用的方法是将求得得矩阵投影到满足奇异约束得空间中。
    *  具体地,对F进行奇异值分解
    *               F = USV'
    *  其中S是对角矩阵,S=diag[sigma1, sigma2, sigma3]
    *  将sigma3设置为0,并重构F
    *                       [sigma1, 0,     ,0]
    *                 F = U [  0   , sigma2 ,0] V'
    *                       [  0   , 0      ,0]
    */

4 参考博客

基础矩阵,本质矩阵,单应性矩阵讲解 - MKT-porter - 博客园

Opencv学习(3)——基础矩阵F、本质矩阵E、单应矩阵H 函数解析_cv基础矩阵-CSDN博客

特征检测与匹配,测试8点法求取基础矩阵F(三维重建task1-3)_计算 基本矩阵 7点法和8点法 c++-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jjycheng字符签名

jjycheng字符签名--字符 jjjj jjjj hhhhhhh j::::j j::::j h:::::h …

AI大模型开发架构设计(14)——基于LangChain大模型的案例架构实战

文章目录 基于LangChain大模型的案例架构实战1 LangChain 顶层架构设计以及关键技术剖析LangChain 是什么?LangChain的主要功能是什么&#xff1f;LangChain 顶层架构设计LangChain 典型使用场景&#xff1a;QA 问答系统LangChain 顶层架构设计之 Model I/OLangChain 顶层架构…

Ubuntu下安装和配置MySQL5.7教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 在ubuntu下安装MySQL数据库 查看操作系统版本 ​编辑 添加 MySQL APT 源 访问下载页面并下载发布包 安装发布包 安装MySQL 查看MySQL状态 开启自启动 登…

设计模式4-工厂模式策略模式

目录 一 工厂模式 1.1 思想 1.2 案例 1.2.1 接口 1.2.2 实现类 1.2.3 工厂类 1.2.4 调用 二 策略模式 2.1 思想 2.2 案例 2.2.1 接口 2.2.2 实现类 2.2.3 策略类 2.2.4 调用 三 工厂模式策略模式 3.1 思想 3.2 案例 3.2.1 接口 3.2.2 实现类 3.2.3 定义F…

【HTML】之form表单元素详解

HTML表单是网页与用户交互的关键组成部分&#xff0c;它允许用户输入数据并将数据提交到服务器进行处理。本文将全面详细地介绍HTML表单的各个方面&#xff0c;从基础元素到高级用法&#xff0c;并提供丰富的代码示例和中文注释&#xff0c;帮助你彻底掌握表单的使用。 1. 表单…

shodan5,参数使用,批量查找Mongodb未授权登录,jenkins批量挖掘

查找美国安全局漏洞 nww.nsa.gov&#xff08;美国安全局官方网站) net参数使用 搜索指定的ip网段 shodan search --limit 10 --fields ip_str,port net:208.88.84.0/24 (老美国家安全局的一个网段)可能直接访问不太行&#xff0c;可以使用host参数&#xff0c;得到域名再去…

【Unity基础】初识UI Toolkit - 编辑器UI

&#xff08;本文所需图片在文章上面的资源中&#xff0c;点击“立即下载”。&#xff09; 本文介绍了如何通过UI工具包&#xff08;UI Toolkit&#xff09;来创建一个编辑器UI。 一、创建项目 1. 打开Unity创建一个空项目&#xff08;任意模板&#xff09;&#xff0c;这里我…

NVR小程序接入平台/设备EasyNVR多个NVR同时管理多平台级联与上下级对接的高效应用

政务数据共享平台的建设正致力于消除“信息孤岛”现象&#xff0c;打破“数据烟囱”&#xff0c;实现国家、省、市及区县数据的全面对接与共享。省市平台的“级联对接”工作由多级平台共同构成&#xff0c;旨在满足跨部门、跨层级及跨省数据共享的需求&#xff0c;推动数据流通…

Android 获取OAID

获取OAID 老规矩&#xff0c;直接上&#xff1a; implementation com.huawei.hms:opendevice:6.11.0.300 // 要获取华为vaid 和aaid&#xff0c;还需添加opendevice 依赖implementation(name: oaid_sdk_2.5.0, ext: aar) import android.content.Context; import android.util.…

Flume采集Kafka数据到Hive

版本&#xff1a; Kafka&#xff1a;2.4.1 Flume&#xff1a;1.9.0 Hive&#xff1a;3.1.0 Kafka主题准备&#xff1a; Hive表准备&#xff1a;确保hive表为&#xff1a;分区分桶、orc存储、开启事务 Flume准备&#xff1a; 配置flume文件&#xff1a; /opt/datasophon/flume-1…

还在担心你收藏的书签下架或失效?试试这款自托管书签管理器『Linkwarden』吧!

还在担心你收藏的书签下架或失效&#xff1f;试试这款自托管书签管理器『Linkwarden』吧&#xff01; 哈喽&#xff0c;小伙伴儿们好&#xff0c;我是Stark-C~ 随着大家在网上收藏的浏览器书签越来越多&#xff0c;难免会导致管理混乱的问题。可能会在我们需要的时候难以找到…

MySQL与金蝶云星空数据集成,实现生产用料清单自动刷新

MySQL数据集成到金蝶云星空&#xff1a;zz-生产用料清单主动刷新 在企业的日常运营中&#xff0c;数据的及时性和准确性至关重要。为了实现MySQL数据库与金蝶云星空系统之间的数据无缝对接&#xff0c;我们设计并实施了一个名为“zz-生产用料清单主动刷新”的集成方案。本案例…

八,Linux基础环境搭建(CentOS7)- 安装Mysql和Hive

Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Mysql和Hive 大家注意以下的环境搭建版本号&#xff0c;如果版本不匹配有可能出现问题&#xff01; 一、Mysql下载及安装 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Orac…

计算机毕业设计Python+大模型恶意木马流量检测与分类 恶意流量监测 随机森林模型 深度学习 机器学习 数据可视化 大数据毕业设计 信息安全 网络安全

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; Python大模型恶意木马流量检…

Conditional DETR论文笔记

原文链接 [2108.06152] Conditional DETR for Fast Training Convergencehttps://arxiv.org/abs/2108.06152 原文笔记 What 《Conditional DETR for Fast Training Convergence》 这个工作也是针对于DETR Query的工作 用于解决DETR训练收敛慢&#xff08;Object query需要…

LoRA微调,真的有毒!

本文介绍一篇相当有意思的文章&#xff0c;该文章的内容对我们使用指令微调将预训练模型改造为 Chat 模型和下游专业模型相当有指导意义。 本文的标题听起来有些唬人&#xff0c;有些标题党&#xff0c;但是这个论点在一定的限定条件下是成立的&#xff0c;笔者归纳为&#xf…

Qt——信号和槽

一.信号和槽概述 谈及信号&#xff0c;很容易联想到在Linux系统中所分享到的信号。那么Linux信号和Qt信息有什么不同&#xff1f; 在 Qt 中&#xff0c;用户和控件的每次交互过程称为⼀个事件。比如 "用户点击按钮" 是⼀个事件&#xff0c;"用户关 闭窗口&quo…

Nginx反向代理(下)

1. WebSocket的反向代理 WebSocket 是目前比较成熟的技术了, WebSocket 协议为创建客户端和服务器端需要实时双向通讯的 webapp 提供了一个选择。服务器可以向浏览器推送相关消息&#xff0c;这样在前端实现的某个页面中我们可以及时看到服务器的状态变化而不用使用定时刷新去…

2024年10月中国数据库排行榜:TiDB续探花,GaussDB升四强

10月中国数据库流行度排行榜如期发布&#xff0c;再次印证了市场分层的加速形成。国家数据库测评结果已然揭晓&#xff0c;本批次通过的产品数量有限&#xff0c;凸显了行业标准的严格与技术门槛的提升。再看排行榜&#xff0c;得分差距明显增大&#xff0c;第三名与后续竞争者…

【C++】RBTree——红黑树

文章目录 一、红黑树的概念1.1 红⿊树的规则&#xff1a;1.2 理解最长路径长度不超过最短路径长度的 2 倍1.3 红⿊树的效率 二、 红⿊树的实现2.1 红⿊树的结构2.2 红⿊树的插⼊2.2.1 红⿊树树插⼊⼀个值的⼤概过程 2.3 红⿊树的插⼊代码实现 一、红黑树的概念 红⿊树是⼀棵⼆…