3

我有一个使用 Apriltags3 基准标记的 c++ 应用程序。

这些看起来既快速又稳定,除非标记平面向相机或其附近。

在这些情况下,姿势显着翻转,使姿势数据无法使用。据我了解,这种翻转是方形标记的一个已知问题,因为有两种可能的解决方案来估计姿势。

我该如何改善这种翻转?我努力了:

1 - 使用带有 IPPE_SQUARE 标志的 SolvePnp,我能够返回两个解决方案。

std::vector<cv::Vec3d> rvecsVec, tvecsVec;
std::vector<double> errs;
solvePnPGeneric(markerObjPoints, marker.corners2d, K, D, rvecsVec, tvecsVec, false, cv::SOLVEPNP_IPPE_SQUARE, cv::noArray(), cv::noArray(),errs);

然后我选择最接近前一个姿势的姿势。这工作得很好,直到姿势的旋转通过零(正值到负值),然后旋转轴翻转。

2 - 存储前几个姿势并在 3d 点、2d 角和姿势上运行滑动窗口束调整。这似乎没有任何效果,我仍然看到同样的翻转。

3 - 使用以下内容:

cv::Mat R1;
cv::Rodrigues(rvecsVec[0], R1);
R1 = R1.t();
cv::Mat t1 = -R1 * tvecsVec[0];

cv::Mat R2;
cv::Rodrigues(rvecsVec[1], R2);
R2 = R2.t();
cv::Mat t2 = -R2 * tvecsVec[1];

获取相机相对于标记的姿势。我会假设具有正 X 值(在标记前面)的相机姿势是正确的,但是,当我使用该姿势时:

if (t1.at<double>(0, 0) < 0)
    {
        marker.rvec = rvecsVec[0];
        marker.tvec = tvecsVec[0];
        std::cout << "using pose 0" << std::endl;

    }
    if (t2.at<double>(0, 0) < 0)
    {
        marker.rvec = rvecsVec[1];
        marker.tvec = tvecsVec[1];
        std::cout << "using pose 1" << std::endl;       
    }

我看到与解决方案 1 相同的问题。

4 - 使用立体相机,在每帧中找到标记,对点进行三角测量,然后使用 Eigen SVD 函数找到这些点与从零标记长度创建的一组点之间的刚性变换。

PointsType p1s, p2s;
p1s.push_back(Eigen::Vector3d(-markerLength / 2.f, markerLength / 2.f, 0));
p1s.push_back(Eigen::Vector3d(markerLength / 2.f, markerLength / 2.f, 0));
p1s.push_back(Eigen::Vector3d(markerLength / 2.f, -markerLength / 2.f, 0));
p1s.push_back(Eigen::Vector3d(-markerLength / 2.f, -markerLength / 2.f, 0));

这对翻译很有用,但旋转似乎翻转得更多!

有答案吗?我还能尝试什么?

注意:我用 Aruco 标记测试过,相同的相机和校准,我没有看到这个翻转问题,这似乎是 Apriltags3 的问题。

4

0 回答 0