cv::solvePnP使用方法及注意点详解(OpenCV/C++)

cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, flags);

1、参数说明:

  • objectPoints:一个 vector<cv::Point3f>,包含了在世界坐标系中的三维点的坐标,至少需要4个点。
  • imagePoints:一个 vector<cv::Point2f>,包含了对应的图像上的二维点的坐标,与 objectPoints 中的点一一对应。
  • cameraMatrix:相机的内参数矩阵,类型为 cv::Mat,一般为 3x3 的浮点数矩阵。
  • distCoeffs:相机的畸变系数,类型为 cv::Mat,一般为 4x1 或 5x1 的浮点数矩阵。
  • rvec:输出的旋转向量,类型为 cv::Mat,是大小为 3x1 的浮点数矩阵。
  • tvec:输出的平移向量,类型为 cv::Mat,是大小为 3x1 的浮点数矩阵。
  • useExtrinsicGuess:一个布尔值,表示是否使用可选的旋转和平移向量的初始猜测。默认为 false。
  • flags:一个用于控制函数行为的选项标志,默认为 0。

        函数返回:

  • 成功返回 true,失败返回 false。

2、使用说明:

objectPoints, imagePoints, cameraMatrix, distCoeffs  四个参数作为输入参数

rvec, tvec 作为输出参数

objectPoints是世界坐标系的三维坐标

imagePoints是图像上的二维点坐标

例如 使用标定好的单目相机拍摄一个矩形物体(已知相机内参&畸变系数),

objectPoints:使用量尺测量物体的左上角、右上角、左下角、右下角之间的距离,以任意一个点作为0点,建立世界坐标系,z值设为0,得到所有点的坐标则为objectPoints,保存在vector中。

imagePoints:在图像中找到物体的左上角、右上角、左下角、右下角四个点,其所有点的像素坐标为imagePoints,保存在vector中。

使用示例:

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>int main() {std::vector<cv::Point3f> objectPoints;  // 世界坐标系中的三维点std::vector<cv::Point2f> imagePoints;   // 图像上的二维点// 添加 objectPoints 和 imagePoints 的数据// 创建相机内参数矩阵cv::Mat cameraMatrix = (cv::Mat_<double>(3,3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);  // 创建相机畸变系数矩阵cv::Mat distCoeffs = (cv::Mat_<double>(1,5) << k1, k2, p1, p2, k3;//完善内参参数&畸变系数参数  cv::Mat rvec;  // 输出的旋转向量cv::Mat tvec;  // 输出的平移向量bool success = cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);if (success) {// 获取旋转向量和平移向量的结果cv::Mat rotationMatrix;cv::Rodrigues(rvec, rotationMatrix);std::cout << "Rotation Vector:" << std::endl << rvec << std::endl;std::cout << "Translation Vector:" << std::endl << tvec << std::endl;std::cout << "Rotation Matrix:" << std::endl << rotationMatrix << std::endl;}return 0;
}

3、注意事项:

在使用solvePnP时,需注意objectPoints和imagePoints容器中的点坐标必须一一对应,例如只有四个点时,全部按左上角、右上角、左下角、右下角的顺序存放在容器中;如果顺序不相同,则最终输出值有误。

在笔者使用solvePnP时,拍摄物是四个定位圆,圆的像素坐标是通过opencv的SimpleBlobDetector识别的,识别以后的圆像素坐标是无序的,无法和objectPoints对应上,因此有了下述算法,

用于为四个二维坐标做冒泡排序得到左上角、右上角、左下角、右下角分别对应的点

(如果没有该需求,可以忽略此段)

int main() {std::vector<cv::Point2f> imagePoints; // 存放四个点的 vector// 假设已经将四个点的坐标存入 imagePoints 中// 寻找左上角、右上角、右下角和左下角对应的点cv::Point2f topLeft, topRight, bottomRight, bottomLeft;float minX = FLT_MAX, minY = FLT_MAX;float maxX = FLT_MIN, maxY = FLT_MIN;for (const auto& point : imagePoints) {if (point.x <= minX && point.y <= minY) {topLeft = point;minX = point.x;minY = point.y;}if (point.x >= maxX && point.y <= minY) {topRight = point;maxX = point.x;minY = point.y;}if (point.x >= maxX && point.y >= maxY) {bottomRight = point;maxX = point.x;maxY = point.y;}if (point.x <= minX && point.y >= maxY) {bottomLeft = point;minX = point.x;maxY = point.y;}}// 输出左上角、右上角、右下角和左下角对应的点的坐标std::cout << "左上角坐标: (" << topLeft.x << ", " << topLeft.y << ")" << std::endl;std::cout << "右上角坐标: (" << topRight.x << ", " << topRight.y << ")" << std::endl;std::cout << "右下角坐标: (" << bottomRight.x << ", " << bottomRight.y << ")" << std::endl;std::cout << "左下角坐标: (" << bottomLeft.x << ", " << bottomLeft.y << ")" << std::endl;// 新建一个vector存放四个点坐标,按照objectPoints的存放顺序进行存放std::vector<cv::Point2f> imagePoints2; imagePoints2.push_back(topLeft);imagePoints2.push_back(topRight);imagePoints2.push_back(bottomRight);imagePoints2.push_back(bottomLeft);return 0;
}

