OpenCV solvePnP位姿估计

news/2024/12/22 9:01:45/

目录

一、概述

二、实现代码

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. 提高工作效率 - 回拨模式允许通过一键拨打客户电话,一旦客户接听,即可立即进行沟通,大大缩短了拨号等待时间和无效通话时间。 - 与传统的外呼方式相比,回拨模式…