OpenCV solvePnP位姿估计

news/2024/9/13 22:55:34/ 标签: opencv, 人工智能, 算法, python, 计算机视觉, 图像处理

目录

一、概述

二、实现代码

2.1solvePnP函数

2.1.1输入参数

2.1.2输出参数

2.2完整代码

三、实现效果

3.1标定板位姿

3.2标定板到相机的变换矩阵


一、概述

        完成相机标定后,可以通过检测标定板在图像中的位置来计算标定板在相机坐标系下的位姿(外参)。通过cv2.solvePnP求出标定板在相机坐标系下的姿态矩阵后,保存下来可用于后续的手眼标定

具体步骤如下:

  1. 相机标定:获取相机的内参矩阵和畸变系数。
  2. 检测标定板:在图像中检测棋盘格角点。
  3. 计算外参:使用 cv2.solvePnP 计算标定板在相机坐标系下的位姿。

二、实现代码

2.1solvePnP函数

        cv2.solvePnP 是 OpenCV 中用于估计对象姿态的函数。它计算从 3D 点到 2D 图像点的变换,包括旋转和位移。

python">retval, rvec, tvec = cv2.solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs[, rvec[, tvec[, useExtrinsicGuess[, flags]]]])

2.1.1输入参数

2.1.2输出参数

2.2完整代码

python">import cv2
import numpy as np
import glob# 加载相机标定参数
with np.load('camera_calibration.npz') as data:mtx = data['mtx']dist = data['dist']# 设置棋盘格参数
chessboard_size = (11, 8)  # 棋盘格的内角点个数
square_size = 1.0  # 棋盘格每个方格的实际大小,单位可以是毫米、厘米或米# 准备棋盘格的世界坐标系坐标(假设z=0)
objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
objp *= square_size# 用于存储每张图像的位姿矩阵
pose_matrices = []# 获取所有棋盘格图像的路径
images = glob.glob('board_image/*.png')for image_path in images:# 读取图像img = cv2.imread(image_path)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 检测棋盘格角点ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)if ret:# 优化角点位置到亚像素级精度criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)# 计算标定板在相机坐标系下的位姿(标定板在相机坐标系下的位姿)ret, rvec, tvec = cv2.solvePnP(objp, corners, mtx, dist)# 将旋转向量转换为旋转矩阵rmat, _ = cv2.Rodrigues(rvec)# 组合旋转矩阵和平移向量为位姿矩阵pose_matrix = np.hstack((rmat, tvec))pose_matrices.append(pose_matrix)# 在图像上绘制坐标轴用于可视化axis = np.float32([[3, 0, 0], [0, 3, 0], [0, 0, -3]]).reshape(-1, 3)imgpts, _ = cv2.projectPoints(axis, rvec, tvec, mtx, dist)img = cv2.drawChessboardCorners(img, chessboard_size, corners, ret)corner = tuple(corners[0].ravel().astype(int))# 确保坐标点是以正确的格式传递给 cv2.line 函数img = cv2.line(img, corner, tuple(imgpts[0].ravel().astype(int)), (255, 0, 0), 5)img = cv2.line(img, corner, tuple(imgpts[1].ravel().astype(int)), (0, 255, 0), 5)img = cv2.line(img, corner, tuple(imgpts[2].ravel().astype(int)), (0, 0, 255), 5)cv2.imshow('Pose Estimation', img)cv2.waitKey(0)cv2.destroyAllWindows()# # 保存所有位姿矩阵到文件
# np.save('pose_matrices.npy', np.array(pose_matrices))
#
# 输出所有位姿矩阵
for i, pose_matrix in enumerate(pose_matrices):print(f"Pose matrix for image {i+1}:\n", pose_matrix)

三、实现效果

3.1标定板位姿

3.2标定板到相机的变换矩阵

