三角测量法恢复深度

参考:单目vo中的深度确定方法--三角测量_单目相机三角测量-CSDN博客

方法一:直接法

由于我们已经通过本质矩阵分解或者单应矩阵分解获得了Rt,此时想求的是两个特征点的深度

bool depthFromTriangulation(const SE3& T_search_ref,const Vector3d& f_ref,const Vector3d& f_cur,double& depth)
{Matrix<double,3,2> A;A << T_search_ref.rotation_matrix()*f_ref, f_cur;const Matrix2d AtA = A.transpose()*A;if(AtA.determinant() < 0.000001)return false;const Vector2d depth2 = - AtA.inverse()*A.transpose()*T_search_ref.translation();depth = fabs(depth2[0]);return true;
}

方法二:Cramer法则

    // 方程// d_ref * f_ref = d_cur * ( R_RC * f_cur ) + t_RC// => [ f_ref^T f_ref, -f_ref^T f_cur ] [d_ref] = [f_ref^T t]//    [ f_cur^T f_ref, -f_cur^T f_cur ] [d_cur] = [f_cur^T t]// 二阶方程用克莱默法则求解并解之Vector3d t = T_R_C.translation();Vector3d f2 = T_R_C.rotation_matrix() * f_curr; Vector2d b = Vector2d ( t.dot ( f_ref ), t.dot ( f2 ) );// 此处计算出系数矩阵Adouble A[4];A[0] = f_ref.dot ( f_ref );A[2] = f_ref.dot ( f2 );A[1] = -A[2];A[3] = - f2.dot ( f2 );// 此处计算A的行列式double d = A[0]*A[3]-A[1]*A[2];Vector2d lambdavec = Vector2d (  A[3] * b ( 0,0 ) - A[1] * b ( 1,0 ),-A[2] * b ( 0,0 ) + A[0] * b ( 1,0 )) /d;Vector3d xm = lambdavec ( 0,0 ) * f_ref;Vector3d xn = t + lambdavec ( 1,0 ) * f2;Vector3d d_esti = ( xm+xn ) / 2.0;  // 三角化算得的深度向量double depth_estimation = d_esti.norm();   // 深度值

方法三:OpenCV接口 同方法二

void triangulation ( const vector< KeyPoint >& keypoint_1, const vector< KeyPoint >& keypoint_2, const std::vector< DMatch >& matches,const Mat& R, const Mat& t, vector< Point3d >& points )
{//相机第一个位置处的位姿Mat T1 = (Mat_<float> (3,4) <<1,0,0,0,0,1,0,0,0,0,1,0);//相机第二个位置处的位姿Mat T2 = (Mat_<float> (3,4) <<R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2), t.at<double>(0,0),R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2), t.at<double>(1,0),R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2), t.at<double>(2,0));// 相机内参Mat K = ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );vector<Point2f> pts_1, pts_2;for ( DMatch m:matches ){// 将像素坐标转换至相机平面坐标,为什么要这一步,上面推导中有讲pts_1.push_back ( pixel2cam( keypoint_1[m.queryIdx].pt, K) );pts_2.push_back ( pixel2cam( keypoint_2[m.trainIdx].pt, K) );}Mat pts_4d;//opencv提供的三角测量函数cv::triangulatePoints( T1, T2, pts_1, pts_2, pts_4d );// 转换成非齐次坐标for ( int i=0; i<pts_4d.cols; i++ ){Mat x = pts_4d.col(i);x /= x.at<float>(3,0); // 归一化Point3d p (x.at<float>(0,0), x.at<float>(1,0), x.at<float>(2,0) );points.push_back( p );}
}Point2f pixel2cam ( const Point2d& p, const Mat& K )
{return Point2f(( p.x - K.at<double>(0,2) ) / K.at<double>(0,0), ( p.y - K.at<double>(1,2) ) / K.at<double>(1,1) );
}

方法四:最小二乘法

