PnP 位姿解算学习笔记

628 字
3 分钟
PnP 位姿解算学习笔记

PnP(Perspective-n-Point)的作用#

已知:

  • 平面图像上的三个点,或者更多
  • 物理世界中对应点之间的三维位置关系
  • 相机的内参矩阵

能够求出:

  • 平面图像上的点在三维空间中的位置(相对于相机坐标系)

cv::solvePnP#

bool cv::solvePnP(
InputArray objectPoints, // 物体坐标系下的三维点
InputArray imagePoints, // 图像坐标系下的二维点
InputArray cameraMatrix, // 相机内参矩阵
InputArray distCoeffs, // 相机畸变参数
OutputArray rvec, // 输出旋转向量
OutputArray tvec, // 输出平移向量
bool useExtrinsicGuess = false, // 是否使用外参初值
int flags = SOLVEPNP_ITERATIVE // 求解方法
);

objectPoints#

是物体坐标系下的三维点,通常是一个 N x 3 的矩阵,表示 N 个三维点的坐标。

对于识别甲板而言,就是左上角、右上角、右下角、左下角四个点的三维坐标。例如:

那么就有:

static const double ARMOR_WIDTH = 0.135; // 装甲板宽度
static const double LIGHTBAR_LENGTH = 0.15; // 灯条长度
static const std::vector<cv::Point3f> objectPoints = {
{-ARMOR_WIDTH / 2, LIGHTBAR_LENGTH / 2, 0}, // 左上角
{ARMOR_WIDTH / 2, LIGHTBAR_LENGTH / 2, 0}, // 右上角
{ARMOR_WIDTH / 2, -LIGHTBAR_LENGTH / 2, 0}, // 右下角
{-ARMOR_WIDTH / 2, -LIGHTBAR_LENGTH / 2, 0} // 左下角
};

在这里我们把甲板的几何中心当做原点,那么剩下的点就可以定位了。

solvePnP 解出的东西#

  • 旋转向量 rvec,即目标平面的朝向
  • 平移向量 tvec,即目标平面到相机的距离

这里 rvectvec 是直接被 solvePnP 函数地址引用了,所以在函数调用后就可以直接使用。

拿到具体参数#

tvec.at<double>(0) // x
tvec.at<double>(1) // y
tvec.at<double>(2) // z
rvec.at<double>(0) // 绕 x 轴旋转角度
rvec.at<double>(1) // 绕 y 轴旋转角度
rvec.at<double>(2) // 绕 z 轴旋转角度

旋转的表示方法#

  1. 旋转向量 rvec 到旋转矩阵 rmat
cv::Mat rmat;
cv::Rodrigues(rvec, rmat); // 罗德里格斯公式
  1. 旋转矩阵 rmat 到欧拉角
cv::Vec3f euler = rotationMatrixToEulerAngles(rmat);
  1. 欧拉角到四元数
cv::Vec4f quaternion = eulerAnglesToQuaternion(euler);

旋转向量、旋转矩阵、欧拉角、四元数有什么区别?#

  • 旋转向量:用一个三维向量表示旋转,向量的方向表示旋转轴,向量的长度表示旋转角度。
  • 旋转矩阵:用一个 3x3 的矩阵表示旋转,矩阵的每一列代表旋转后坐标轴的方向。
  • 欧拉角:用三个角度表示旋转,通常表示绕 x、y、z 轴的旋转角度。
  • 四元数:用四个数表示旋转,可以避免万向节死锁问题,计算效率高。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或投喂支持!

投喂
PnP 位姿解算学习笔记
https://www.infvar.com/posts/pnp/
作者
Dignite
发布于
2026-09-12
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
Dignite
技术,学习,生活,旅行。
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
站点统计
文章
158
分类
5
标签
282
总字数
338,254
运行时长
0
最后活动
0 天前

目录