4、补充

通过solvePnP得到旋转向量rvec和平移向量tvec后,可以计算相机到被测物中心的实际距离

#include <cmath>
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>int main() {std::vector<cv::Point3f> objectPoints;  // 世界坐标系中的三维点std::vector<cv::Point2f> imagePoints;   // 图像上的二维点// 添加 objectPoints 和 imagePoints 的数据// 创建相机内参数矩阵cv::Mat cameraMatrix = (cv::Mat_<double>(3,3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);  // 创建相机畸变系数矩阵cv::Mat distCoeffs = (cv::Mat_<double>(1,5) << k1, k2, p1, p2, k3;//完善内参参数&畸变系数参数  cv::Mat rvec;  // 输出的旋转向量cv::Mat tvec;  // 输出的平移向量bool success = cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);if (success) {//计算相机距离被测物的实际距离float distance = sqrt(tvec.at<double>(0,0) * tvec.at<double>(0,0) + tvec.at<double>(1,0) * tvec.at<double>(1,0) + tvec.at<double>(2,0) * tvec.at<double>(2,0)) / 10; std::cout << "distance = "<< distance << std::endl;}return 0;
}

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

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

相关文章

RK3399平台开发中安卓系统去除USB权限弹窗

RK3399平台开发中安卓系统去除USB权限弹窗 问题方法 问题 当我们在访问一个插入到Android系统的USB设备的时候往往是需要权限的&#xff0c;此时系统会弹出询问权限的对话框&#xff0c;而我们此时希望让它默认允许访问USB设备并且不希望用户看到这个对话框。 方法 文件目录&…

CSS - 常用属性和布局方式

目录 前言 一、常用属性 1.1、字体相关 1.2、文本相关 1.3、背景相关 1.3.1、背景颜色 1.3.2、背景图片 1.4、圆角边框 二、常用布局相关 2.1、display 2.2、盒子模型 2.2.1、基本概念 2.2.2、border 边框 2.2.3、padding 内边距 2.2.4、margin 外边距 2.3、弹…

Golang命令行库

前言 有时候我们需要安装公司的软件,或者做个类似 node_explorer 的客户端采集程序,当 ./xx -h 的时候可以看到很多的命令行参数。Golang命令行参数我们可以通过内置的库 os.args 或者 flag库去实现,但是功能较弱。如果使用第三库 会更加功能丰富。 第三方库 cli库 ## ht…

gcc和makfile

gcc和makfile gcc预处理(进行宏替换)编译(生成汇编)汇编(生成机器可以识别的代码)连接(生成可以执行的文件或者库文件) makemakefile文件的编写 gcc 没安装的话&#xff0c;按照终端提示的安装命令安装就行 运行的格式&#xff1a; gcc [选项] [要编译的文件] [选项] [目标文件…

idea 没加载 provided的包

目录 前言解决方案 前言 我的版本是IntelliJ IDEA 2022.1.4 (Community Edition)&#xff0c;本地调试不知道为什么不加载provided的包。后来找到这篇文章https://youtrack.jetbrains.com/issue/IDEA-107048才知道这是个bug。不知道其他版本会不会出现这种问题。 解决方案 我…

SylixOS BSP开发(八)

初始化FPU、MMU和Cache组件 本来想在不初始化这些部件的情况下把SylixOS先启动起来感受下&#xff0c;结果测试发现如果MMU不使能的话&#xff0c;系统启动过程中线程无法进行调度emm。。。所以只好把这一章节提前来讲了。这三个组件的初始化都是在bspInit.c中进行的。 1. FPU初…

Unity游戏开发中打造游戏攻击技能架构与设计

一、技能系统的设计 在 MOBA 游戏中&#xff0c;每个英雄角色都会有多个技能&#xff0c;这些技能可以分为普通攻击和技能攻击两种。普通攻击是英雄角色的基本攻击方式&#xff0c;而技能攻击则需要消耗一定的资源&#xff08;如蓝量&#xff09;才能使用。在设计技能系统时&a…

【面试经典150 | 链表】循环链表

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;哈希集合方法二&#xff1a;快慢指针方法三&#xff1a;计数 拓展其他语言python3 写在最后 Tag 【快慢指针】【哈希集合】【计数】【链表】 题目来源 141. 环形链表 题目解读 判断一个链表中是否存在环。 解题思路 …

