当前位置: 首页 > news >正文

【Opencv】三维重建之cv::recoverPose()函数(1)

官网链接

从估计的本质矩阵和两幅图像中的对应点恢复相机之间的旋转和平移,使用光束法则进行检验。返回通过检验的内点数目。

#include <opencv2/calib3d.hpp>

int cv::recoverPose	(	InputArray 	E,
InputArray 	points1,
InputArray 	points2,
InputArray 	cameraMatrix,
OutputArray 	R,
OutputArray 	t,
InputOutputArray 	mask = noArray() 
)	
int recoverPose( InputArray E, InputArray points1, InputArray points2,OutputArray R, OutputArray t, double focal = 1.0,Point2d pp = Point2d(0, 0), InputOutputArray mask = noArray() );
int recoverPose( InputArray E, InputArray points1, InputArray points2,InputArray cameraMatrix, OutputArray R, OutputArray t, double distanceThresh, InputOutputArray mask = noArray(),OutputArray triangulatedPoints = noArray());

E:已经求解出来的本质矩阵,它是3x3的矩阵;
  points1:第一张图片中的点;
  points2:第二张图片中的点;
  cameraMatrix:相机内参矩阵,它是3x3的矩阵;
  R:求解出来的两帧图片之间的旋转矩阵;
  t:求解出来的两帧图片之间的平移向量;
  focal:相机焦距;
  pp:像素坐标的原点;
  distanceThresh:点的距离阈值,用来滤出距离较远的点;
  triangulatedPoints:通过三角化还原点;

官方例子

// Example. Estimation of fundamental matrix using the RANSAC algorithm
int point_count = 100;
vector<Point2f> points1(point_count);
vector<Point2f> points2(point_count);
// initialize the points here ...
for( int i = 0; i < point_count; i++ )
{points1[i] = ...;points2[i] = ...;
}
// cametra matrix with both focal lengths = 1, and principal point = (0, 0)
Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
Mat E, R, t, mask;
E = findEssentialMat(points1, points2, cameraMatrix, RANSAC, 0.999, 1.0, mask);
recoverPose(E, points1, points2, cameraMatrix, R, t, mask);

