#include <iostream> #include <pcl/io/ply_io.h> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/kdtree/kdtree.h> #include <pcl/segmentation/extract_clusters.h> #include <pcl/visualization/pcl_visualizer.h> #include <boost/thread/thread.hpp> #include <pcl/segmentation/extract_clusters.h> #include <pcl/features/moment_of_inertia_estimation.h> #include <pcl/features/normal_3d.h> #include <pcl/features/boundary.h> "vtkAutoInit.h"

VTK_MODULE_INIT(vtkRenderingOpenGL); // VTK was built with vtkRenderingOpenGL2 typedef pcl::PointXYZRGB PointT; typedef pcl::PointCloud<PointT> PointCloud;

using namespace std; using namespace pcl; using PointT = pcl::PointXYZRGB;

int main(int argc, char** argv) { // -------------------------------------------加载点云--------------------------------------------- pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>); if (pcl::io::loadPLYFile <PointT>("D:\DIANYUNWENJIANJIA\qiepianfenge_ply.ply", *cloud) == -1) { PCL_ERROR("Cloud reading failed."); return (-1); } cout << "检测到点云个数" << cloud->size() << endl; // -------------------------------------------欧式聚类-------------------------------------------- pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>); tree->setInputCloud(cloud); vector<pcl::PointIndices> cluster_indices; // 创建聚类索引的容器 pcl::EuclideanClusterExtraction<PointT> ec;// 欧式聚类对象 ec.setClusterTolerance(0.01); // 设置近邻搜索的搜索半径(也即两个不同聚类团点之间的最小欧氏距离) ec.setMinClusterSize(5); // 设置一个聚类需要的最少的点数目为4 ec.setMaxClusterSize(800); // 设置一个聚类需要的最大点数目为1000 ec.setSearchMethod(tree); // 设置点云的搜索机制 ec.setInputCloud(cloud); // 设置输入点云

ec.extract(cluster_indices); // 从点云中提取聚类,并将点云索引保存在cluster_indices中

	//计算点云质心
	pcl::PointCloud&#x3C;PointT&#x3E;::Ptr cluster_centroids(new pcl::PointCloud&#x3C;PointT&#x3E;);
	for (std::vector&#x3C;pcl::PointIndices&#x3E;::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
	{
		PointT centroid(0, 0, 0);
			for (std::vector&#x3C;int&#x3E;::const_iterator pit = it->indices.begin(); pit != it->indices.end(); ++pit)
			{
				centroid.x += cloud->points[*pit].x;
					centroid.y += cloud->points[*pit].y;
					centroid.z += cloud->points[*pit].z;
				}
		centroid.x /= it->indices.size();
		centroid.y /= it->indices.size();
		centroid.z /= it->indices.size();
		cluster_centroids->points.push_back(centroid);
	}
cluster_centroids->width = cluster_centroids->points.size();
cluster_centroids->height = 1;
cluster_centroids->is_dense = true;

// Save the centroids point cloud to a PLY file
pcl::io::savePLYFile(&#x22;D:\DIANYUNWENJIANJIA\newOUSHIJULEI_ply.ply&#x22;, *cluster_centroids);
//------------------------------------保存聚类结果并可视化---------------------------------------
boost::shared_ptr&#x3C;pcl::visualization::PCLVisualizer&#x3E;viewer(new pcl::visualization::PCLVisualizer(&#x22;planar segment&#x22;));
viewer->setBackgroundColor(0, 0, 0);
viewer->setWindowName(&#x22;欧式聚类&#x22;);


int begin = 0;          //定义一个计数器,用来给保存的文件命名,从1开始
for (auto it = cluster_indices.begin(); it != cluster_indices.end(); ++it)  //遍历每一个聚类,
{
	pcl::PointCloud&#x3C;PointT&#x3E;::Ptr cloud_cluster(new pcl::PointCloud&#x3C;PointT&#x3E;);  //创建一个新的点云指针用来存储每一个聚类

	for (auto pit = it->indices.begin(); pit != it->indices.end(); pit++)    //遍历当前聚类中的所有点的索引
	{
		cloud_cluster->push_back(cloud->points[*pit]);      //通过尾加法将点加入到cloud——cluster新点云中
	}

	cout &#x3C;&#x3C; &#x22;size&#x22; &#x3C;&#x3C; begin + 1 &#x3C;&#x3C; &#x3A; &#x3C;&#x3C; cloud_cluster->size() &#x3C;&#x3C; endl;

	// 检查cloud_cluster的大小,如果为空,则输出提示信息
	if (cloud_cluster->size() == 0)
	{
		std::cout &#x3C;&#x3C; &#x22;聚类后的点云数据为空,请检查聚类参数设置。&#x22; &#x3C;&#x3C; std::endl;
		continue; // 跳过当前循环,继续处理下一个聚类
	}

	Eigen::Vector4f centroid;  //创建一个四维向量容器
	pcl::compute3DCentroid(*cloud_cluster, centroid);
	std::stringstream sa;
	sa &#x3C;&#x3C; &#x22;cluster_&#x22; &#x3C;&#x3C; begin;
	pcl::PointXYZ center_point(centroid(0), centroid(1), centroid(2));   //确定质心点
	
	//viewer->addSphere(pcl::PointXYZ(centroid[0], centroid[1], centroid[2]), 0.0023, 1.0, 0.0, 0.0, sa.str());//可视化质心点
	//std::cout &#x3C;&#x3C; &#x22;Cluster &#x22; &#x3C;&#x3C; begin + 1 &#x3C;&#x3C; &#x22; Centroid: (&#x22; &#x3C;&#x3C; centroid[0] &#x3C;&#x3C; &#x22;, &#x22; &#x3C;&#x3C; centroid[1] &#x3C;&#x3C; &#x22;, &#x22; &#x3C;&#x3C; centroid[2] &#x3C;&#x3C; &#x22;)&#x22; &#x3C;&#x3C; std::endl;
	std::stringstream ss;                                      //定义一个字符串流,用于生成保存的ply文件名
	ss &#x3C;&#x3C; &#x22;Euclidean_cluster_&#x22; &#x3C;&#x3C; begin + 1 &#x3C;&#x3C; &#x22;.ply&#x22;;          //设置文件的名字
	pcl::io::savePLYFile(ss.str(), *cloud_cluster);      //将当前聚类保存为ply文件
	cout &#x3C;&#x3C; ss.str() &#x3C;&#x3C; &#x22;保存完毕!!!&#x22; &#x3C;&#x3C; endl;
	begin++;    //计数器+1用于给下一个文件命名



	// 可视化相关的代码
	uint8_t R = rand() % (256) + 0;
	uint8_t G = rand() % (256) + 0;
	uint8_t B = rand() % (256) + 0;
	string str;
	ss &#x3C;&#x3C; str;
	pcl::visualization::PointCloudColorHandlerCustom&#x3C;PointT&#x3E; color(cloud_cluster, R, G, B);
	viewer->addPointCloud&#x3C;PointT&#x3E;(cloud_cluster, color, str);
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, str);

}

while (!viewer->wasStopped())
{
	viewer->spinOnce(100);
	boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}

return (0);

}

这段代码的可视化都是正确的,但是保存的点云文件,在其他代码里面打开是空的,该如何解决,使用cloudcompare也打不开,我想检查点云数据为空:在保存之前,请确保聚类后的点云数据cloud_cluster是非空的。你可以使用cloud_cluster->size()来检查点云的大小。如何操作内容:在保存之前,确保聚类后的点云数据cloud_cluster是非空的,可以使用cloud_cluster->size()来检查点云的大小。如果点云数据为空,可能是聚类参数设置不合适导致的。可以尝试调整聚类的参数,如聚类的距离阈值、最小和最大聚类点数等,以确保正确地提取到聚类。

另外,还可以使用调试打印语句输出相关变量的值,以帮助定位问题。例如,在保存之前可以输出cloud_cluster的大小,以确认其是否为空。可以添加以下代码进行调试:

cout &#x3C;&#x3C; &#x22;cloud_cluster size: &#x22; &#x3C;&#x3C; cloud_cluster->size() &#x3C;&#x3C; endl;

如果cloud_cluster的大小为0,说明在聚类过程中可能存在问题,需要进一步调整聚类参数或检查数据是否正确。


原文地址: https://www.cveoy.top/t/topic/pLzJ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录