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;
}
相关文章:
cv::solvePnP使用方法及注意点详解(OpenCV/C++)
cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, flags); 1、参数说明: objectPoints:一个 vector<cv::Point3f>,包含了在世界坐标系中的三维点的坐标,至少需要4个点…...
DevOps持续集成-Jenkins(4)
❤️作者简介:2022新星计划第三季云原生与云计算赛道Top5🏅、华为云享专家🏅、云原生领域潜力新星🏅 💛博客首页:C站个人主页🌞 💗作者目的:如有错误请指正,将…...
【数据仓库-零】数据仓库知识体系 ing
文章目录 一. 数仓基本概念二. 离线数仓建设方法论三. etl流程四. 数仓规范建设指南四. 数据仓库架构五. 数据可视化 通过熟悉构建数仓整体的过程,可以系统的了解 数仓构建理论:能够站在全局角度看数仓的运行架构,数仓执行流程。了解到构建数…...
css3 3D 转换 技巧详细解析与代码实例
CSS3 3D转换是CSS3中的一项新特性,通过它我们可以比较容易地实现3D效果。在这里,我将向大家介绍CSS3 3D转换的一些基本概念、使用方法和常见技巧。 1. 基本概念 在使用CSS3 3D转换时,需要了解一些基础概念: 三维坐标系…...
[Unity]给场景中的3D字体TextMesh增加描边方案一
取你的文本对象,简单地添加以下脚本: using UnityEngine; using System.Collections; using UnityEngine.UI;public class TextOutline : MonoBehaviour {public float pixelSize 1;public Color outlineColor Color.black;public bool resolutionDependant fal…...
TDengine(taos)数据库导出历史数据
业务需求:导出某个站点的累计充电量,累计放电量,光伏总放电量,进线总功率的所有数据‘ 1、登录taos,使用存数据的库; 提示Database changed;即为使用成功; 2、找到你想要导出的字段…...
算法进修Day-37
算法进修Day-37 73. 矩阵置零 难度:中等 题目要求 给定一个 _m_ x _n_ 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例1 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[…...
服务器之日常整活
文章目录 一,序二、服务器相关流水帐未完,待补充 一,序 假如你有一台服务器,你最想做哪些事? 等等,什么叫假如你有一台服务器,假如只有一台,肯定我想搞第二台,顺便第三台…...
交互式 Web 应用 0 基础入门
初探 Gradio:轻松构建交互式 Web 应用 文章目录 初探 Gradio:轻松构建交互式 Web 应用Why Gradio?安装 Gradio创建交互式界面1. gr.Interface2. gr.Blocks 强大的组件库输入输出组件控制组件布局组件 示例交互式数据可视化多组件同时(嵌套&a…...
JSONP的安全性较差,那么在跨域情况下,有没有其他更安全的替代方案呢?
在跨域情况下,为了保证安全性,有几种更安全的替代方案可以考虑使用: 1:CORS(Cross-Origin Resource Sharing): CORS 是一种现代化的跨域解决方案,通过在服务器端设置响应头来控制跨…...
Slax Linux 获得增强的会话管理和启动参数选项
Slax Linux 的创建者和维护者托马斯-马特吉切克(Tomas Matejicek)在自己生日这天(生日快乐!)发布了其小巧便携的 GNU/Linux 发行版的新版本,带来了各种增强功能和错误修复。 新发布的 Slax Linux 版本&…...
C/C++新冠疫情死亡率 2020年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
目录 C/C新冠疫情死亡率 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C新冠疫情死亡率 2020年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 2020年全世界爆发了新冠疫情,请…...
Adobe Photoshop 基本操作
PS快捷键 图层 选择图层 Ctrl T:可以对图层的大小和位置进行调整 填充图层 MAC: AltBackspace (前景) or CtrlBackspace (背景) WINDOWS: AltDelete (前景) or CtrlDelete (背景) 快速将图层填充为前景色或背景色 平面化图层(盖印图层)…...
SpringMVC原理及核心组件
一、SpringMVC原理及核心组件 1、 Spring MVC的工作原理 Spring MVC 是一个对javaWeb中Servlet 简化和封装, 1.首先SpringMVC 配置DispatcherServlet 来接受所有的请求,我们通过DispatcherServlet 响应的所有数据,DispatcherServlet 是Htt…...
【rk3568-linux】 rk3568x_linux-- 编译说明
概述 一个好的安装教程能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径,学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 开发环境 开发环境:ubuntu18 文章目录 概述开发环境一、选择型号二、全自动编译三、…...
模拟计算器编程教程,中文编程开发语言工具编程实例
模拟计算器编程教程,中文编程开发语言工具编程实例 中文编程系统化教程,不需英语基础。学习链接 https://edu.csdn.net/course/detail/39036 课程安排:初级1 1 初级概述 2 熟悉构件取值赋值 3 折叠式菜单滑动面板编程 4 自定…...
Spring Security漏洞防护—HTTP 安全响应头
一、默认的 Security Header Spring Security提供了 一套默认的安全HTTP响应头,以提供安全默认值。虽然这些头信息中的每一个都被认为是最佳实践,但应该注意的是,并不是所有的客户端都使用这些头信息,所以鼓励进行额外的测试。 …...
Plooks大型视频在线一起看网站源码
在前段时间,因为想和异地的朋友一起看电影,但是发现有电影的地方没有一起看功能,有一起看功能的视频网站没有电影,所以就想自己做一个一起看网站,于是就有了Plooks。 Plooks是一个完整的视频网站,其中包括…...
图像处理中底层、高层特征、上下文信息理解
1.图像的语义信息: 图像的语义分为视觉层、对象层和概念层。 视觉层即通常所理解的底层,即颜色、纹理和形状等等,这些特征都被称为底层特征语义; 对象层即中间层,通常包含了属性特征等,就是某一对象在某一时刻的状态&a…...
负载均衡的算法(静态算法与动态算法)
1.静态算法 静态算法是不考虑服务器动态负载的算法,包括: (1)轮转算法:轮流将服务请求(任务)调度给不同的节点(即:服务器)。 (2)加…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