**说明: **
  1. 通过该函数求解出来的 R , t R,t R,t ,它表示的是points1到points2的变换,也就是 R 21 R_{21} R21 , t 21 t_{21} t21
  2.该函数求解出来的 R 21 R_{21} R21 , t 21 t_{21} t21,已经是最合适已经通过内部的代码去掉了另外三种错误的解
  3. cv::recoverPose()中points1和points2的输入顺序,必须也要和求本质矩阵时对函数cv::findEssentialMat()输入的顺序相同。
  4. 使用方法,可以直接包含对应的头文件,也可以直接将函数的内部实现拷贝也可以自己实现(vins),如下:

    int recoverPose( InputArray E, InputArray _points1, InputArray _points2, InputArray _cameraMatrix,OutputArray _R, OutputArray _t, InputOutputArray _mask){Mat points1, points2, cameraMatrix;_points1.getMat().convertTo(points1, CV_64F);_points2.getMat().convertTo(points2, CV_64F);_cameraMatrix.getMat().convertTo(cameraMatrix, CV_64F);int npoints = points1.checkVector(2);CV_Assert( npoints >= 0 && points2.checkVector(2) == npoints &&points1.type() == points2.type());CV_Assert(cameraMatrix.rows == 3 && cameraMatrix.cols == 3 && cameraMatrix.channels() == 1);if (points1.channels() > 1){points1 = points1.reshape(1, npoints);points2 = points2.reshape(1, npoints);}double fx = cameraMatrix.at<double>(0,0);double fy = cameraMatrix.at<double>(1,1);double cx = cameraMatrix.at<double>(0,2);double cy = cameraMatrix.at<double>(1,2);points1.col(0) = (points1.col(0) - cx) / fx;points2.col(0) = (points2.col(0) - cx) / fx;points1.col(1) = (points1.col(1) - cy) / fy;points2.col(1) = (points2.col(1) - cy) / fy;points1 = points1.t();points2 = points2.t();Mat R1, R2, t;decomposeEssentialMat(E, R1, R2, t);Mat P0 = Mat::eye(3, 4, R1.type());Mat P1(3, 4, R1.type()), P2(3, 4, R1.type()), P3(3, 4, R1.type()), P4(3, 4, R1.type());P1(Range::all(), Range(0, 3)) = R1 * 1.0; P1.col(3) = t * 1.0;P2(Range::all(), Range(0, 3)) = R2 * 1.0; P2.col(3) = t * 1.0;P3(Range::all(), Range(0, 3)) = R1 * 1.0; P3.col(3) = -t * 1.0;P4(Range::all(), Range(0, 3)) = R2 * 1.0; P4.col(3) = -t * 1.0;// Do the cheirality check.// Notice here a threshold dist is used to filter// out far away points (i.e. infinite points) since// there depth may vary between postive and negtive.double dist = 50.0;Mat Q;triangulatePoints(P0, P1, points1, points2, Q);Mat mask1 = Q.row(2).mul(Q.row(3)) > 0;Q.row(0) /= Q.row(3);Q.row(1) /= Q.row(3);Q.row(2) /= Q.row(3);Q.row(3) /= Q.row(3);mask1 = (Q.row(2) < dist) & mask1;Q = P1 * Q;mask1 = (Q.row(2) > 0) & mask1;mask1 = (Q.row(2) < dist) & mask1;triangulatePoints(P0, P2, points1, points2, Q);Mat mask2 = Q.row(2).mul(Q.row(3)) > 0;Q.row(0) /= Q.row(3);Q.row(1) /= Q.row(3);Q.row(2) /= Q.row(3);Q.row(3) /= Q.row(3);mask2 = (Q.row(2) < dist) & mask2;Q = P2 * Q;mask2 = (Q.row(2) > 0) & mask2;mask2 = (Q.row(2) < dist) & mask2;triangulatePoints(P0, P3, points1, points2, Q);Mat mask3 = Q.row(2).mul(Q.row(3)) > 0;Q.row(0) /= Q.row(3);Q.row(1) /= Q.row(3);Q.row(2) /= Q.row(3);Q.row(3) /= Q.row(3);mask3 = (Q.row(2) < dist) & mask3;Q = P3 * Q;mask3 = (Q.row(2) > 0) & mask3;mask3 = (Q.row(2) < dist) & mask3;triangulatePoints(P0, P4, points1, points2, Q);Mat mask4 = Q.row(2).mul(Q.row(3)) > 0;Q.row(0) /= Q.row(3);Q.row(1) /= Q.row(3);Q.row(2) /= Q.row(3);Q.row(3) /= Q.row(3);mask4 = (Q.row(2) < dist) & mask4;Q = P4 * Q;mask4 = (Q.row(2) > 0) & mask4;mask4 = (Q.row(2) < dist) & mask4;mask1 = mask1.t();mask2 = mask2.t();mask3 = mask3.t();mask4 = mask4.t();// If _mask is given, then use it to filter outliers.if (!_mask.empty()){Mat mask = _mask.getMat();CV_Assert(mask.size() == mask1.size());bitwise_and(mask, mask1, mask1);bitwise_and(mask, mask2, mask2);bitwise_and(mask, mask3, mask3);bitwise_and(mask, mask4, mask4);}if (_mask.empty() && _mask.needed()){_mask.create(mask1.size(), CV_8U);}CV_Assert(_R.needed() && _t.needed());_R.create(3, 3, R1.type());_t.create(3, 1, t.type());int good1 = countNonZero(mask1);int good2 = countNonZero(mask2);int good3 = countNonZero(mask3);int good4 = countNonZero(mask4);if (good1 >= good2 && good1 >= good3 && good1 >= good4){R1.copyTo(_R);t.copyTo(_t);if (_mask.needed()) mask1.copyTo(_mask);return good1;}else if (good2 >= good1 && good2 >= good3 && good2 >= good4){R2.copyTo(_R);t.copyTo(_t);if (_mask.needed()) mask2.copyTo(_mask);return good2;}else if (good3 >= good1 && good3 >= good2 && good3 >= good4){t = -t;R1.copyTo(_R);t.copyTo(_t);if (_mask.needed()) mask3.copyTo(_mask);return good3;}else{t = -t;R2.copyTo(_R);t.copyTo(_t);if (_mask.needed()) mask4.copyTo(_mask);return good4;}}int recoverPose( InputArray E, InputArray _points1, InputArray _points2, OutputArray _R,OutputArray _t, double focal, Point2d pp, InputOutputArray _mask){Mat cameraMatrix = (Mat_<double>(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1);return cv::recoverPose(E, _points1, _points2, cameraMatrix, _R, _t, _mask);}
}