// vins中初始化sfm时根据一个三维点在两帧中的投影位置确定三维点位置
void GlobalSFM::triangulatePoint(Eigen::Matrix<double, 3, 4> &Pose0, Eigen::Matrix<double, 3, 4> &Pose1,Vector2d &point0, Vector2d &point1, Vector3d &point_3d)
{Matrix4d design_matrix = Matrix4d::Zero();design_matrix.row(0) = point0[0] * Pose0.row(2) - Pose0.row(0);design_matrix.row(1) = point0[1] * Pose0.row(2) - Pose0.row(1);design_matrix.row(2) = point1[0] * Pose1.row(2) - Pose1.row(0);design_matrix.row(3) = point1[1] * Pose1.row(2) - Pose1.row(1);Vector4d triangulated_point;triangulated_point =design_matrix.jacobiSvd(Eigen::ComputeFullV).matrixV().rightCols<1>();point_3d(0) = triangulated_point(0) / triangulated_point(3);point_3d(1) = triangulated_point(1) / triangulated_point(3);point_3d(2) = triangulated_point(2) / triangulated_point(3);
}

方法五:概率法

测量值是符合正态分布的,噪声符合均匀分布,此时我们可以通过一些概率的方法对多次测量结果进行融合,得到更鲁棒的结果。

  • 在SVO中,使用贝叶斯方法(最大后验概率)进行更新

  • 在LSD中,使用卡尔曼滤波进行深度测量值的滤波

    参考:lsd-slam深度滤波器-CSDN博客

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

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

相关文章

电脑开机提示“no bootable device”,无法进入系统

当您的Windows 10电脑开机时提示“no bootable device”,这意味着计算机无法找到一个可以启动操作系统的设备。这个问题通常与硬件连接、BIOS设置、硬盘问题、引导扇区故障或系统文件损坏等有关。以下是一系列详细的解决步骤: 检查硬件连接:关闭电脑,拔掉电源线,打开机箱检…

如何创建Windows下google Chrome便携版?

创建google Chrome便携版教程 准备工作&#xff1a; 1&#xff0c;下载GoogleChromePortable启动器 2&#xff0c;下载谷歌浏览器 3&#xff0c;下载7-ZIP 解压提取器 用7zip解压GoogleChromePortable&#xff0c;得到GoogleChromePortable.exe启动器 解压谷歌浏览器 用7…

Java入门基础day29

day29 内部类 分类 非静态成员内部类 静态成员内部类 局部内部类 匿名内部类 概念 在一个类的内部&#xff0c;再定义一个完整的类 特点&#xff1a; 编译之后可以生成一个独立的字节码class文件 内部类可以直接访问外部类的私有成员&#xff0c;而不会破坏其封装性 可以为外…

Flutter之TabBar篇

总结了一下项目中用到的几种TabBar&#xff0c;针对不同的样式&#xff0c;有采用系统提供的&#xff0c;也有三方插件提供的&#xff0c;也有自定义的&#xff0c;效果如下&#xff08;后续如果遇到新的样式&#xff0c;会不间断地记录更新&#xff0c;避免重复造轮子…&#…

性能分析-数据库与磁盘知识

数据库 数据库&#xff0c;其实是数据库管理系统dbms。 数据库管理系统&#xff0c; 常见&#xff1a; 关系型数据库&#xff1a; mysql、pg、 库的表&#xff0c;表与表之间有关联关系&#xff1b; 表二维表统一标准的SQL&#xff08;不局限于CRUD&#xff09;非关系型数据…

ssm034学生请假系统+jsp

学生请假系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本学生请假系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处…

C++11 新特性:std::array

std::array是 C11 中引入的容器类型&#xff0c;它封装了固定大小的数组&#xff0c;提供了类似于 STL 容器的接口&#xff0c;同时保持了 C 风格数组的性能特性。 与普通数组相比&#xff0c;std::array更安全、更易于使用&#xff0c;并且支持迭代器。以下是std::array提供的…

-webkit-input-placeholder的意思