python">Pose matrix for image 1:[[ 9.54690321e-01  1.63896269e-01  2.48403711e-01 -9.17541763e+00][-1.45600442e-01  9.85200423e-01 -9.04468778e-02 -1.04041170e+01][-2.59551347e-01  5.01810686e-02  9.64424677e-01  8.94162448e+01]]
Pose matrix for image 2:[[ 9.68117431e-01 -2.30857543e-02  2.49430728e-01 -4.40319806e+00][ 5.02887074e-02  9.93383921e-01 -1.03244525e-01 -8.17764301e+00][-2.45396997e-01  1.12496373e-01  9.62873242e-01  8.84715217e+01]]
Pose matrix for image 3:[[  0.77862222  -0.56844737   0.26573487  -4.22080186][  0.61191435   0.78162231  -0.12094374 -12.23688825][ -0.13895415   0.25677646   0.95642961  87.62645824]]
Pose matrix for image 4:[[ 3.65280489e-01 -8.84489869e-01  2.90254777e-01 -4.59486253e-01][ 9.30890782e-01  3.45882851e-01 -1.17504915e-01 -1.47317632e+01][ 3.53775679e-03  3.13117749e-01  9.49707723e-01  8.60033729e+01]]
Pose matrix for image 5:[[ 2.10536679e-02 -9.53945915e-01  2.99238925e-01  2.39861926e+00][ 9.94637523e-01 -1.03281967e-02 -1.02905426e-01 -1.39552702e+01][ 1.01256809e-01  2.99800800e-01  9.48612955e-01  8.52141515e+01]]
Pose matrix for image 6:[[-8.08420711e-01 -5.24826800e-01  2.66482240e-01  5.53844533e+00][ 5.25127881e-01 -8.47600539e-01 -7.62498222e-02 -8.15940333e+00][ 2.65888440e-01  7.82953186e-02  9.60819015e-01  8.55355115e+01]]
Pose matrix for image 7:[[-0.90930726  0.32912313  0.25463362  0.90404698][-0.3662639  -0.92345944 -0.11433903 -3.69221782][ 0.1975122  -0.19723241  0.96025429 87.56252021]]


http://www.ppmy.cn/news/1475778.html

相关文章

vue 项目代码架构

Vue项目的代码架构通常遵循一定的组织结构和约定,以提高项目的可维护性、可扩展性和可读性。以下是对Vue项目代码架构的详细解析: 一、项目目录结构 Vue项目的目录结构通常包括以下几个关键部分: 根目录: package.json&#x…

如何使用这个XMLHttpRequest?

ajax含义:async javascript and XML;是异步的JS和XML;是实现页面局部刷新的技术(是一门独立的技术)。 为什么在js内能够使用呢?是因为ajax在浏览器内内置了一个核心对象,--》XMLHttpRequest(低版本的IE浏览器没有) 步…

Jetson-AGX-Orin gstreamer+rtmp+http-flv 推拉流

Jetson-AGX-Orin gstreamerrtmphttp-flv 推拉流 Orin是ubuntu20.04 ARM64架构的系统,自带gstreamer 1、 测试摄像头 测试摄像头可以用v4l2-ctl命令或者用gst-launch-1.0 #用v4l2-ctl测试摄像头,有尖角符号持续打印则正常 v4l2-ctl -d /dev/video0 --set-fmt-vid…

MySQL篇:事务

