首页 > 编程语言 >3d激光雷达开发(欧几里得聚类算法)

3d激光雷达开发(欧几里得聚类算法)

时间:2022-11-23 23:01:47浏览次数:78  
标签:cluster 激光雷达 pcl 聚类 filtered include extract cloud 3d



         图形处理里面有一个聚类算法,叫k-means。基本思想就是默认图像里面有k个区域,每个区域都可以内部聚合、外部松散的组合体,找到了这k个区域,就可以实现图像的分割了。正好,点云算法里面也有类似的一个算法,称之为欧几里得聚类算法,​​https://pcl.readthedocs.io/projects/tutorials/en/master/cluster_extraction.html#cluster-extraction​

1、代码内容

#include <pcl/ModelCoefficients.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/search/kdtree.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>


int
main ()
{
// Read in the cloud data
pcl::PCDReader reader;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
reader.read ("table_scene_lms400.pcd", *cloud);
std::cout << "PointCloud before filtering has: " << cloud->size () << " data points." << std::endl; //*

// Create the filtering object: downsample the dataset using a leaf size of 1cm
pcl::VoxelGrid<pcl::PointXYZ> vg;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
vg.setInputCloud (cloud);
vg.setLeafSize (0.01f, 0.01f, 0.01f);
vg.filter (*cloud_filtered);
std::cout << "PointCloud after filtering has: " << cloud_filtered->size () << " data points." << std::endl; //*

// Create the segmentation object for the planar model and set all the parameters
pcl::SACSegmentation<pcl::PointXYZ> seg;
pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());
pcl::PCDWriter writer;
seg.setOptimizeCoefficients (true);
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setMaxIterations (100);
seg.setDistanceThreshold (0.02);

int nr_points = (int) cloud_filtered->size ();
while (cloud_filtered->size () > 0.3 * nr_points)
{
// Segment the largest planar component from the remaining cloud
seg.setInputCloud (cloud_filtered);
seg.segment (*inliers, *coefficients);
if (inliers->indices.size () == 0)
{
std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
break;
}

// Extract the planar inliers from the input cloud
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud (cloud_filtered);
extract.setIndices (inliers);
extract.setNegative (false);

// Get the points associated with the planar surface
extract.filter (*cloud_plane);
std::cout << "PointCloud representing the planar component: " << cloud_plane->size () << " data points." << std::endl;

// Remove the planar inliers, extract the rest
extract.setNegative (true);
extract.filter (*cloud_f);
*cloud_filtered = *cloud_f;
}

// Creating the KdTree object for the search method of the extraction
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud (cloud_filtered);

std::vector<pcl::PointIndices> cluster_indices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance (0.02); // 2cm
ec.setMinClusterSize (100);
ec.setMaxClusterSize (25000);
ec.setSearchMethod (tree);
ec.setInputCloud (cloud_filtered);
ec.extract (cluster_indices);

int j = 0;
for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
for (const auto& idx : it->indices)
cloud_cluster->push_back ((*cloud_filtered)[idx]); //*
cloud_cluster->width = cloud_cluster->size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;

std::cout << "PointCloud representing the Cluster: " << cloud_cluster->size () << " data points." << std::endl;
std::stringstream ss;
ss << "cloud_cluster_" << j << ".pcd";
writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*
j++;
}

return (0);
}

2、代码分析

        整个代码的内容比较简单,主要就是先除去平面,再进行分割。

3、准备CMakeLists.txt

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(cluster)

find_package(PCL 1.2 REQUIRED)

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

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

4、准备sln,开始编译

3d激光雷达开发(欧几里得聚类算法)_聚类算法

5、运行 exe

3d激光雷达开发(欧几里得聚类算法)_#include_02

        不出意外,应该可以看到这几个文件,

3d激光雷达开发(欧几里得聚类算法)_聚类_03

标签:cluster,激光雷达,pcl,聚类,filtered,include,extract,cloud,3d
From: https://blog.51cto.com/feixiaoxing/5881891

相关文章

  • 3d激光雷达开发(ransac的思想)
        前面我们写了平面分割、圆柱分割这两篇文章。细心的同学可能发现,这里面都提到了ransac,那什么是ransac呢?    所谓ransac,全称是randomsampleconsensus,......
  • 3d激光雷达开发(项目练习)
            网上关于pcl的教程很多,大部分都是翻译过来的。但是怎么把pcl这些教程串在一起,做一个简单的项目,这方面的资料不多。今天,正好看到一个范例项目,很有代表性,值得......
  • 3d激光雷达开发(平面分割)
        平面分割是点云数据经常需要处理的一个功能。在很多场景下面,平面数据都是没有用的。这个时候需要考虑的,就是怎么把平面数据从点云当中分割出去。鉴于此,pcl库给......
  • 3d激光雷达开发(圆柱分割)
        和平面分割一样,pcl也支持圆柱分割。使用的方法和平面分割也差不多,都是基于ransac的基本原理。在pcl官方库当中,也给出了参考代码,注意关联的pcd文件,https://pcl.r......
  • 3d激光雷达开发(ndt匹配)
        除了icp匹配之外,ndt匹配也是使用比较多的一种方法。相比较icp而言,ndt匹配花的时间要少一些。此外,ndt匹配还需要输入估计的yaw、pitch、roll、x、y、z,这个可以根......
  • 3d激光雷达开发(icp匹配)
        所谓匹配,其实就是看两个点云数据里面,哪些关键点是一样的。这样就可以把一个点云移动到另外合适的位置,组成一个新的点云。一般来说,单个机器人上面,3d激光扫描到的......
  • ASW3642pin√pin替代TS3DV642无需更改电路
    TS3DV642是一种12通道1:2或2:1双向多路替代器/多路解复用器。TS3DV642接入2.6V至4.5V的电源供电,适用于电池供电。电阻(RON)最小和I/O电容较小,能够实现典型值高达7.5GHz的带宽......
  • 3DMAX2018安装
    1.下载3DMAX2018安装包并解压2.打开解压后的文件点击Setup选择语言和安装位置点击下一步安装完成后点击enteraserialnumber输入序列号066-66666666,密钥128J1后点......
  • 大咖说·先临三维|技术入云塑造3D视觉行业新模式
    高精度3D视觉技术主要的工作原理是什么?它的开发难度在哪里?数字化技术对其有何助力?本期大咖说,看先临三维副总裁兼研究院副院长江腾飞如何分享。嘉宾介绍江腾飞:先......
  • Matplotlib数据可视化——3D视图
    """绘制三维图形"""importnumpyasnpimportmatplotlib.pyplotaspltfrommpl_toolkits.mplot3dimportAxes3Dfig=plt.figure()ax=Axes3D(fig)X=np.ara......