-webkit-input-placeholder是一个CSS伪类选择器&#xff0c;用于设置表单输入字段的占位文本样式。-webkit-input-placeholder是Webkit浏览器私有的前缀&#xff0c;用于适用于Webkit内核的浏览器&#xff08;如Chrome和Safari&#xff09;。 使用-webkit-input-placeholder&a…

鸿蒙HarmonyOS开发实例:【简单时钟】

简单时钟 介绍 本示例通过使用[ohos.display]接口以及Canvas组件来实现一个简单的时钟应用。 效果预览 主页 使用说明 1.界面通过setInterval实现周期性实时刷新时间&#xff0c;使用Canvas绘制时钟&#xff0c;指针旋转角度通过计算得出。 例如&#xff1a;"2 * M…

Microsoft Visio 参与者 [actor] - 人的形状图标

Microsoft Visio 参与者 [actor] - 人的形状图标 1. 更多形状 -> 搜索形状2. 参与者References 1. 更多形状 -> 搜索形状 2. 参与者 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

网络入门基础:从概念到实践

导言 网络已经成为了我们日常生活和工作中不可或缺的一部分&#xff0c;无论是用于沟通、学习、娱乐还是商务交易&#xff0c;网络都扮演着至关重要的角色。本文将介绍网络的基础知识&#xff0c;从概念到实践&#xff0c;帮助初学者了解网络的基本原理和构成&#xff0c;以便…

【简单讲解下如何Java中文乱码浅析及解决方案】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

力扣经典150题(1)

文章目录 6.Z字形变换82.删除排序链表中的重复元素||61.旋转链表100.相同的树 6.Z字形变换 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1…

Spring循环依赖

Java开发常见面试题详解&#xff08;LockSupport&#xff0c;AQS&#xff0c;Spring循环依赖&#xff0c;Redis&#xff09;_java 常见面试题详解(locksupport-CSDN博客 循环依赖现象在spring容器中注入依赖的对象&#xff0c;有2种情况 构造器方式注入依赖&#xff08;不可行…

如何在HarmonyOS(鸿蒙操作系统)上进行应用开发

文章中提到的关键点包括&#xff1a; 学习ArkTS&#xff1a;作者建议初学者首先学习使用ArkTS编写Hello World程序&#xff0c;并可以通过TypeScript教程来快速掌握基础语法。对于有Flutter或React Native开发经验的开发者来说&#xff0c;页面布局会比较容易上手。 页面布局&…

基于遗传优化的SVD水印嵌入提取算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化的的SVD水印嵌入提取算法。对比遗传优化前后SVD水印提取性能&#xff0c;并分析不同干扰情况下水印提取效果。 2.测试软件版本以及运行结果展示 MA…

18、差分

差分 题目描述 输入一个长度为n的整数序列。 接下来输入m个操作&#xff0c;每个操作包含三个整数l, r, c&#xff0c;表示将序列中[l, r]之间的每个数加上c。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两个整数n和m。 第二行包含n个整数&#xff0c;表示整…

根据mysql的执行顺序来写select

过滤顺序指的是mysql的逻辑执行顺序&#xff0c;个人觉得我们可以按照执行顺序来写select查询语句。 目录 一、执行顺序二、小tips三、案例第一轮查询&#xff1a;统计每个num的出现次数第二轮查询&#xff1a;计算**最多次数**第三轮查询&#xff1a;找到所有出现次数为最多次…

图片地址生成二维码(通过前端实现)

文章目录 概要安装插件代码实例 概要 要将图片地址生成二维码&#xff0c;你可以使用 QrCode 库&#xff08;假设你已经在项目中引入了该库&#xff09;。以下是一个简单的示例代码&#xff0c;演示了如何使用 QrCode 库将图片地址转换为二维码并显示在页面上 安装插件 先下载…

Linux使用宝塔面板安装MySQL结合内网穿透实现公网连接本地数据库

文章目录 推荐前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…