点云分割-pcl区域生长算法

目录

  • 写在前面
  • 原理
  • 代码
    • 运行结果
  • 参考

写在前面

1、本文内容
pcl的区域生长算法的使用和原理

2、平台/环境
cmake, pcl
3、转载请注明出处:
https://blog.csdn.net/qq_41102371/article/details/131927376

原理

参考:https://pcl.readthedocs.io/projects/tutorials/en/master/region_growing_segmentation.html#region-growing-segmentation
https://blog.csdn.net/taifyang/article/details/124097186

这里主要将可设置的参数列出:
KSearch: 用于计算法向量的最近邻点数量,针对K近邻搜索求法向量,也可使用半径搜索求法向量:

  normal_estimator.setKSearch(KSearch);// 30
 // normal_estimator.setRadiusSearch(2);

MinClusterSize: 至少多少点才能构成一个簇
NumberOfNeighbours: 区域生长的近邻点数量
SmoothnessThreshold: 法向量角度阈值,判断当前邻域点和种子点的法向量夹角是否小于此阈值,小于则将当前邻域点加入当前簇
CurvatureThreshold: 曲率阈值,若当前近邻点与种子点夹角小于法向量阈值,并且曲率小于此曲率阈值,则加入种子点

代码

新建文件夹

mkdir pcl_region_growging_segmentation
cd pcl_region_growging_segmentation

pcl_region_growging_segmentation/CMakeLists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(region_growing_segmentation)

find_package(PCL 1.5 REQUIRED)

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

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

pcl_region_growging_segmentation/region_growging_segmentation.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

template <typename PointT>
void PcdVisualizer(pcl::PointCloud<PointT> cloud, bool coordinate = false)
{
  pcl::visualization::PCLVisualizer::Ptr viewer(
      new pcl::visualization::PCLVisualizer("3D Viewer"));
  viewer->setBackgroundColor(0, 0, 0);
  pcl::PointCloud<PointT>::Ptr cloud_ptr(new pcl::PointCloud<PointT>);
  *cloud_ptr = cloud;
  viewer->addPointCloud<PointT>(cloud_ptr, "cloud");
  if (coordinate)
  {
    viewer->addCoordinateSystem(1.0, "global");
  }
  while (!viewer->wasStopped())
  {
    viewer->spinOnce(100);
    // td::this_thread::sleep_for(100ms);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
}

int main(int argc, char **argv)
{
  if (argc < 2)
  {
    std::cout << "please input a pcd" << std::endl;
    return 0;
  }
  std::string pcd_path = argv[1];
  std::cout << "pcd_path: " << pcd_path << std::endl;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ>(pcd_path, *cloud) == -1)
  {
    std::cout << "Cloud reading failed." << std::endl;
    return (-1);
  }

  int KSearch = std::atoi(argv[2]);
  int MinClusterSize = std::atoi(argv[3]);
  int NumberOfNeighbours = std::atoi(argv[4]);
  double SmoothnessThreshold = std::atof(argv[5]);
  double CurvatureThreshold = std::atof(argv[6]);

  std::cout << "KSearch: " << KSearch << std::endl;
  std::cout << "MinClusterSize: " << MinClusterSize << std::endl;
  std::cout << "NumberOfNeighbours: " << NumberOfNeighbours << std::endl;
  std::cout << "SmoothnessThreshold: " << SmoothnessThreshold << std::endl;
  std::cout << "CurvatureThreshold: " << CurvatureThreshold << std::endl;

  pcl::search::Search<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
  pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
  normal_estimator.setSearchMethod(tree);
  normal_estimator.setInputCloud(cloud);
  normal_estimator.setKSearch(KSearch);// 30
  // normal_estimator.setRadiusSearch(2);
  normal_estimator.compute(*normals);

  pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
  reg.setMinClusterSize(MinClusterSize); //50
  reg.setMaxClusterSize(1000000);
  reg.setSearchMethod(tree);
  reg.setNumberOfNeighbours(NumberOfNeighbours); //30
  reg.setInputCloud(cloud);
  reg.setInputNormals(normals);
  reg.setSmoothnessThreshold(SmoothnessThreshold / 180.0 * M_PI); //5.0
  reg.setCurvatureThreshold(CurvatureThreshold); //1.0

  std::vector<pcl::PointIndices> clusters;
  reg.extract(clusters);

  std::cout << "Number of clusters is equal to " << clusters.size() << std::endl;
  std::cout << "First cluster has " << clusters[0].indices.size() << " points." << std::endl;
  std::cout << "These are the indices of the points of the initial" << std::endl
            << "cloud that belong to the first cluster:" << std::endl;
  int counter = 0;
  // while (counter < clusters[0].indices.size ())
  // {
  //   std::cout << clusters[0].indices[counter] << ", ";
  //   counter++;
  //   if (counter % 10 == 0)
  //     std::cout << std::endl;
  // }
  std::cout << std::endl;

  pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud();
  PcdVisualizer(*colored_cloud);

  return (0);
}

windows: pcl_region_growging_segmentation/compile.bat

cmake -DCMAKE_BUILD_TYPE=Release -DPCL_DIR="your pcl path whcih including cmake files of pcl" -S ./ -B ./build
cmake --build ./build --config Release --parallel 8 --target ALL_BUILD

for example:

-DPCL_DIR="D:/carlos/install/PCL 1.10.0/cmake"

linux: pcl_region_growging_segmentation/compile.sh

cmake -DCMAKE_BUILD_TYPE=Release -DPCL_DIR="your pcl path whcih including cmake files of pcl" -S ./ -B ./build
cmake --build ./build --config Release --parallel 8 

运行结果

windows: pcl_region_growging_segmentation/run.bat

set PATH=D:\carlos\install\PCL 1.10.0\bin;D:\carlos\install\PCL 1.10.0\3rdParty\FLANN\bin;D:\carlos\install\PCL 1.10.0\3rdParty\VTK\bin;D:\carlos\install\PCL 1.10.0\3rdParty\Qhull\bin;D:\carlos\install\PCL 1.10.0\3rdParty\OpenNI2\Tools;%PATH%
.\build\Release\region_growing_segmentation.exe ^
C:\Users\12538\Downloads\region_growing_tutorial.pcd ^
50 500 30 5 1.0

其中set PATH是设置环境变量,用于运行时能够找到pcl所需要的dll
pcl提供的测试数据:https://raw.github.com/PointCloudLibrary/data/master/tutorials/region_growing_tutorial.pcd
点云分割-pcl区域生长算法_第1张图片

包含建筑,车辆,树木的一个点云数据:

参考

文中已列出

主要做激光/影像三维重建,配准、分割等常用点云算法,技术交流、咨询可私信

你可能感兴趣的:(点云算法,pcl,点云算法,点云分割,pcl,c++,cmake)