OpenCV相机标定与3D重建(35)计算两幅图像之间本质矩阵(Essential Matrix)的函数findEssentialMat()的使用

news2024/12/28 17:21:44
  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

从两幅图像中的对应点计算本质矩阵。
cv::findEssentialMat 是 OpenCV 库中用于计算两幅图像之间本质矩阵(Essential Matrix)的函数。本质矩阵描述了两个校准过的摄像机之间的相对旋转和平移,它对于立体视觉、运动结构恢复(Structure from Motion, SfM)和视觉里程计(Visual Odometry)等计算机视觉任务非常重要。

函数原型1


Mat cv::findEssentialMat	
(
	InputArray 	points1,
	InputArray 	points2,
	InputArray 	cameraMatrix,
	int 	method = RANSAC,
	double 	prob = 0.999,
	double 	threshold = 1.0,
	int 	maxIters = 1000,
	OutputArray 	mask = noArray() 
)		

参数1

  • 参数points1:来自第一幅图像的 N (N >= 5) 个2D点数组。点的坐标应该是浮点数(单精度或双精度)。
  • 参数points2:第二幅图像的点数组,与 points1 具有相同的大小和格式。
  • 参数cameraMatrix:相机内参矩阵 A = [ f x 0 c x 0 f y c y 0 0 1 ] A = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} A= fx000fy0cxcy1 。注意,此函数假设 points1 和 points2 是来自具有相同内参矩阵的相机的特征点。如果这个假设在你的应用场景中不成立,可以使用 undistortPoints 函数,并为两个相机设置 P=cv::NoArray(),以将图像点转换为适用于单位内参矩阵的归一化图像坐标。当传递这些坐标时,对于此参数应传递单位矩阵。
  • 参数method:计算本质矩阵的方法。
    • RANSAC:用于RANSAC算法。
    • LMEDS:用于最小中值法(LMedS)算法。
  • 参数 prob:仅用于RANSAC或LMedS方法的参数。它指定了估计矩阵正确的期望置信水平(概率)。
  • 参数threshold:仅用于RANSAC方法的参数。它是点到极线的最大距离(以像素为单位),超过该距离的点被认为是离群点,并不用于计算最终的本质矩阵。根据点定位的准确性、图像分辨率和图像噪声,它可以设置为1-3等。
  • 参数mask:输出数组,包含N个元素,每个元素对于离群点设置为0,对于其他点设置为1。该数组仅在RANSAC和LMedS方法中计算。
  • 参数maxIters:稳健方法的最大迭代次数。
    该函数基于五点算法求解器估算本质矩阵。[204] 中描述了该算法,[247] 也与此相关。极几何由以下方程描述:

[ p 2 ; 1 ] T K − T E K − 1 [ p 1 ; 1 ] = 0 [p_2; 1]^T K^{-T} E K^{-1} [p_1; 1] = 0 [p2;1]TKTEK1[p1;1]=0

其中E是本质矩阵,p1 和p2分别是第一幅和第二幅图像中的对应点。此函数的结果可以进一步传递给 decomposeEssentialMat 或 recoverPose 来恢复摄像机之间的相对位姿。

函数原型2


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,
	int 	maxIters = 1000,
	OutputArray 	mask = noArray() 
)		

参数2

  • 参数points1:来自第一幅图像的 N (N >= 5) 个2D点数组。点的坐标应该是浮点数(单精度或双精度)。
  • 参数points2:第二幅图像的点数组,与 points1 具有相同的大小和格式。
  • 参数focal:相机的焦距。注意,此函数假设 points1 和 points2 是来自具有相同焦距和主点的相机的特征点。
  • 参数pp:相机的主点。
  • 参数method:计算基本矩阵的方法。
    • RANSAC:用于RANSAC算法。
    • LMEDS:用于最小中值法(LMedS)算法。
  • 参数threshold:仅用于RANSAC方法的参数。它是点到极线的最大距离(以像素为单位),超过该距离的点被认为是离群点,并不用于计算最终的基本矩阵。根据点定位的准确性、图像分辨率和图像噪声,它可以设置为1-3等。
  • 参数prob:仅用于RANSAC或LMedS方法的参数。它指定了估计矩阵正确的期望置信水平(概率)。
  • 参数mask:输出数组,包含N个元素,每个元素对于离群点设置为0,对于其他点设置为1。该数组仅在RANSAC和LMedS方法中计算。
  • 参数maxIters:稳健方法的最大迭代次数。
    说明

