代码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;
}