我正在编写一个手眼校准程序。
为了做到这一点,我将安装在机械臂上的摄像头移动到20个不同的位置,看着一个单一的aruco标记。
平移向量非常稳定,但旋转轴会闪烁,从而在生成的校准矩阵中引入误差。
因此,我想平均X个帧的旋转向量(aruco库确实分别返回旋转向量和平移向量)。
下面是代码的重要部分
cv::aruco::detectMarkers(image, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);
outputImage = image.clone();
cv::aruco::drawDetectedMarkers(outputImage, markerCorners, markerIds);
cv::aruco::estimatePoseSingleMarkers(markerCorners, 0.05, camMatrix, distCoeffs, rvecs, tvecs);
rvecs实际上是旋转向量的向量,由于只有一个aruco标记,因此只有一个成员。
如果在帧中发现标记,
if (rvecs.size() == 1) { // There is one marker good frame
framesFound++;
for (int i = 0; i < 3; i++) {
avgRvecs[i] =+ rvecs[0][i];
avgTvecs[i] =+ tvecs[0][i];
}
}
并且在处理了所有期望的要平均的帧之后,
if (framesFound == 0 ) { // No frames with markers...
} else {
for (int i = 0; i < 3; i++) {
avgRvecs[i] = avgRvecs[i] / framesFound;
avgTvecs[i] = avgTvecs[i] / framesFound;
}
cv::drawFrameAxes(outputImage, camMatrix, distCoeffs, avgRvecs, avgTvecs, 0.1);
一帧画面
平均10帧
1条答案
按热度按时间vybvopom1#
由于Aruco标记的姿势估计通常使用IPPE(solvePnP引擎盖下的算法)完成,因此旋转结果中可能会有一些“奇点”。
平均旋转可能是一个很好的解决方案,因为它可以作为一个低通滤波器,但您需要记住,如果您正在寻求精度,这可能不是最适合使用的滤波器。
大多数时候,我们喜欢操纵欧拉角、直接余弦矩阵或罗德里格斯角。不幸的是,这些都不是平均Angular 值的理想解决方案。如果你想操纵Angular 而不出现数学错误,我绝对推荐你看看四元数。
一些现有的帖子提出了有趣的四元数方法:
"Average" of multiple quaternions?
https://math.stackexchange.com/questions/1984608/average-of-3d-rotations
数学可能有点可怕,但帖子附带了写得很好的代码示例。