pcl 点云分割实现

代码1

三维点云使用pcl实现RANSAC平面分割_点云平面分割-优快云博客

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <vector>

int main(int argc, char** argv) {
	// 创建点云对象并加载点云数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\cow0.pcd", *cloud) == -1) { // 修改为你的文件路径
		PCL_ERROR("Couldn't read the point cloud file\n");
		return -1;
	}

	// 创建点云平面分割对象
	pcl::SACSegmentation<pcl::PointXYZ> seg;
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);

	// 设置分割参数
	seg.setOptimizeCoefficients(true);
	seg.setModelType(pcl::SACMODEL_PLANE);
	seg.setMethodType(pcl::SAC_RANSAC);
	seg.setMaxIterations(1000);
	seg.setDistanceThreshold(0.01);  // 距离阈值,适用于点云数据的尺度

	pcl::ExtractIndices<pcl::PointXYZ> extract;

	// 创建可视化对象
	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer->setBackgroundColor(0, 0, 0);

	// 预定义一些颜色
	std::vector<std::tuple<int, int, int>> colors = {
		std::make_tuple(255, 0, 0),   // Red
		std::make_tuple(0, 255, 0),   // Green
		std::make_tuple(0, 0, 255),   // Blue
		std::make_tuple(255, 255, 0), // Yellow
		std::make_tuple(255, 0, 255), // Magenta
		std::make_tuple(0, 255, 255), // Cyan
		std::make_tuple(255, 165, 0), // Orange
		std::make_tuple(128, 0, 128)  // Purple
	};

	int i = 0, nr_points = static_cast<int>(cloud->points.size());
	while (cloud->points.size() > 0.1 * nr_points) {
		// 分割平面
		seg.setInputCloud(cloud);
		seg.segment(*inliers, *coefficients);
		if (inliers->indices.size() == 0) {
			std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
			break;
		}

		// 输出平面系数
		std::cout << "Plane coefficients: " << coefficients->values[0] << " "
			<< coefficients->values[1] << " "
			<< coefficients->values[2] << " "
			<< coefficients->values[3] << std::endl;

		// 提取平面内的点
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>());
		extract.setInputCloud(cloud);
		extract.setIndices(inliers);
		extract.setNegative(false);
		extract.filter(*cloud_plane);
		std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size() << " data points." << std::endl;

		// 从颜色列表中获取颜色
		int r, g, b;
		std::tie(r, g, b) = colors[i % colors.size()];
		pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud_plane, r, g, b);
		viewer->addPointCloud<pcl::PointXYZ>(cloud_plane, single_color, "plane_" + std::to_string(i));
		viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "plane_" + std::to_string(i));

		// 保存提取到的平面
		std::stringstream ss;
		ss << "plane_" << i << ".pcd";
		pcl::io::savePCDFileASCII(ss.str(), *cloud_plane);

		// 移除平面内的点,保留其余点
		extract.setNegative(true);
		extract.filter(*cloud);
		i++;
	}

	// 显示剩余点云
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> remaining_color(cloud, 255, 255, 255); // White for remaining points
	viewer->addPointCloud<pcl::PointXYZ>(cloud, remaining_color, "remaining_cloud");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "remaining_cloud");

	// 进入可视化主循环
	while (!viewer->wasStopped()) {
		viewer->spinOnce(100);
	}

	return 0;
}

代码2

#include <pcl/io/pcd_io.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/region_growing.h>
#include <pcl/segmentation/min_cut_segmentation.h>
#include <iostream>
#include <pcl/segmentation/region_growing_rgb.h>
#include <boost/lexical_cast.hpp>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/point_types.h>

// 全局变量,用于存储点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

