天天看点

PCL - MLS代碼研讀(九)- MLS入口 - process函數PCL - MLS代碼研讀(九)- MLS入口 - process函數

PCL - MLS代碼研讀(九)- MLS入口 - process函數

前言

在PCL - MLS代碼研讀(一)中,我們看到了MLS模塊的入口函數是

process

,這也是本篇要介紹的內容。

process

process

為入口函數,做完一些檢查及必要的初始化之後調用

performProcessing

//
template <typename PointInT, typename PointOutT> void
pcl::MovingLeastSquares<PointInT, PointOutT>::process (PointCloudOut &output)
{
  //process為入口函數,做完一些檢查及必要的初始化之後調用performProcessing
           

corresponding_input_indices_

的類型是

PointIndicesPtr

,它的底層是

std::shared_ptr

,使用

std::shared_ptr::reset

來將

corresponding_input_indices_

管理的指標替換為

new PointIndices

//用來儲存輸出點雲中每個點在輸入點雲中對應的點
  // Reset or initialize the collection of indices
  corresponding_input_indices_.reset (new PointIndices);
           

將法向量提前計算好:

// Check if normals have to be computed/saved
  if (compute_normals_)
  {
    //將normals_管理的指標替換為new NormalCloud
    normals_.reset (new NormalCloud);
    // Copy the header
    normals_->header = input_->header;
    // Clear the fields in case the method exits before computation
    normals_->width = normals_->height = 0;
    normals_->points.clear ();
  }
           

準備

output

點雲:

// Copy the header
  output.header = input_->header;
  output.width = output.height = 0;
  output.clear ();
           

檢查

search_radius_

sqr_gauss_param_

是否合理,如果不合理隨即退出:

if (search_radius_ <= 0 || sqr_gauss_param_ <= 0)
  {
    PCL_ERROR ("[pcl::%s::process] Invalid search radius (%f) or Gaussian parameter (%f)!\n", getClassName ().c_str (), search_radius_, sqr_gauss_param_);
    return;
  }
           

如果上採樣方法是

DISTINCT_CLOUD

,那麼必須設定好成員變數

distinct_cloud_

// Check if distinct_cloud_ was set
  if (upsample_method_ == DISTINCT_CLOUD && !distinct_cloud_)
  {
    PCL_ERROR ("[pcl::%s::process] Upsample method was set to DISTINCT_CLOUD, but no distinct cloud was specified.\n", getClassName ().c_str ());
    return;
  }
           

PCLBase::initCompute

,作用是檢查

input_

是否存在,並準備好

indices_

fake_indices_

等變量:

//PCLBase::initCompute,檢查input_是否存在,並準備好indices_,fake_indices_等變量
  if (!initCompute ())
    return;
           

初始化kdtree,並將搜索方法設為kdtree。然後將

tree

的搜索範圍設定為

input_

點雲。

// Initialize the spatial locator
  if (!tree_)
  {
    KdTreePtr tree;
    if (input_->isOrganized ())
      tree.reset (new pcl::search::OrganizedNeighbor<PointInT> ());
    else
      tree.reset (new pcl::search::KdTree<PointInT> (false));
    //設定tree_及search_method_
    setSearchMethod (tree);
  }

  // Send the surface dataset to the spatial locator
  tree_->setInputCloud (input_);
           

根據上採樣方法

upsample_method_

設定各自需要的變數。

switch (upsample_method_)
  {
    // Initialize random number generator if necessary
    case (RANDOM_UNIFORM_DENSITY):
    {
      std::random_device rd;
      rng_.seed (rd());
      const double tmp = search_radius_ / 2.0;
      rng_uniform_distribution_.reset (new std::uniform_real_distribution<> (-tmp, tmp));

      break;
    }
    case (VOXEL_GRID_DILATION):
    case (DISTINCT_CLOUD):
    {
      if (!cache_mls_results_)
        PCL_WARN ("The cache mls results is forced when using upsampling method VOXEL_GRID_DILATION or DISTINCT_CLOUD.\n");

      cache_mls_results_ = true;
      break;
    }
    default:
      break;
  }
           

依據是否需要儲存MLS的結果

cache_mls_results_

,來決定

mls_results_

的大小。

if (cache_mls_results_)
  {
    mls_results_.resize (input_->size ());
  }
  else
  {
    //需要一個dummy result?
    mls_results_.resize (1); // Need to have a reference to a single dummy result.
  }
           

到這裡才是實際進行曲面重建的地方,

performProcessing

將留到下一篇做介紹。

// Perform the actual surface reconstruction
  performProcessing (output);
           

後處理:如果

output[i]

有法向量和曲率欄位,則設成跟

(*normals_)[i]

一樣。

if (compute_normals_)
  {
    normals_->height = 1;
    normals_->width = normals_->size ();

    for (std::size_t i = 0; i < output.size (); ++i)
    {
      using FieldList = typename pcl::traits::fieldList<PointOutT>::type;
      //如果output[i]有"normal_x"這個欄位的話,就將它設為(*normals_)[i].normal_x
      pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output[i], "normal_x", (*normals_)[i].normal_x));
      pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output[i], "normal_y", (*normals_)[i].normal_y));
      pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output[i], "normal_z", (*normals_)[i].normal_z));
      pcl::for_each_type<FieldList> (SetIfFieldExists<PointOutT, float> (output[i], "curvature", (*normals_)[i].curvature));
    }

  }
           

後處理:設定輸出點雲

output

的寬高。

// Set proper widths and heights for the clouds
  output.height = 1;
  output.width = output.size ();
           

pcl::PCLBase::deinitCompute

pcl::PCLBase::deinitCompute

函數沒做什麼,就只有return true而已:

deinitCompute ();
}
           

继续阅读