相关文章:

【Opencv】三维重建之cv::recoverPose()函数(1)

官网链接 从估计的本质矩阵和两幅图像中的对应点恢复相机之间的旋转和平移&#xff0c;使用光束法则进行检验。返回通过检验的内点数目。 #include <opencv2/calib3d.hpp>int cv::recoverPose ( InputArray E, InputArray points1, InputArray points2, InputArray …...

Perl兼容正则表达式函数-PHP8知识详解

在php8中有两类正则表达式函数&#xff0c;一类是perl兼容正则表达式函数&#xff0c;另一类是posix扩展正则表达式函数。二者区别不大&#xff0c;我们推荐使用Perl兼容正则表达式函数。 1、使用正则表达式对字符串进行匹配 用正则表达式对目标字符串进行匹配是正则表达式的主…...

Python处理空值NaN

fork_address_tempread_excel_column_to_list(./eqp_info.xls,Sheet1,车辆地址)for i in fork_address_temp:print(type(i))fork_address[0 if address nan else address for address in fork_address_temp]fork_address结果 <class float><class float><class…...

软件机器人助力交通运输局数据录入,实现高效管理

随着科技的迅速发展&#xff0c;许多传统的行业正在寻求通过科技创新优化工作流程、提升效率。在这样的大背景下&#xff0c;交通运输部门也开始注重引入科技手段改善工作流程。博为小帮软件机器人正逐步改变着交通运输局的工作方式。 软件机器人&#xff1a;交通管理的利器 博…...

时序分解 | MATLAB实现基于SGMD辛几何模态分解的信号分解分量可视化

时序分解 | MATLAB实现基于SGMD辛几何模态分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于SGMD辛几何模态分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SGMD分解算法&#xff08;辛几何模态分解&#xff09;&#xff0c;分解结果可视…...

FinalShell报错:Swap file “.docker-compose.yml.swp“ already exists

FinalShell中编辑docker-compose.yml文件&#xff0c;保存时报错&#xff1a;Swap file ".docker-compose.yml.swp" already exists&#xff1b;报错信息截图如下&#xff1a; 问题原因&#xff1a;有人正在编辑docker-compose.yml文件或者上次编辑没有保存&#xff…...

卷积过程详细讲解

1&#xff1a;单通道卷积 以单通道卷积为例&#xff0c;输入为&#xff08;1,5,5&#xff09;&#xff0c;分别表示1个通道&#xff0c;宽为5&#xff0c;高为5。假设卷积核大小为3x3&#xff0c;padding0&#xff0c;stride1。 卷积过程如下&#xff1a; 相应的卷积核不断…...

代码随想录第五十六天

代码随想录第五十六天 Leetcode 583. 两个字符串的删除操作Leetcode 72. 编辑距离 Leetcode 583. 两个字符串的删除操作 题目链接: 两个字符串的删除操作 自己的思路:想到了&#xff0c;但是初始化初始错了&#xff01;&#xff01;&#xff01;&#xff01; 思路1:直接动规五…...

.NET 最便捷的Log4Net日志记录器

最便捷的Log4Net使用方法 LOG4NET 配置日志记录器开始引用nuget LOG4NET 配置日志记录器 Apache log4net 库是一个帮助程序员将日志语句输出到各种的工具 的输出目标。log4net是优秀的Apachelog4j™框架的移植 Microsoft.NET 运行时。我们保持了与原始log4j相似的框架 同时利…...

