PnP解算及SolvePnp用法

[复制链接]
查看728 | 回复0 | 2023-8-23 11:39:00 | 显示全部楼层 |阅读模式
1 PnP解算

PnP标题:Perspective-n-Point标题。
参考下图,

给定n个3D空间参考点,以及各点在相机图像上对应的成像点,求参考点所在坐标系与相机的空间关系。
即:
已知条件1:给定匹配点对:世界坐标系(图中OwXwYwZw)下的n个3D点坐标及其对应在图像坐标系(图中ouv)下的2D点坐标。
已知条件2:相机的内参。
求:世界坐标系OwXwYwZw与相机坐标系OcXcYcZc之间的位姿变更关系。
PnP标题的用途:相机位姿获取,物体位姿丈量,AR/VR,机器人操纵,SLAM中位姿初值求解……
常用解法:DLT,P3P,EPnP,UPnP。
2 OpenCV的solvePnP

2.1 函数原型界说

OpenCV提供了PnP标题的解算函数,且包罗有多种解法。
有以下两个函数。
1) solvePnP

  1. bool solvePnP( InputArray objectPoints, InputArray imagePoints,
  2.                             InputArray cameraMatrix, InputArray distCoeffs,
  3.                             OutputArray rvec, OutputArray tvec,
  4.                             bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE );
复制代码
作用:根据3D-2D点对应关系,得到物体的位姿。
此函数返盘旋转和平移向量,可用来将物体坐标系中的3D点变更到相机坐标系下。
2) solvePnPRansac

  1. bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints,
  2.                                   InputArray cameraMatrix, InputArray distCoeffs,
  3.                                   OutputArray rvec, OutputArray tvec,
  4.                                   bool useExtrinsicGuess = false, int iterationsCount = 100,
  5.                                   float reprojectionError = 8.0, double confidence = 0.99,
  6.                                   OutputArray inliers = noArray(), int flags = SOLVEPNP_ITERATIVE );
复制代码
与solvePnP功能雷同,但这个函数使用RANSAC算法剔除非常样本。
RANSAC:Random Sample Consensus(随机抽样同等)。它是根据一组包罗非常数据的样本数据集,计算出数据的数学模子参数,得到有用样本数据的算法。它于1981年由Fischler和Bolles开始提出。
因此RANSAC使得PnP函数可以或许抵抗非常值。
2.2 函数参数

参数:
objectPoints:世界坐标系(上图中OwXwYwZw)下的3D点坐标数组
imagePoints:图像(上图中ouv)中对应3D点的成像点坐标数组
cameraMatrix:相机内参矩阵,3×3
distCoeffs:相机畸变系数数组,可以为NULL,此时视为无畸变。
rvec和tvec:计算结果输出,rvec为旋转向量,tvec为平移向量,两者归并表达的是物体团体(即世界坐标系)在相机坐标系中的位姿
以下参数为可选:
useExtrinsicGuess,这个参数仅用于flags=SOLVEPNP_ITERATIVE,此值假如为true (1),必要rvec和tvec有输入值,以便函数把输入值作为旋转和平移的估计初始值.
flags:PnP解算方法,详见下节。
solvePnPRansac必要的可选参数
iterationsCount:迭代次数;
reprojectionError:RANSAC使用的内点阈值,即思量作为内点的观察点与计算点投影之间的最大允许距离
confidence:算法得到有用结果的概率;
inliers:包罗 objectPoints 和 imagePoints 中的内点索引的输出向量 .
2.3 PnP解算方法(flags取值)


  • SOLVEPNP_ITERATIVE:缺省方法,基于 Levenberg-Marquardt 优化的迭代方法,使重投影偏差最小化
  • SOLVEPNP_P3P:方法基于论文 X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang “Complete Solution Classification for the Perspective-Three-Point Problem”
  • SOLVEPNP_AP3P:方法基于论文 T. Ke, S. Roumeliotis "An Efficient Algebraic Solution to the Perspective-Three-Point Problem
  • SOLVEPNP_EPNP:方法基于论文 F. Moreno-Noguer, V. Lepetit and P. Fua “EPnP: Efficient Perspective-n-Point Camera Pose Estimation”
  • SOLVEPNP_DLS:方法基于论文 J. Hesch and S. Roumeliotis. “A Direct Least-Squares (DLS) Method for PnP”
  • SOLVEPNP_UPNP:方法基于论文 A. Penate-Sanchez, J. Andrade-Cetto, F. Moreno-Noguer. “Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation”
  • SOLVEPNP_IPPE:方法基于论文 T. Collins and A. Bartoli. “Infinitesimal Plane-Based Pose Estimation”
  • SOLVEPNP_IPPE_SQUARE:方法基于论文 Toby Collins and Adrien Bartoli. “Infinitesimal Plane-Based Pose Estimation”
  • SOLVEPNP_SQPNP:方法基于论文 “A Consistently Fast and Globally Optimal Solution to the Perspective-n-Point Problem” by G. Terzakis and M.Lourakis
2.4 solvePnp的点对

一样平常来说,解算PnP,最少必要4个物体点与其成像点构成的点对,几个特例如下:

  • 当SOLVEPNP_ITERATIVE而且useExtrinsicGuess=true时(rvec和tvec有初值),所需的点数最小可以为3;
  • P3P methods (SOLVEPNP_P3P, SOLVEPNP_AP3P): 需且仅需4个输入点来得到唯一解;
  • SOLVEPNP_IPPE:输入点数必须 >= 4,而且所有物体点必须共面;
  • SOLVEPNP_IPPE_SQUARE:对点的次序有规定,具体这里略;
    除了这几个外,其它方法(flags)要求点的数量必须 >= 4 ,对物体点位置次序等没有特殊规定。
3 solvePnP使用

使用solvePnP前,必要已具备如下参数:
  1. vector<Point3f>objPts;        //3D点数组,世界坐标系物体点坐标,至少4个点
  2. vector<Point2f>imgPts;        //2D点数组,与以上物体点一一对应的图像点坐标
  3. Mat cameraMatrix;        //相机内参矩阵,3x3矩阵
  4. Mat distCoeff;        //相机畸变系数矩阵,我一般是用1x5矩阵,如果相机没有畸变,可以把所有元素置为0
复制代码
然后调用
  1. Mat rvec, tvec;        //声明用于接收运算结果的两个矢量
  2. solvePnP(objPts, imgPts, cameraMatrix, distCoeff, rvec, tvec);
复制代码
得到解算结果后,rvec为旋转矢量形式,后续计算不方便,以是一样平常会用Rodrigues公式转为旋转矩阵,以下直接将rvec和tvec一起转为位姿矩阵
  1. Mat wldInCam = Mat::zeros(4, 4, CV_64FC1);
  2. Rodrigues(rvec, wldInCam(Rect(0, 0, 3, 3)));
  3. tvec.copyTo(wldInCam(Rect(0, 3, 1, 3)));
复制代码
以上得到的wldInCam即为世界坐标系在相机坐标系中的位姿,假如必要求相机活着界坐标系中的位姿,可取逆即可:
  1. Mat camInWld = wldInCam.inv();
复制代码
参考

[PnP] PnP标题之DLT解法

来源:https://blog.csdn.net/hangl_ciom/article/details/127960154
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则