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 ();
}