这个函数与上述函数的不同之处在于它通过焦距和主点来计算相机内参矩阵

A = [ f 0 x p p 0 f y p p 0 0 1 ] A = \begin{bmatrix} f & 0 & x_{pp} \\ 0 & f & y_{pp} \\ 0 & 0 & 1 \end{bmatrix} A= f000f0xppypp1

代码示例


#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    // 创建虚拟的匹配点数据(假设我们有10对匹配点)
    vector< Point2f > points1 = { Point2f( 154.0f, 38.0f ),  Point2f( 285.0f, 176.0f ), Point2f( 279.0f, 238.0f ), Point2f( 276.0f, 284.0f ), Point2f( 273.0f, 342.0f ),
                                  Point2f( 267.0f, 397.0f ), Point2f( 262.0f, 446.0f ), Point2f( 254.0f, 495.0f ), Point2f( 246.0f, 545.0f ), Point2f( 234.0f, 592.0f ) };

    vector< Point2f > points2 = { Point2f( 149.0f, 49.0f ),  Point2f( 280.0f, 187.0f ), Point2f( 274.0f, 249.0f ), Point2f( 271.0f, 295.0f ), Point2f( 268.0f, 353.0f ),
                                  Point2f( 262.0f, 408.0f ), Point2f( 257.0f, 457.0f ), Point2f( 249.0f, 506.0f ), Point2f( 241.0f, 556.0f ), Point2f( 229.0f, 603.0f ) };

    // 相机内参矩阵 (示例值)
    Mat cameraMatrix = ( Mat_< double >( 3, 3 ) << 718.856, 0, 607.193, 0, 718.856, 185.216, 0, 0, 1 );

    // 定义输出的本质矩阵和掩码
    Mat essentialMatrix, mask;

    // 使用 RANSAC 方法计算本质矩阵
    essentialMatrix = findEssentialMat( points1, points2, cameraMatrix, RANSAC, 0.999, 1.0, 1000, mask );

    // 打印结果
    cout << "Essential Matrix:\n" << essentialMatrix << endl;

    // 打印哪些点被认为是内点
    cout << "Inliers mask:\n";
    for ( size_t i = 0; i < mask.total(); ++i )
    {
        if ( mask.at< uchar >( i ) )
        {
            cout << "Point " << i + 1 << " is an inlier." << endl;
        }
        else
        {
            cout << "Point " << i + 1 << " is an outlier." << endl;
        }
    }

    // 如果需要,可以进一步分解本质矩阵或恢复姿态
    // decomposeEssentialMat(essentialMatrix, R1, R2, t);
    // recoverPose(essentialMatrix, points1, points2, cameraMatrix, R, t, mask);

    return 0;
}

运行结果

Essential Matrix:
[3.552514976490105e-09, -2.34328248364459e-07, -0.6437262524331034;
 2.332007722595955e-07, -1.168059907413519e-10, -0.2926029947621791;
 0.6437262524341074, 0.2926029926567176, 3.212847006212214e-09]
Inliers mask:
Point 1 is an inlier.
Point 2 is an inlier.
Point 3 is an inlier.
Point 4 is an inlier.
Point 5 is an inlier.
Point 6 is an inlier.
Point 7 is an inlier.
Point 8 is an inlier.
Point 9 is an inlier.
Point 10 is an inlier.

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

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

相关文章

RAGFlow 基于深度文档理解构建的开源 RAG引擎 - 安装部署

RAGFlow 基于深度文档理解构建的开源 RAG引擎 - 安装部署 flyfish 1. 确保 vm.max_map_count ≥ 262144 这是指要调整Linux内核参数vm.max_map_count&#xff0c;以确保其值至少为262144。这个参数控制着进程可以映射的最大内存区域数量。对于某些应用程序&#xff08;如Ela…

鸿蒙项目云捐助第二十九讲云捐助项目云数据库商品的批量增加功能实现

鸿蒙项目云捐助第二十九讲云捐助项目云数据库商品的批量增加功能实现 关于鸿蒙云捐助项目&#xff0c;前面的内容已使用云函数&#xff0c;云数据库分别实现云捐助项目首页中的项分类导航&#xff0c;底部导航&#xff0c;轮播图功能&#xff0c;这里继续实现云数据库加载捐赠…

Confluent Cloud Kafka 可观测性最佳实践

Confluent Cloud 介绍 Confluent Cloud 是一个完全托管的 Apache Kafka 服务&#xff0c;提供高可用性和可扩展性&#xff0c;旨在简化数据流处理和实时数据集成。用户可以轻松创建和管理 Kafka 集群&#xff0c;而无需担心基础设施的维护和管理。Confluent Cloud 支持多种数据…

SpringCloudAlibaba升级手册-nacos问题记录

目录 一、前言 二、升级过程 1.问题 2.原因 3.出处 4.理论解决 5.测试环境问题 6.Spring Cloud Alibaba版本对比 7. Spring Cloud Alibaba适配组件版本对比 8.降低Spring Cloud版本 9.SpringCloud与SpringBoot兼容对比表 10.naocs-client版本对比 三、最终解决 一…

15、【OS】【Nuttx】OS裁剪,运行指定程序,周期打印当前任务

背景 接之前wiki【Nsh中运行第一个程序】https://blog.csdn.net/nobigdeal00/article/details/144728771 OS还是比较庞大&#xff0c;且上面搭载了Nsh&#xff08;Nuttx Shell&#xff09;&#xff0c;需要接入串口才能正常工作&#xff0c;一般调试的时候用&#xff0c;非调试…

C# 窗体应用程序嵌套web网页,基于谷歌浏览器内核(含源码)

有一个winform项目&#xff0c;需要借助一个web项目来显示&#xff0c;并且对web做一些操作,web页目是需要用谷歌内核&#xff0c;基于谷歌 Chromium项目的开源Web Browser控件来开发写了一个demo。 安装步骤 第一步&#xff1a;右键项目&#xff0c;点击 管理NuGet程序包 , 输…

通过远程控制软件实现企业高效协作

在这个信息技术迅猛发展的时代&#xff0c;远程办公已经成为一种趋势&#xff0c;而远程控制软件则是连接分散团队的重要工具。技术的革新不仅推动了远程控制软件的广泛应用&#xff0c;也为现代办公带来了高效的协作体验。本文将探讨远程控制软件的发展&#xff0c;并以RayLin…

赋能开发者 | 麒麟信安受邀参加2024开放原子开发者大会,以技术为引领,以人才创发展

12月20至21日&#xff0c;以“一切为了开发者”为主题的“2024开放原子开发者大会暨首届开源技术学术大会”在湖北武汉举办。本届大会由开放原子开源基金会、中国通信学会联合主办&#xff0c;旨在贯彻落实国家软件发展战略&#xff0c;加速培育壮大我国开源生态。工业和信息化…

每天40分玩转Django:Django国际化

Django国际化 一、今日学习内容概述 学习模块重要程度主要内容国际化基础⭐⭐⭐⭐⭐基本概念、配置设置字符串翻译⭐⭐⭐⭐⭐翻译标记、消息文件模板国际化⭐⭐⭐⭐模板标签、过滤器动态内容翻译⭐⭐⭐⭐模型字段、表单翻译 二、国际化基础配置 # settings.py# 启用国际化 …

Elasticsearch 国产化替代方案之一 Easysearch 的介绍与部署指南

一、前言 在国内数字化转型浪潮和 信创 大背景下&#xff0c;“替代进口”成为许多企业级应用所需要面对的重要课题&#xff0c;搜索领域也不例外。 Elasticsearch&#xff08;简称 ES&#xff09;作为一款业界领先的全文搜索和分析引擎&#xff0c;虽然功能强大&#xff0c;但…

