PCL - MLS代碼研讀(十四)- DISTINCT_CLOUD上採樣方法
前言
在PCL - MLS代碼研讀(十一)- computeMLSPointNormal函數中已經介紹了NONE
和SAMPLE_LOCAL_PLANE
上採樣方法,並且在PCL - MLS代碼研讀(十三)- RANDOM_UNIFORM_DENSITY上採樣方法中介紹了RANDOM_UNIFORM_DENSITY
上採樣方法,本篇主要介紹五種上採樣方法中的第四種:DISTINCT_CLOUD
上採樣方法。
成員變數
protected
成員變數:
/** \brief The distinct point cloud that will be projected to the MLS surface. */
PointCloudInConstPtr distinct_cloud_;
在DISTINCT_CLOUD
上採樣方法中,我們會對輸入點雲外的另一個點雲中每一個非無窮遠的點都做投影,並把投影結果加入輸出點雲中。此處定義的成員變數distinct_cloud_
即是被投影的點雲。
setter & getter
public
成員函數,這兩個函數是為distinct_cloud_
成員變數的setter和getter。
/** \brief Set the distinct cloud used for the DISTINCT_CLOUD upsampling method. */
inline void
setDistinctCloud (PointCloudInConstPtr distinct_cloud) { distinct_cloud_ = distinct_cloud; }
/** \brief Get the distinct cloud used for the DISTINCT_CLOUD upsampling method. */
inline PointCloudInConstPtr
getDistinctCloud () const { return (distinct_cloud_); }
process函數
在process
函數中,僅將cache_mls_results_
設為true
後,就調用performProcessing (output)
進行曲面重建。
template <typename PointInT, typename PointOutT> void
pcl::MovingLeastSquares<PointInT, PointOutT>::process (PointCloudOut &output)
{
//...
// 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;
}
//...
switch (upsample_method_)
{
// Initialize random number generator if necessary
case (RANDOM_UNIFORM_DENSITY):
{
//...
}
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;
}
//...
// Perform the actual surface reconstruction
performProcessing (output);
//...
}
performProcessing函數
template <typename PointInT, typename PointOutT> void
pcl::MovingLeastSquares<PointInT, PointOutT>::performUpsampling (PointCloudOut &output)
{
if (upsample_method_ == DISTINCT_CLOUD)
{
corresponding_input_indices_.reset (new PointIndices);
對distinct_cloud_
中的每一個點都做以下事情:
for (std::size_t dp_i = 0; dp_i < distinct_cloud_->size (); ++dp_i) // dp_i = distinct_point_i
{
如果distinct_cloud_
中有無窮遠的點,就忽視它:
// Distinct cloud may have nan points, skip them
if (!std::isfinite ((*distinct_cloud_)[dp_i].x))
continue;
尋找input_
點雲中距離(*distinct_cloud_)[dp_i]
最近的點,其索引為input_index
:
// Get 3D position of point
//Eigen::Vector3f pos = (*distinct_cloud_)[dp_i].getVector3fMap ();
pcl::Indices nn_indices;
std::vector<float> nn_dists;
tree_->nearestKSearch ((*distinct_cloud_)[dp_i], 1, nn_indices, nn_dists);
const auto input_index = nn_indices.front ();
如果input_
點雲中最近鄰的投影結果是無效的,則跳過:
// If the closest point did not have a valid MLS fitting result
// OR if it is too far away from the sampled point
// 這裡似乎沒有排除太遠的點?
if (mls_results_[input_index].valid == false)
continue;
獲取(*distinct_cloud_)[dp_i]
的坐標,接下來我們會對它做投影:
//distinct_cloud_中的每一個非無窮遠的點都是待投影點
Eigen::Vector3d add_point = (*distinct_cloud_)[dp_i].getVector3fMap ().template cast<double> ();
將剛剛得到的add_point
投影到由input_
點雲中第input_index
個點鄰域點所擬合的曲面上:
//需要5 * nr_coeff_個鄰居?
MLSResult::MLSProjectionResults proj = mls_results_[input_index].projectPoint (add_point, projection_method_, 5 * nr_coeff_);
最後將投影結果添加到output
,normals_
等數據結構中:
addProjectedPointNormal (input_index, proj.point, proj.normal, mls_results_[input_index].curvature, output, *normals_, *corresponding_input_indices_);
}
}
// ...
}
上採樣結果
原始點雲:
用來被投影的點雲(distinct_cloud_
):
投影後的distinct_cloud
:
投影前與投影後的distinct_cloud_
:
輸入點雲與投影後的distinct_cloud
: