OpenCV相机标定与3D重建(56)估计物体姿态(即旋转和平移)的函数solvePnPRansac()的使用

news2025/1/15 15:46:21
  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

使用RANSAC方案从3D-2D点对应关系中找到物体的姿态。
cv::solvePnPRansac 是 OpenCV 中用于估计物体姿态(即旋转和平移)的函数,它通过随机抽样一致性算法(RANSAC)来增强对异常值(outliers)的鲁棒性。

函数原型

bool cv::solvePnPRansac	
(
	InputArray 	objectPoints,
	InputArray 	imagePoints,
	InputArray 	cameraMatrix,
	InputArray 	distCoeffs,
	OutputArray 	rvec,
	OutputArray 	tvec,
	bool 	useExtrinsicGuess = false,
	int 	iterationsCount = 100,
	float 	reprojectionError = 8.0,
	double 	confidence = 0.99,
	OutputArray 	inliers = noArray(),
	int 	flags = SOLVEPNP_ITERATIVE 
)		

参数

  • 参数objectPoints 物体坐标空间中的物体点数组,格式为Nx3的单通道或1xN/Nx1的三通道,其中N是点的数量。也可以传递

  • 参数vector 类型的数据。

  • 参数imagePoints 对应的图像点数组,格式为Nx2的单通道或1xN/Nx1的双通道,其中N是点的数量。也可以传递 vector 类型的数据。

  • 参数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

  • 参数distCoeffs 输入的畸变系数向量 (k1, k2, p1, p2 [,k3 [,k4, k5, k6 [,s1, s2, s3, s4 [,τx, τy]]]]),包含4、5、8、12或14个元素。如果该向量为空,则假设畸变为零。

  • 参数rvec 输出的旋转向量(见 Rodrigues),与 tvec 一起将模型坐标系中的点变换到相机坐标系中。

  • 参数tvec 输出的平移向量。

  • 参数useExtrinsicGuess 仅用于 SOLVEPNP_ITERATIVE 方法。如果为真(1),函数会使用提供的 rvec 和 tvec 值作为旋转和平移向量的初始近似值,并进一步优化它们。

  • 参数iterationsCount 迭代次数。

  • 参数reprojectionError RANSAC过程使用的内点阈值。参数值是观察到的投影点和计算出的投影点之间的最大允许距离,以被认为是内点。

  • 参数 confidence 算法产生有用结果的概率。

  • 参数inliers 输出向量,包含 objectPoints 和 imagePoints 中内点的索引。

  • 参数flags 解决PnP问题的方法(见 solvePnP)。

该函数根据一组物体点及其对应的图像投影,以及相机内参矩阵和畸变系数来估计物体的姿态。这个函数寻找一个使重投影误差最小的姿态,即观测到的投影点 imagePoints 和使用 projectPoints 投影的 objectPoints 之间的平方距离之和最小。RANSAC的使用使得函数对异常值具有鲁棒性。

注意

使用 solvePNPRansac 进行物体检测的一个示例可以在 opencv_source_code/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/ 找到。
最小样本集步骤中用于估计相机姿态的默认方法是 SOLVEPNP_EPNP。例外情况包括:
如果选择了 SOLVEPNP_P3P 或 SOLVEPNP_AP3P,则这些方法将被使用。
如果输入点的数量等于4,则使用 SOLVEPNP_P3P。
使用所有内点估计相机姿态的方法由 flags 参数定义,除非它等于 SOLVEPNP_P3P 或 SOLVEPNP_AP3P,在这种情况下,将使用 SOLVEPNP_EPNP 方法代替。

代码示例

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

using namespace cv;
using namespace std;