(Java)中的数据类型和变量

文章目录 一、字面常量二、数据类型三、变量1.变量的概念2.语法的格式3.整型变量4.长整型变量5.短整型变量6.字节型变量 四、浮点型变量1.双精度浮点数2.单精度浮点数 五、字符型常量六、布尔型变量七、类型转换1.自动类型转换&#xff08;隐式&#xff09;2.强制类型转换(显式…

react的setState做了什么

1、为什么需要setState setState的作用是帮助我们更改数据的同时并且通知视图进行渲染。因为React并不会绑定视图和state&#xff0c;需要我们手动去更新视图。 2、setState什么时候是同步的&#xff0c;什么时候是异步的 setState这个方法在调用的时候是同步的&#xff0c;…

技巧 | 如何解决 zsh: permission denied 问题 | Mac

技巧 | 如何解决 zsh: permission denied 问题 | Mac 问题描述 在 macOS 系统终端执行 sh 程序脚本时&#xff0c;抛出异常 zsh: permission denied 原因分析 用户没有权限&#xff0c;所以才出现了这个错误&#xff0c;所以只需要用 chmod 修改一下权限就可以了 解决方法…

【人工智能Ⅰ】实验1:谓词表示法与产生式知识表示

实验1 谓词表示法与产生式知识表示 一、实验目的 1、熟悉谓词逻辑表示法&#xff1b; 2、理解和掌握产生式知识表示方法&#xff0c;实现产生式系统的规则库。 二、实验内容 要求通过C/C/python语言编程实现&#xff1a; 1、猴子摘香蕉问题 2、动物识别系统 &#xff08…

Spring无法加载静态属性和SpringBoot单元测试指定加载配置文件

一、Spring无法加载静态属性&#xff0c;怎么解决&#xff1f; Spring主要用于管理和注入Bean&#xff08;对象&#xff09;的实例属性&#xff0c;而不是静态属性。静态属性属于类本身&#xff0c;而不是类的实例&#xff0c;因此Spring的依赖注入机制不会处理它们。 看图&a…

项目部署Linux步骤

1、最小化安装centos7-环境准备 安装epel-release 安装epel-release&#xff0c;因为有些rpm包在官方库中找不到。前提是保证可以联网 yum install -y epel-release 修改IP net-tools net-tool&#xff1a;工具包集合&#xff0c;包含ifconfig等命令 yum install -y net-…

【MySQL-->数据操作】

文章目录 前言一、insert1.单行插入2.多行插入3.插入更新/替换 二、select1.全列查询2.指定列插入3.列别名4. 表达式计算5.去重6.where条件查询7.排序8.limit分页显示 三、update四、delete五、插入查询结果六、聚合函数六、聚合分组1.格式2.where和having的区别 前言 一、inse…

个人创业新机遇,零成本开启真人手办定制项目

桌上的日历变薄&#xff0c;2023年已经接近尾声&#xff0c;浅观这一年&#xff0c;您是否发现大家日常关注的重点有明显的变化&#xff0c;诸多社会事件和宏观数字的背后&#xff0c;潜藏着对经济的“不托底”&#xff0c;而当我们真正开始关注起用个人经济积累去对冲未来的不…

大数据Flink(一百零一):SQL 表值函数(Table Function)

文章目录 SQL 表值函数(Table Function) SQL 表值函数(Table Function) Python UDTF,即 Python TableFunction,针对每一条输入数据,Python UDTF 可以产生 0 条、1 条或者多条输出数据,此外,一条输出数据可以包含多个列。比如以下示例,定义了一个名字为 split 的Pyt…

【会员管理系统】篇二之项目搭建、初始化、安装第三方库

一、项目搭建 1.全局安装vue-cli npm install -g vue/cli查看版本信息 vue -V 2.创建项目 vue create 项目名称 回车 回车 剩余选择如下 之后等待项目创建 最后npm run serve 二、初始化配置 1.更改标题 打开public下的index&#xff0c;将title标签里的改成想要设置的…

汽车电子专有名词与相应技术

1.EEA &#xff08;Electronic & Electrical Architecture 电子电气架构&#xff09; EEA在宏观上概括为物理架构与逻辑架构的结合&#xff0c;微观上通过众多电子元器件的协同配合&#xff0c;或集成式或分布式的系统级电子电气架构&#xff0c;具体详见专栏 新能源汽车电…

大疆DJI RoboMaster 机甲大师知识库和参赛攻略

标题链接【RM2021 四川站第二期直播】步兵设计及弹道测试https://bbs.robomaster.com/forum.php?modviewthread&tid11504&extrapage%3D1%26filter%3Dtypeid%26orderby%3Ddateline【RM2021 黑龙江站第4期直播】步兵机械设计入门2https://bbs.robomaster.com/forum.php?…