【PCL】(七) 点云的法线估计

文章目录

  • (七) 法线估计
    • 使用近邻点估计法线
    • 利用积分图像估计法线

(七) 法线估计

点云样例数据:
https://github.com/PointCloudLibrary/pcl/raw/master/test/table_scene_mug_stereo_textured.pcd

使用近邻点估计法线

以下代码实现使用近邻点估计点云所有点的法线。

normal_estimation.cpp

#include 

#include 
#include 
#include 

int main (int, char** argv)
{

  std::string filename = argv[1];
  std::cout << "Reading " << filename << std::endl;
// 定义输入点云数据
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  if (pcl::io::loadPCDFile<pcl::PointXYZ> (filename, *cloud) == -1) // load the file
  {
    PCL_ERROR ("Couldn't read file\n");
    return -1;
  }

  std::cout << "points: " << cloud->size () << std::endl;

  // 创建法线估计对象,并将点云数据传递给它
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
  normal_estimation.setInputCloud (cloud);


  //创建一个空的kdtree,并将其传递给法线估计对象。
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  normal_estimation.setSearchMethod (tree);

  // 定义估计的法线
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

  //利用半径为3cm的球体中的所有邻点进行估计
  normal_estimation.setRadiusSearch (0.03);

  // 进行法线估计
  normal_estimation.compute (*cloud_normals);

  // cloud_normals->size () 应该等于cloud->size ()
  std::cout << "cloud_normals->size (): " << cloud_normals->size () << std::endl;
  // 可视化
  pcl::visualization::PCLVisualizer viewer("PCL Viewer");
  viewer.setBackgroundColor (0.0, 0.0, 0);
  viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, cloud_normals);

  while (!viewer.wasStopped ())
  {
    viewer.spinOnce ();
  }

  return 0;
}


CmakeLists.txt:

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(normal_estimation)

find_package(PCL 1.3 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (normal_estimation normal_estimation.cpp)
target_link_libraries (normal_estimation ${PCL_LIBRARIES})

编译后运行:

./normal_estimation table_scene_mug_stereo_textured.pcd 

【PCL】(七) 点云的法线估计_第1张图片

利用积分图像估计法线

以下代码实现使用积分图像估计点云的法线。

normal_estimation_sing_integral_images.cpp

#include 
#include 
#include 
#include 
#include 
    
int main ()
{
    //加载点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile ("table_scene_mug_stereo_textured.pcd", *cloud);
    
    // 估计法线
    pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);

    pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
    ne.setMaxDepthChangeFactor(0.02f);
    ne.setNormalSmoothingSize(10.0f);
    ne.setInputCloud(cloud);
    ne.compute(*normals);

    /*
    以下是setNormalEstimationMethod可用的法线估计方法:
    COVARIANCE_MATRIX模式创建9个积分图像,以根据其局部邻域的协方差矩阵计算特定点的法线。
    AVERAGE_3D_GRADIENT模式创建6个积分图像来计算水平和垂直3D梯度的平滑版本,并使用这两个梯度之间的叉积来计算法线。
    AVERAGE_DEPTH_CHANGE模式仅创建单个积分图像,并根据平均深度变化计算法线。
    */

    // 可视化
    pcl::visualization::PCLVisualizer viewer("PCL Viewer");
    viewer.setBackgroundColor (0.0, 0.0, 0);
    viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, normals);
    
    while (!viewer.wasStopped ())
    {
      viewer.spinOnce ();
    }
    return 0;
}

CmakeLists.txt

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(normal_estimation_using_integral_images)

find_package(PCL 1.3 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (normal_estimation_using_integral_images normal_estimation_using_integral_images.cpp)
target_link_libraries (normal_estimation_using_integral_images ${PCL_LIBRARIES})

编译后运行:

./normal_estimation_sing_integral_images table_scene_mug_stereo_textured.pcd

【PCL】(七) 点云的法线估计_第2张图片

你可能感兴趣的:(PCL,点云,法线估计)