天天看點

colmap 子模型對齊中的 Ransac

這段代碼,用 src 和 ref_images 儲存 在 src重建和ref 重建中都存在的圖像。

重建類包含有關單個重模組化型的所有資訊。 它由映射和捆綁調整類使用,并且可以寫入磁盤和從磁盤讀取。重建類中的圖像類:

圖像類是儲存有關圖像的資訊的類。 圖像是在某個位置(參數化為姿勢)拍攝的一台相機的産物。 一個圖像可以與多個其他圖像共享一個相機,如果它的内在特性是相同的

for (size_t i = 0; i < common_image_ids.size(); ++i) {
    src_images[i] = &src_reconstruction.Image(common_image_ids[i]);
    ref_images[i] = &ref_reconstruction.Image(common_image_ids[i]);
  }
           

然年調用 ransac 進行兩個子模型的對準

如下是Estimate的參數,可見其隻需要兩個 圖像清單(src_images 和 ref_images),傳回是一個Report(涵蓋了模型對其的結果資料和是否成功布爾判斷吧應該)

typename LORANSAC<Estimator, LocalEstimator, SupportMeasurer, Sampler>::Report
LORANSAC<Estimator, LocalEstimator, SupportMeasurer, Sampler>::Estimate(
    const std::vector<typename Estimator::X_t>& X,
    const std::vector<typename Estimator::Y_t>& Y) {
           

下面應該是一些準備工作,num_samples就是采樣數,程式中 采樣數=兩模型共有的圖檔數,比如共有 10張圖 那麼ransac就采樣10次,

ransac應該是估計出滿足這10張圖檔的一個模型

,嗯。

CHECK_EQ(X.size(), Y.size());

  const size_t num_samples = X.size();

  typename RANSAC<Estimator, SupportMeasurer, Sampler>::Report report;
  report.success = false;
  report.num_trials = 0;

  if (num_samples < Estimator::kMinNumSamples) {
    return report;
  }
           

這邊是申請一些變量,變量的含義在注釋中

//最優的模型解
  typename SupportMeasurer::Support best_support;
  typename Estimator::M_t best_model;
  bool best_model_is_local = false;

  bool abort = false;
//最大的殘差
  const double max_residual = options_.max_error * options_.max_error;
// 用于存儲每個 采樣點殘差 的數組
  std::vector<double> residuals(num_samples);
// 
  std::vector<typename LocalEstimator::X_t> X_inlier;
  std::vector<typename LocalEstimator::Y_t> Y_inlier;
// 臨時的全局 Estimator
  std::vector<typename Estimator::X_t> X_rand(Estimator::kMinNumSamples);
  std::vector<typename Estimator::Y_t> Y_rand(Estimator::kMinNumSamples);
// 采樣類的執行個體化,參數隻是一個采樣數
  sampler.Initialize(num_samples);
// 确定采樣數
  size_t max_num_trials = options_.max_num_trials;
  max_num_trials = std::min<size_t>(max_num_trials, sampler.MaxNumSamples());
  size_t dyn_max_num_trials = max_num_trials;
           

假如說num_trials為100,意思是進行100輪的ransac估計,下面就是for循環

for (report.num_trials = 0; report.num_trials < max_num_trials;
       ++report.num_trials) {
       // 暫停,跳過一次循環
    if (abort) {
      report.num_trials += 1;
      break;
    }
		// 進行采樣,以common images數量為10為例,這裡随機采樣10個圖檔吧應該
    sampler.SampleXY(X, Y, &X_rand, &Y_rand);

    // 用采樣到的這10張圖檔,估計模型,怎麼估計的,估計的細節是什麼在下一個部落格
    // 傳回不止一個模型,傳回一個模型集合 sample_models
    const std::vector<typename Estimator::M_t> sample_models =
        estimator.Estimate(X_rand, Y_rand);
	// 循環選擇出最好的
    for (const auto& sample_model : sample_models) {
    // 用模型估計殘差,怎麼估計,估計的細節在下一個部落格
      estimator.Residuals(X, Y, sample_model, &residuals);
      CHECK_EQ(residuals.size(), X.size());
	
      const auto support = support_measurer.Evaluate(residuals, max_residual);
	
      // Do local optimization if better than all previous subsets.
      if (support_measurer.Compare(support, best_support)) {
        //如果目前的模型最優 ↓↓↓↓
        best_support = support;
        best_model = sample_model;
        best_model_is_local = false;

        // Estimate locally optimized model from inliers.
        // Estimator 和 LocalEstimator 應該分别指的是全局的ransac估計和
        // 這10個采樣的ransac估計?
        if (support.num_inliers > Estimator::kMinNumSamples &&
            support.num_inliers >= LocalEstimator::kMinNumSamples) {
          X_inlier.clear();
          Y_inlier.clear();
          X_inlier.reserve(support.num_inliers);
          Y_inlier.reserve(support.num_inliers);
          // ransac的政策,如果遇到更好的,就用目前的10張圖檔為基礎,
          // 在這10個的基礎上進行估計
          // X_inlier 和 Y_inlier 是更好的采樣資料
          // 通過計算内點的數量并對所有内點殘差求和來衡量模型的支援度。 
          // 如果它具有更多的内點和更小的殘差總和,則此模型為更好
          for (size_t i = 0; i < residuals.size(); ++i) {
            if (residuals[i] <= max_residual) {
              X_inlier.push_back(X[i]);
              Y_inlier.push_back(Y[i]);
            }
          }
		
          const std::vector<typename LocalEstimator::78h> local_models =
              local_estimator.Estimate(X_inlier, Y_inlier);
			//在更好的采樣結果上重複篩選操作
          for (const auto& local_model : local_models) {
            local_estimator.Residuals(X, Y, local_model, &residuals);
            CHECK_EQ(residuals.size(), X.size());

            const auto local_support =
                support_measurer.Evaluate(residuals, max_residual);

            // 儲存最好的結果
            if (support_measurer.Compare(local_support, best_support)) {
              best_support = local_support;
              best_model = local_model;
              best_model_is_local = true;
            }
          }
        }
		// 調整一下循環次數,優化時間
        dyn_max_num_trials =
            RANSAC<Estimator, SupportMeasurer, Sampler>::ComputeNumTrials(
                best_support.num_inliers, num_samples, options_.confidence,
                options_.dyn_num_trials_multiplier);
      }
		// 特判跳出循環
      if (report.num_trials >= dyn_max_num_trials &&
          report.num_trials >= options_.min_num_trials) {
        abort = true;
        break;
      }
    }
  }