对OpenMVG中ComputeStructureFromKnownPoses的理解

OpenMVG中这部分讲的就是摄影测量中的空三部分

首先定义一个结构估算对象structure_estimator,然后让其调用structure_estimator.triangulate(sfm_data);即可实现。

原文代码如下:

首先了解一下triangulate函数的参数sfm_data表示的含义:sfm_data储存了所相关的视角Views有哪些,而Views是一个哈希图,定义为using Views = Hash_Map<IndexT, std::shared_ptr<View>>;也就是一系列的键值对,View包含影像的路径、影像索引、内参索引、姿态索引、影像大小信息。

sfm_data储存了每个视图的位姿Poses,而Poses也是一个哈希图using Poses = Hash_Map<IndexT, geometry::Pose3>;Pose3包含旋转矩阵。

sfm_data储存了每个视图的共同的一些内部参数Intrinsics,包含影像的宽和高

sfm_data储存了特征点structure的三维坐标及其对应的二维观察点坐标(像点坐标)以及地面控制点的三维坐标及对应观察点坐标,LandLmarks定义为using Landmarks = Hash_Map<IndexT, Landmark>;Landmark包含三维坐标和观察点的二维坐标和特征索引(对于控制点不用考虑这个特征索引)

第二步是遍历sfm_data中存储的特征点sfm_data.structure进行空三解算,如果解算成功就把成功的landmark赋值给这个特征点,否则就剔除这个特征点。原文代码入口如下:

第三步 空三解算(核心部分)

具体方案是使用RANSAC算法鲁棒估计最好的三维点,且这个三维点必须被大于所规定的最小要求局内点个数(min_required_inliers)的视角所观察到,用人话说就是需要选具有较高重叠度的点进行解算。

核心函数是bool SfM_Data_Structure_Computation_Robust::robust_triangulation
(const SfM_Data & sfm_data,const Observations & obs,Landmark & landmark // X & valid observations
),输入其实是某一个特征点对应的所有视图的像点坐标及其特征信息,输出是解算成功的landmark。

情况一:该点恰好只能被最小要求数量的视角看到,所有的相关视角都要参与解算

情况二:多张都能看到,进行鲁棒性空三估计

for (IndexT i = 0; i < nbIter; ++i)       //迭代可视视角个数的2倍次
  {
    std::vector<uint32_t> samples;
    robust::UniformSample(min_sample_index_, obs.size(), random_generator, &samples);

    Vec3 X;
    // Hypothesis generation
    const auto minimal_sample = ObservationsSampler(obs, samples);

    if (!track_triangulation(sfm_data, minimal_sample, X, etri_method_))
      continue;

    // Test validity of the hypothesis
    if (!track_check_predicate(minimal_sample, sfm_data, X, predicate_binding))
      continue;

    std::deque<IndexT> inlier_set;
    double current_error = 0.0;
    // inlier/outlier classification according pixel residual errors.
    for (const auto & obs_it : obs)
    {
      const View * view = sfm_data.views.at(obs_it.first).get();
      if (!sfm_data.IsPoseAndIntrinsicDefined(view))
        continue;
      const IntrinsicBase & cam =  *sfm_data.GetIntrinsics().at(view->id_intrinsic).get();
      const Pose3 pose = sfm_data.GetPoseOrDie(view);
      if (!CheiralityTest(cam(obs_it.second.x), pose, X))
        continue;
      const double residual_sq = cam.residual(pose(X), obs_it.second.x).squaredNorm();
      if (residual_sq < dSquared_pixel_threshold)
      {
        inlier_set.push_front(obs_it.first);
        current_error += residual_sq;
      }
      else
      {
        current_error += dSquared_pixel_threshold;
      }
    }
    // Does the hypothesis:
    // - is the best one we have seen so far.
    // - has sufficient inliers.
    if (current_error < best_error &&
      inlier_set.size() >= min_required_inliers_)
    {
      best_model = X;
      best_inlier_set = inlier_set;
      best_error = current_error;
    }
  }
  if (!best_inlier_set.empty() && best_inlier_set.size() >= min_required_inliers_)
  {
    // Update information (3D landmark position & valid observations)
    landmark.X = best_model;
    for (const IndexT & val : best_inlier_set)
    {
      landmark.obs[val] = obs.at(val);
    }
  }
  return !best_inlier_set.empty();
}

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周周写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值