深入探讨软件逆向工程:解密黑盒的奥秘

引言 逆向工程作为计算机科学领域中的一项关键技术&#xff0c;扮演着解密、漏洞分析、反病毒等诸多领域的重要角色。本文将深入探讨逆向工程的概念、应用领域以及一些常用的逆向工程技术。 什么是逆向工程&#xff1f; 逆向工程是指通过分析已有的程序或设备&#xff0c;推…...

利用tidevice+mysql+grafana实现ios性能测试

利用tidevicemysqlgrafana实现ios性能测试 1.什么是tidevice&#xff1f; tidevice是一个可以和ios设备进行通信的工具&#xff0c;提供以下功能&#xff1a; 截图获取手机信息ipa包的安装和卸载根据bundleID 启动和停止应用列出安装应用信息模拟Xcode运行XCTest&#xff0c…...

内网安全:WMI协议与SMB协议横向移动

目录 网络拓扑图 网络环境说明 WMI协议 SMB协议 域内信息收集 WMI协议 - 横向移动 利用方式一&#xff1a;wmic命令 利用方式一&#xff1a;cscript 利用方式一&#xff1a;impacket SMB协议 - 横向移动 利用方式一&#xff1a;psexec 利用方式二&#xff1a;psexe…...

05-Numpy基础-用于数组的文件输入输出

np.save和np.load是读写磁盘数组数据的两个主要函数。默认情况下&#xff0c;数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中的&#xff1a; 如果文件路径末尾没有扩展名.npy&#xff0c;则该扩展名会被自动加上。然后就可以通过np.load读取磁盘上的数组&#xff1…...

Docker微服务实战

文章目录 业务需求IDEA编写代码编写Dockerfile构建镜像运行容器网页端访问测试 业务需求 利用Docker部署应用服务&#xff0c;实现在网页端通过输入地址 ip:端口/hello/docker&#xff0c;页面显示hello docker ! IDEA编写代码 创建springboot项目 网上很多教程,此步骤省略……...

NLNet论文总结和代码实现

Non-local Neural Networks&#xff08;非局部神经网络&#xff09;&#xff1a;使用自注意力机制捕获远程依赖。 论文&#xff1a; https://arxiv.org/pdf/1711.07971.pdf 源码&#xff1a; 长距离依赖关系&#xff0c;顾名思义&#xff0c;是要和远程建立关系&#xff0c;在l…...

数字 IC 设计职位经典笔/面试题(三)

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 1. IC 设计中同步复位与异步复位的区别&#xff1f; 同步复位在时钟沿变化时&#xff0c;完成复位动作。异步复位不管时钟&#xff0c;只要复位信号满足条件&#xff0c;就完成复位动作。异步复位对复位信号要求…...

Matlab分割彩色图像

彩色图像 彩色图像除有亮度信息外&#xff0c;还包含有颜色信息。以最常见的RGB&#xff08;红绿蓝&#xff09;彩色空间为例来简要说明彩色图像&#xff1a; 彩色图像可按照颜色的数目来划分。例如&#xff0c;256色图像和真彩色图像&#xff08;2的16次方&#xff1d;21677…...

[数据集][目标检测]垃圾目标检测数据集VOC格式14963张44类别

数据集格式&#xff1a;Pascal VOC格式(不包含分割的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;14963 标注数量(xml文件个数)&#xff1a;14963 标注类别数&#xff1a;44 标注类别名称:["toiletries","plastic utensi…...

MATLAB算法实战应用案例精讲-【深度学习】推荐系统模型DSSMDeepFM

目录 前言 DSSM 输入层 英文 中文 表示层 匹配层 优缺点 DeepFM模...

基于springboot的社区生活缴费系统/基于javaweb的水电缴费系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把社区生活缴费管理与现在网络相结合&#xff0c;利用java语言建设社区生活缴费系统&#xff0c;实现社区生活缴费管理的信息化。则对于进一步提高社区生活缴费管理发展&#xff0c;丰富社区生活缴费管理经验能起到不少的促进…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...