1.四大特性 首先,事务的四大特性:ACID(原子性,一致性,隔离性,持久性) 在InnoDB引擎中,是怎么来保证这四个特性的呢? 持久性是通过 redo log (重做日志&…

暗黑魅力:Xcode全面拥抱应用暗黑模式开发指南

暗黑魅力:Xcode全面拥抱应用暗黑模式开发指南 随着苹果在iOS 13和iPadOS 13中引入暗黑模式,用户可以根据自己的喜好或环境光线选择不同的界面主题。作为开发者,支持暗黑模式不仅能提升用户体验,还能彰显应用的专业性。Xcode提供了…

AI数字人直播saas系统源码分析与解读,哪家部署的系统更具优势?

随着AI数字人直播的应用潜力持续展现,越来越多的创业者都有了打造AI数字人直播saas系统,从而通过为各大企业提供AI数字人直播等服务来获得收益。在此背景下,各大数字人源码厂商所部署的AI数字人直播saas系统源码质量成为了众多创业者的重点关…

概率论原理精解【3】

文章目录 向量值向量值函数导数向量值函数定义性质应用示例 向量值函数的导数定义性质应用 向量值 向量值函数导数 D n ⊂ R n , 向量值函数 f : D n → R m D^n \subset R^n,向量值函数f:D^n\rightarrow R^m Dn⊂Rn,向量值函数f:Dn→Rm 1. 向量值函数 f ( f 1 , f 2 , . . …

外呼系统用回拨模式打电话有什么优势

外呼系统采用回拨模式的优势主要体现在以下几个方面: 1. 提高工作效率 - 回拨模式允许通过一键拨打客户电话,一旦客户接听,即可立即进行沟通,大大缩短了拨号等待时间和无效通话时间。 - 与传统的外呼方式相比,回拨模式…

OSU!题解(概率dp)

题目:OSU! - 洛谷 思路: 设E()表示截止到i所获得的分数; 对于到i点的每一个l,如果第i1点为1,那么会新增分数3*l^23*l1; 就有递推公式方程: E()E()p[i1]p*(3*l^23*l1);(p代表截止到i获得长度l的概率)&a…

策划分销策略中的AI智能名片O2O商城小程序应用探索

摘要:在数字经济时代,企业面临着前所未有的市场竞争压力,传统的分销模式已难以满足快速变化的市场需求。随着人工智能(AI)技术的不断成熟与移动互联网的普及,AI智能名片O2O商城小程序作为一种新兴的分销工具…

【区块链 + 智慧政务】涉税行政事业性收费“e 链通”项目 | FISCO BCOS应用案例

国内很多城市目前划转至税务部门征收的非税收入项目已达 17 项,其征管方式为行政主管部门核定后交由税务 部门征收。涉税行政事业性收费受限于传统的管理模式,缴费人、业务主管部门、税务部门、财政部门四方处于 相对孤立的状态,信息的传递靠…

http协议,tomcat的作用

HTTP 概念:Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。 特点: 1.基于TCP协议:面向连接,安全 2. 基于请求-响应模型的:一次请求对应一次响应 3HTTP协议是无状态的协议:对于事务处理没有记忆能…

原来,BI数据分析也是有模板的

在当今数据驱动的时代,商业智能(BI)数据分析已经成为企业决策的重要工具。然而,很多人可能并不了解,BI数据分析并非从零开始,而是可以依托现成的模板和解决方案来快速搭建和实施的。以奥威BI方案为例&#…

ARM功耗管理之功耗数据与功耗收益评估

安全之安全(security)博客目录导读 思考:功耗数据如何测试?功耗曲线?功耗收益评估? UPF的全称是Unified Power Format,其作用是把功耗设计意图(power intent)传递给EDA工具, 从而帮…

Hadoop发展史和生态圈介绍

目录 一、Hdoop概述 二、Hadoop生态组件 三、大数据的技术生态体系 四、Hadoop发展历史 4.1 概述 4.2 Hadoop历史发展节点 4.2.1 2002-2004年理论阶段 4.2.2 2005-2008年Hadoop的问世与崛起 4.2.3 2009-2017年Hadoop助力大数据行业的发展 4.2.4 至今 五、Hadoop优势特…

AWS ECS实现低风险的服务更新:创建新服务和流量切换

在使用Amazon ECS (Elastic Container Service)进行容器化应用部署时,我们经常需要更新服务。但直接更新现有服务可能会带来风险,尤其是在生产环境中。本文将介绍一种低风险的服务更新方法:基于原有服务创建新服务,并逐步切换流量。 方法概述 基于原有ECS服务的配置创建新的服…

【LINUX】pr_info函数开发摸索

1、打印开关可随时控制,开机如果要修改是否打印日志的话,需要修改代码重新编译内核才行,其实如果真要搞,应该有其他方法; 2、打印次数,当前代码里边写的是1000次,其实可以根据传参动态修改打印…

Selenium 元素操作 WebElement 对象

通过 find_element() 方法找到的元素对象就是 WebElement 类型。clear(): 清除文本 send_keys(value): 模拟按键输入 click(): 单击元素 submit(): 提交表单(有些不提供搜索按钮,通过键盘上的回车键完成提交,可以通过 submit 模拟) size: 获…

阿里云Linux中安装MySQL,并使用navicat连接以及报错解决

首先查询是否安装MySQL // linux 使用yum安装或者rpm安装。(就是一个安装工具类似于applStore,brew不必在意) // 区别:yum会自动安装你要安装的东西的其他依赖,rpm不会但会提示你需要安装的东西,比较麻烦,所以采用yum安…

【游戏客户端】大话slg玩法架构(三)建筑控件

【游戏客户端】大话slg玩法架构(三)建筑控件 大家好,我是Lampard家杰~~ 今天我们继续给大家分享SLG玩法的实现架构,关于SLG玩法的介绍可以参考这篇上一篇文章:【游戏客户端】制作率土之滨Like玩法 PS:和之前…