int main()
{
    // 确保至少有4个点对
    vector< Point3f > objectPoints = { Point3f( 0.0f, 0.0f, 0.0f ), Point3f( 1.0f, 0.0f, 0.0f ), Point3f( 0.0f, 1.0f, 0.0f ), Point3f( 1.0f, 1.0f, 0.0f ) };

    vector< Point2f > imagePoints = { Point2f( 300.0f, 300.0f ), Point2f( 400.0f, 300.0f ), Point2f( 300.0f, 400.0f ), Point2f( 400.0f, 400.0f ) };

    // 检查点的数量是否一致
    if ( objectPoints.size() != imagePoints.size() || objectPoints.size() < 4 )
    {
        cerr << "Error: Need at least 4 point pairs and the number of points must match." << endl;
        return -1;
    }

    // 相机内参矩阵
    Mat cameraMatrix = ( Mat_< double >( 3, 3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );

    // 畸变系数
    Mat distCoeffs = ( Mat_< double >( 5, 1 ) << 0.2624, -0.9531, -0.0054, 0.0026, 1.1633 );

    // 输出变量
    Vec3d rvec;  // 旋转向量
    Vec3d tvec;  // 平移向量

    // 调用 solvePnPRansac 函数
    bool success = solvePnPRansac( objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, false, 100, 8.0, 0.99, noArray(), SOLVEPNP_ITERATIVE );

    if ( success )
    {
        cout << "成功找到解:" << endl;
        cout << "旋转向量: " << rvec << endl;
        cout << "平移向量: " << tvec << endl;

        // 可选:将旋转向量转换为旋转矩阵
        Mat R;
        Rodrigues( rvec, R );
        cout << "旋转矩阵: " << endl << R << endl;
    }
    else
    {
        cout << "未能找到有效的解" << endl;
    }

    return 0;
}

运行结果

成功找到解:
旋转向量: [0.0425377, -0.0162527, -0.000105512]
平移向量: [-0.251554, 0.504018, 5.22556]
旋转矩阵: 
[0.9998679414301481, -0.000240141627923739, -0.01624937021045788;
 -0.0004510929798306415, 0.999095423415709, -0.04252212864978416;
 0.01624488274385277, 0.04252384321511622, 0.9989633759767446]

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

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

相关文章

保姆级图文详解:Linux和Docker常用终端命令

文章目录 前言1、Docker 常用命令1.1、镜像管理1.2、容器管理1.3、网络管理1.4、数据卷管理1.5、监控和性能管理 2、Linux 常用命令分类2.1、文件和目录管理2.2、用户管理2.3、系统监控和性能2.4、软件包管理2.5、网络管理 前言 亲爱的家人们&#xff0c;技术图文创作很不容易…

相机SD卡照片数据不小心全部删除了怎么办?有什么方法恢复吗?

前几天&#xff0c;小编在后台友收到网友反馈说他在整理相机里的SD卡&#xff0c;原本是想把那些记录着美好瞬间的照片导出来慢慢欣赏。结果手一抖&#xff0c;不小心点了“删除所有照片”&#xff0c;等他反应过来&#xff0c;屏幕上已经显示“删除成功”。那一刻&#xff0c;…

《C++11》nullptr介绍:从NULL说起

在C11之前&#xff0c;我们通常使用NULL来表示空指针。然而&#xff0c;NULL在C中有一些问题和限制&#xff0c;这就是C11引入nullptr的原因。本文将详细介绍nullptr的定义、用法和优点。 1. NULL的问题 在C中&#xff0c;NULL实际上是一个整数0&#xff0c;而不是一个真正的…

【搭建JavaEE】(2)Tomcat安装配置和第一个JavaEE程序

Tomcat–容器(Container) 下载 Apache Tomcat - Welcome! 下载完成 请求/响应 结构 测试 查看Jdk版本 改端口号localhost8080–>8099 学学人家以后牛逼了可以用自己名字当文件夹名 配置端口8099 找到server文件 用记事本打开 再打开另一个logging文件 ”乱码解决“步骤&…

​​​​​​​​​​​​​​★3.3 事件处理

★3.3.1 ※MouseArea Item <-- MouseArea 属性 acceptedButtons : Qt::MouseButtons containsMouse : bool 【书】只读属性。表明当前鼠标光标是否在MouseArea上&#xff0c;默认只有鼠标的一个按钮处于按下状态时才可以被检测到。 containsPress : bool curs…

【C】初阶数据结构3 -- 单链表

之前在顺序表那一篇文章中&#xff0c;提到顺序表具有的缺点&#xff0c;比如头插&#xff0c;头删时间复杂度为O(n)&#xff0c;realloc增容有消耗等。而在链表中&#xff0c;这些问题将得到解决。所以在这一篇文章里&#xff0c;我们将会讲解链表的定义与性质&#xff0c;以及…

Python----Python高级(函数基础,形参和实参,参数传递,全局变量和局部变量,匿名函数,递归函数,eval()函数,LEGB规则)

一、函数基础 1.1、函数的用法和底层分析 函数是可重用的程序代码块。 函数的作用&#xff0c;不仅可以实现代码的复用&#xff0c;更能实现代码的一致性。一致性指的是&#xff0c;只要修改函数的代码&#xff0c;则所有调用该函数的地方都能得到体现。 在编写函数时&#xf…

《leetcode-runner》如何手搓一个debug调试器——架构

本文主要聚焦leetcode-runner对于debug功能的整体设计&#xff0c;并讲述设计原因以及存在的难点 设计引入 让我们来思考一下&#xff0c;一个最简单的调试器需要哪些内容 首先&#xff0c;它能够接受用户的输入 其次&#xff0c;它能够读懂用户想让调试器干嘛&#xff0c;…

食堂采购系统源码:基于PHP的校园食堂供应链管理平台开发全解析

传统的食堂采购管理普遍存在信息不透明、流程繁琐、效率低下等问题&#xff0c;这使得开发一款高效、智能的食堂采购系统变得尤为重要。本篇文章&#xff0c;笔者将详细解析基于PHP开发的校园食堂供应链管理平台&#xff0c;从功能设计、系统架构到技术实现&#xff0c;全方位剖…

WEB 攻防-通用漏-XSS 跨站脚本攻击-反射型/存储型/DOMBEEF-XSS

XSS跨站脚本攻击技术&#xff08;一&#xff09; XSS的定义 XSS攻击&#xff0c;全称为跨站脚本攻击&#xff0c;是指攻击者通过在网页中插入恶意脚本代码&#xff0c;当用户浏览该网页时&#xff0c;恶意脚本会被执行&#xff0c;从而达到攻击目的的一种安全漏洞。这些恶意脚…

重生之我在21世纪学C++—函数与递归

一、函数是什么&#xff1f; 相信我们第一次接触函数是在学习数学的时候&#xff0c;比如&#xff1a;一次函数 y kx b &#xff0c;k 和 b 都是常数&#xff0c;给一个任意的 x &#xff0c;就会得到一个 y 值。 其实在 C 语言中就引入了函数&#xff08;function&#xf…

Mac——Cpolar内网穿透实战

摘要 本文介绍了在Mac系统上实现内网穿透的方法&#xff0c;通过打开远程登录、局域网内测试SSH远程连接&#xff0c;以及利用cpolar工具实现公网SSH远程连接MacOS的步骤。包括安装配置homebrew、安装cpolar服务、获取SSH隧道公网地址及测试公网连接等关键环节。 1. MacOS打开…

Ubuntu中双击自动运行shell脚本

方法1: 修改文件双击反应 参考: https://blog.csdn.net/miffywm/article/details/103382405 chmod x test.sh鼠标选中待执行文件&#xff0c;在窗口左上角edit菜单中选择preference设计双击执行快捷键&#xff0c;如下图&#xff1a; 方法2: 设置一个应用 参考: https://blo…

力扣 全排列

回溯经典例题。 题目 通过回溯生成所有可能的排列。每次递归时&#xff0c;选择一个数字&#xff0c;直到选满所有数字&#xff0c;然后记录当前排列&#xff0c;回到上层时移除最后选的数字并继续选择其他未选的数字。每次递归时&#xff0c;在 path 中添加一个新的数字&…

arcgis提取不规则栅格数据的矢量边界

效果 1、准备数据 栅格数据:dem或者dsm 2、栅格重分类 分成两类即可 3、新建线面图层 在目录下选择预先准备好的文件夹,点击右键,选择“新建”→“Shapefile”,新建一个Shapefile文件。 在弹出的“新建Shapefile”对话框内“名称”命名为“折线”,“要素类型”选…

【DB-GPT】开启数据库交互新篇章的技术探索与实践

一、引言&#xff1a;AI原生数据应用开发的挑战与机遇 在数字化转型的浪潮中&#xff0c;企业对于智能化应用的需求日益增长。然而&#xff0c;传统的数据应用开发方式面临着诸多挑战&#xff0c;如技术栈复杂、开发周期长、成本高昂、难以维护等。这些问题限制了智能化应用的…

LVGL移植高通点阵字库GT30L24A3W

字库芯片: GT30L24A3W MCU:STM32F429 LVGL版本:V8.4 一、实现gt_read_data() 和 r_dat_bat() 请参考下面视频 如何在32位MCU上使用高通点阵字库_哔哩哔哩_bilibili 高通字库使用教程(1)硬件链接与注意事项部分_哔哩哔哩_bilibili 高通字库使用教程(2)SPI底层函数使用_哔哩…

一键掌握多平台短视频矩阵营销/源码部署

短视频矩阵系统的介绍与应用 随着数字化营销策略的不断演进&#xff0c;传统的短视频矩阵操作方法可能已显陈旧。为此&#xff0c;一款全新的短视频矩阵系统应运而生&#xff0c;它通过整合多个社交媒体账户、创建多样化的任务、运用先进的智能视频编辑工具、实现多平台内容的…

MySQL(高级特性篇) 06 章——索引的数据结构

一、为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;就好比一本教科书的目录部分&#xff0c;通过目录找到对应文章的页码&#xff0c;便可快速定位到需要的文章。MySQL中也是一样的道理&#xff0c;进行数据查找时&#xff0c;首先查看查询条件…

源码安装httpd2.4

1、下载 wget https://archive.apache.org/dist/httpd/httpd-2.4.54.tar.gz 2.解压下载压缩包 tar -zxvf httpd-2.4.54.tar.gz cd httpd-2.4.54 3、安装httpd所需要的依赖 yum groupinstall "Development Tools" -y 4.配置httpd ./configure --prefix/usr/local/htt…