4

Step我正在尝试对使用同一台相机拍摄的一系列立体图像(类)执行捆绑调整(BA) 。

每个Step都有左右图像(校正和同步)、生成的深度图、左图像的关键点+描述符和 2 个 4x4 矩阵 - 1 个用于局部(图像平面)到全局(3D 世界),以及它的逆矩阵(T_L2G 和 T_G2L分别)。

步骤相对于第一张图像注册。

我正在尝试对结果运行 BA 以改进转换,并且我正在尝试使用 PBA ( https://grail.cs.washington.edu/projects/mcba/ )

设置摄像头的代码:

for (int i = 0; i < steps.size(); i++)
{
    Step& step = steps[i];

    cv::Mat& T_G2L = step.T_G2L;

    cv::Mat R;
    cv::Mat t;

    T_G2L(cv::Rect(0, 0, 3, 3)).copyTo(R);
    T_G2L(cv::Rect(3, 0, 1, 3)).copyTo(t);
    CameraT camera;

    // Camera Parameters
    camera.SetFocalLength((double)m_focalLength); // Same camera, global focal length
    camera.SetTranslation((float*)t.data);
    camera.SetMatrixRotation((float*)R.data);

    if (i == 0)
    {
        camera.SetConstantCamera();
    }

    camera_data.push_back(camera);
}

然后,我通过在所有图像对上运行并匹配(当前使用 SURF)来生成全局关键点。

然后,生成 BA 点数据:

for (size_t i = 0; i < globalKps.size(); i++)
{
    cv::Point3d& globalPoint = globalKps[i].AbsolutePoint;
    cv::Point3f globalPointF((float)globalPoint.x, (float)globalPoint.y, (float)globalPoint.z);
    int num_obs = 0;

    std::vector < std::pair<int/*stepID*/, int/*KP_ID*/>>& localKps = globalKps[i].LocalKeypoints;
    if (localKps.size() >= 2)
    {
        Point3D pointData;
        pointData.SetPoint((float*)&globalPointF);
        // For this point, set all the measurements
        for (size_t j = 0; j < localKps.size(); j++)
        {
            int& stepID = localKps[j].first;
            int& kpID = localKps[j].second;

            int cameraID = stepsLUT[stepID];

            Step& step = steps[cameraID];

            cv::Point3d p3d = step.KeypointToLocal(kpID);

            Point2D measurement = Point2D(p3d.x, p3d.y);
            measurements.push_back(measurement);
            camidx.push_back(cameraID);
            ptidx.push_back((int)point_data.size());

        }
        point_data.push_back(pointData);
    }
}

然后,运行 BA:

ParallelBA pba(ParallelBA::PBA_CPU_FLOAT);
pba.SetFixedIntrinsics(true); // Same camera with known intrinsics

pba.SetCameraData(camera_data.size(), &camera_data[0]);                        //set camera parameters
pba.SetPointData(point_data.size(), &point_data[0]);                            //set 3D point data
pba.SetProjection(measurements.size(), &measurements[0], &ptidx[0], &camidx[0]);//set the projections

pba.SetNextBundleMode(ParallelBA::BUNDLE_ONLY_MOTION);

pba.RunBundleAdjustment();    //run bundle adjustment, and camera_data/point_data will be 

然后,在我遇到问题的地方,从 PBA 中提取数据:

for (int i = 1/*First camera is stationary*/; i < camera_data.size(); i++)
{
    Step& step = steps[i];

    CameraT& camera = camera_data[i];
    int type = CV_32F;
    cv::Mat t(3, 1, type);
    cv::Mat R(3, 3, type);
    cv::Mat T_L2G = cv::Mat::eye(4, 4, type);
    cv::Mat T_G2L = cv::Mat::eye(4, 4, type);

    camera.GetTranslation((float*)t.data);
    camera.GetMatrixRotation((float*)R.data);

    t.copyTo(T_G2L(TranslationRect));       
    R.copyTo(T_G2L(RotationRect));


    cv::invert(T_G2L, T_L2G);

    step.SetTransformation(T_L2G); // Step expects local 2 global transformation
}

一切都按照我期望的方式运行。PBA 报告的初始错误相对较小(目前使用少量成对注册图像进行测试,因此错误不应太大),运行后报告的错误较小。(快速收敛,通常少于 3 次迭代)

然而,当我使用新发现的转换来转储关键点时,云似乎彼此之间的距离更远了。

(我也尝试在 T_G2L 和 T_L2G 之间切换以“让它们更接近”。不起作用)。

我想知道使用它是否缺少一些东西。

4

1 回答 1

0

云层之间的距离似乎更远了

这似乎不是 PBA 特定的问题,而是捆绑调整的一般问题。

执行捆绑平差时,需要对云进行约束,7 个自由度至少有 7 个约束。如果没有,您的云将在 3 个轴、3 个旋转和比例上漂移。

在本地 BA 边界点设置为固定。在完整的 BA 中,通常有一个像原点这样的指定点和一个固定比例和方向的额外点。

于 2020-07-27T11:19:46.077 回答