Ubuntu 24.04.1 LTS 配置静态固定IP地址

查看网络配置信息 ip addr使用该命令查看网卡名字&#xff0c;一般是ens33或者ens32 修改配置文件 打开 /etc/netplan/下面的yaml配置文件 根据自己的需要配置 network:ethernets:ens33: # 配置的网卡的名称addresses: [192.168.23.140/24] # 配置的静态ip地址和掩码d…

Deep Deterministic Policy Gradient (DDPG)算法

代码 import torch import torch.nn as nn import torch.optim as optim import numpy as np import gym import random from collections import deque# 定义 Actor 网络 class Actor(nn.Module):def __init__(self, state_dim, action_dim, max_action):super(Actor, self).…

C++ OCR 文字识别

一.引言 文字识别&#xff0c;也称为光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;是一种将不同形式的文档&#xff08;如扫描的纸质文档、PDF文件或数字相机拍摄的图片&#xff09;中的文字转换成可编辑和可搜索的数据的技术。随着技…

【解决报错】AttributeError: ‘NoneType‘ object has no attribute ‘group‘

学习爬虫时&#xff0c;遇到如下报错&#xff1a; 报错原因&#xff1a; 正则表达式的 search 或 finditer 方法没有找到任何匹配项&#xff0c;可能是换行符处理不当等。 解决方法如下&#xff1a; 在正则表达式末尾加上re.S即可&#xff0c;re.S是一个编译标志&#xff0c…

JVM实战—3.JVM垃圾回收的算法和全流程

大纲 1.JVM内存中的对象何时会被垃圾回收 2.JVM中的垃圾回收算法及各算法的优劣 3.新生代和老年代的垃圾回收算法 4.避免本应进入S区的对象直接升入老年代 5.Stop the World问题分析 6.JVM垃圾回收的原理核心流程 7.问题汇总 1.JVM内存中的对象何时会被垃圾回收 (1)什么…

基于SpringBoot在线音乐系统平台功能实现十八

一、前言介绍&#xff1a; 1.1 项目摘要 随着互联网技术的迅猛发展和普及&#xff0c;人们对音乐的获取和欣赏方式发生了巨大改变。传统的音乐播放方式&#xff0c;如CD、磁带或本地下载的音乐文件&#xff0c;已经不能满足用户日益增长的需求。用户更希望通过网络直接获取各…

RouYi-Vue框架,环境搭建以及使用

使用若以框架需要配置node.js&#xff0c;如果不了解可以去看node.js安装&#xff0c;uni-app的配置使用_uniapp使用nodejs类库-CSDN博客 安装若依 首先是去若以官网下载自己所需要的框架类型 RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff…

XL系列433芯片、2.4G收发芯片 通讯对码说明

XL系列433芯片对码说明&#xff1a; 发射芯片 XL4456 通过数据脚接收高低电平然后经过调制将波形发出&#xff0c;而接收芯片 XL520 通过接收波形后进行解调&#xff0c;数据脚输出高低电平。至于具体的通信协议&#xff0c;需要用户自定义&#xff0c;一般而言&#xff0c;使…

蓝牙BLE开发——解决iOS设备获取MAC方式

解决iOS设备获取MAC方式 uniapp 解决 iOS 获取 MAC地址&#xff0c;在Android、iOS不同端中互通&#xff0c;根据MAC 地址处理相关的业务场景&#xff1b; 文章目录 解决iOS设备获取MAC方式监听寻找到新设备的事件BLE工具效果图APP监听设备返回数据解决方式ArrayBuffer转16进制…

期权懂|如何计算期权卖方平仓后的盈利?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 如何计算期权卖方平仓后的盈利&#xff1f; 期权卖方平仓后的盈利计算涉及多个因素&#xff0c;包括期权的交易价格、平仓价格以及权利金的变动等。 交易价格&#xff1a;期权卖…