void select_point_cb(const pcl::visualization::PointPickingEvent& event, void* nothing)
{
	int point_index = event.getPointIndex();
	if (point_index == -1)
		return;

	// 获取选中的点的坐标
	pcl::PointXYZ point = cloud->at(point_index);

	// 创建一个点云,列出所知道的所有属于对象的点
	pcl::PointCloud<pcl::PointXYZ>::Ptr foregroundPoints(new pcl::PointCloud<pcl::PointXYZ>());
	foregroundPoints->points.push_back(point);

	// 声明一个Min-cut的聚类对象
	pcl::MinCutSegmentation<pcl::PointXYZ> clustering;
	clustering.setInputCloud(cloud); // 设置输入
	clustering.setForegroundPoints(foregroundPoints); // 设置聚类对象的前景点

													  // 设置sigma,它影响计算平滑度的成本。它的设置取决于点云之间的间隔(分辨率)
	clustering.setSigma(0.02);
	// 设置聚类对象的半径
	clustering.setRadius(0.01);
	// 设置需要搜索的临近点的个数
	clustering.setNumberOfNeighbours(20);
	// 设置前景点的权重
	clustering.setSourceWeight(0.6);

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

	std::cout << "Maximum flow is " << clustering.getMaxFlow() << "." << std::endl;

	int currentClusterNum = 1;
	for (std::vector<pcl::PointIndices>::const_iterator i = clusters.begin(); i != clusters.end(); ++i)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZ>());
		for (std::vector<int>::const_iterator point_idx = i->indices.begin(); point_idx != i->indices.end(); point_idx++)
			cluster->points.push_back(cloud->points[*point_idx]);
		cluster->width = cluster->points.size();
		cluster->height = 1;
		cluster->is_dense = true;

		if (cluster->points.size() > 0)
		{
			std::cout << "Cluster " << currentClusterNum << " has " << cluster->points.size() << " points." << std::endl;
			std::string fileName = "D:\\shiyanjieguoshuchu\\cluster" + boost::lexical_cast<std::string>(currentClusterNum) + ".pcd";
			pcl::io::savePCDFileASCII(fileName, *cluster);
			currentClusterNum++;
		}
	}
}

int main(int argc, char** argv)
{
	// 直接指定文件路径
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\cow0.pcd", *cloud) != 0) // 修改为你的文件路径
	{
		std::cerr << "Error reading point cloud from file D:\\cow0.pcd" << std::endl;
		return -1;
	}

	// 创建PCL Visualizer
	pcl::visualization::PCLVisualizer viewer("Select a point");
	viewer.addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
	viewer.addCoordinateSystem(1.0);
	viewer.initCameraParameters();

	// 注册点选择回调函数
	viewer.registerPointPickingCallback(select_point_cb, (void*)0);

	// 开始渲染
	while (!viewer.wasStopped())
	{
		viewer.spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

	return 0;
}

 

PCL(Point Cloud Library),是一个开源的3D点云处理库,主要用于计算机视觉和机器人技术等领域。在C++中,PCL提供了一系列用于点云分割的工具和算法。点云分割主要是将点云数据划分为有意义的部分,比如物体、地面、障碍物等。 一些常见的点云分割方法有: 1. **基于阈值的方法**:通过设置一定的密度、距离或颜色阈值,将点云分隔成不同的区域。 2. **聚类分割**:如DBSCAN(Density-Based Spatial Clustering of Applications with Noise)算法,根据点之间的空间邻域关系进行分组。 3. **边缘检测**:识别点云中的边缘,然后沿着边缘进行分割。 4. **Region Growing**:从初始种子点开始,逐渐扩大包含相似特征点的区域。 要使用PCL进行点云分割,你需要先加载点云数据,然后选择合适的分割器(例如`pcl::ExtractIndices`),配置参数,并应用到实际的数据上。这里是一些基本步骤: ```cpp // 包含必要的头文件 #include <pcl/point_cloud.h> #include <pcl/filters/passthrough.h> #include <pcl/features/normal_3d.h> // 加载点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); // ... 读取数据 // 创建分割pcl::PassThrough<pcl::PointXYZ> pass; pass.setInputCloud(cloud); // 设置分割条件,例如只保留高度在某个范围内的点 pass.setFilterFieldName ("z"); pass.setFilterLimits (min_height, max_height); // 应用分割 pass.filter (*cloud); // 使用其他分割方法,如KMeans、RANSAC分割等 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值