首先,假设我们只有一个用 给出的标记side = 2 * half_side
。

其次,aruco::detectMarker
返回相机在标记世界中的相对位置。因此,我假设您正在寻找相机世界中角落的坐标。
然后,在标记的空间:
[ half_side ] [ 0 ]
E = [ 0 ], F = [ half_side ]
[ 0 ] [ 0 ]
其中O
正方形的中心具有坐标tvec
(在相机的世界中),并且标记的旋转垫由rot_mat
计算cv::Rodrigues(rvec,rot_mat)
。
现在,使用针孔相机模型P
,凸轮世界中一个点的坐标与标记世界的坐标之间的关系是:
[P_x_cam] [P_x_marker]
[P_y_cam] = rot_mat * [P_y_marker] + tvec
[P_z_cam] [P_z_marker]
例如,在marker的世界中的center O
,在cam的世界中。[0,0,0]
tvec
所以,E
凸轮世界的坐标是:
[E_x_cam] [half_side]
|E_y_cam| = rot_mat * | 0 | + tvec
[E_z_cam] [ 0 ]
神奇的是,它是 的rot_mat
第一列乘以half_size
和的总和tvec
。同样,F
isrot_mat
的第二列的坐标乘以half_size
and tvec
。
现在,可以计算角点,例如
C - O = (E - O) + (F - O), B - O = (E - O) - (F - O)
其中E-O
正是rot_mat
的第一列乘以half_size
。
考虑到所有这些,我们可以编写函数:
vector<Point3f> getCornersInCameraWorld(double side, Vec3d rvec, Vec3d tvec){
double half_side = side/2;
// compute rot_mat
Mat rot_mat;
Rodrigues(rvec, rot_mat);
// transpose of rot_mat for easy columns extraction
Mat rot_mat_t = rot_mat.t();
// the two E-O and F-O vectors
double * tmp = rot_mat_t.ptr<double>(0);
Point3f camWorldE(tmp[0]*half_side,
tmp[1]*half_side,
tmp[2]*half_side);
tmp = rot_mat_t.ptr<double>(1);
Point3f camWorldF(tmp[0]*half_side,
tmp[1]*half_side,
tmp[2]*half_side);
// convert tvec to point
Point3f tvec_3f(tvec[0], tvec[1], tvec[2]);
// return vector:
vector<Point3f> ret(4,tvec_3f);
ret[0] += camWorldE + camWorldF;
ret[1] += -camWorldE + camWorldF;
ret[2] += -camWorldE - camWorldF;
ret[3] += camWorldE - camWorldF;
return ret;
}
注 1:我讨厌 SO 没有 MathJax
注意2:必须有一些我不知道的更快的实现。