一、最小图割(可以用来分割前后景)
1、最小图割核心代码
#include <pcl/segmentation/min_cut_segmentation.h>//最小图割相关头文件
pcl::MinCutSegmentation<pcl::PointXYZ> seg;//创建一个PointXYZ类型的最小分割对象
seg.setInputCloud (cloud);//设置输入点云
if(Bool_Cuting)seg.setIndices (indices);//如果设置输入点云的索引
pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new pcl::PointCloud<pcl::PointXYZ> ());//创建一个PointCloud <pcl::PointXYZRGB>共享指针并进行实例化
pcl::PointXYZ point;//定义中心点并赋值
point.x =C_x;//中心点坐标
point.y = C_y;
point.z = C_z;
foreground_points->points.push_back(point); //前景中心点
seg.setForegroundPoints (foreground_points);//输入前景点云(目标物体)的中心点
seg.setSigma (Sigma);//设置平滑成本的Sigma值
seg.setRadius (Radius);//设置背景惩罚权重的半径
seg.setNumberOfNeighbours (NumberOfNeighbours);//设置临近点数目
seg.setSourceWeight (SourceWeight);//设置前景惩罚权重,设置的越大则分割为前景的概率越大
std::vector <pcl::PointIndices> clusters;//定义一个点云索引类型的向量,存放分割结果
seg.extract (clusters);//获取分割的结果,分割结果保存在点云索引的向量中。
std::cout << "Maximum flow is " << seg.getMaxFlow () << std::endl;//计算并输出分割期间所计算出的流值
pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = seg.getColoredCloud ();//对前景点赋予红色,对背景点赋予白色。
2、完整代码(注释)
#include <iostream>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/min_cut_segmentation.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
using namespace pcl::console;
int main (int argc, char** argv)
{
if(argc<2)
{
std::cout<<".exe xx.pcd -bc 1 -fc 1.0 -nc 0 -cx 68.97 -cy -18.55 -cz 0.57 -s 0.25 -r 3.0433856 -non 14 -sw 0.5"<<endl;
return 0;
}//如果输入参数小于1个,输出提示信息
time_t start,end,diff[5],option; //计时相关
start = time(0); //设置起点时刻
int NumberOfNeighbours=14;//设置默认参数
bool Bool_Cuting=false;//设置默认参数
float far_cuting=1,near_cuting=0,C_x=0.071753,C_y= -0.309913,C_z=1.603000,Sigma=0.25,Radius=0.8,SourceWeight=0.5;//设置默认输入参数
pcl::PointCloud <pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZ>);// 创建一个PointCloud <pcl::PointXYZ>共享指针并进行实例化,用来读入点云
if ( pcl::io::loadPCDFile <pcl::PointXYZ> (argv[1], *cloud) == -1 )// 加载点云数据
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
parse_argument (argc, argv, "-bc", Bool_Cuting);//是否使用直通滤波
parse_argument (argc, argv, "-fc", far_cuting);//直通滤波最大距离
parse_argument (argc, argv, "-nc", near_cuting);//直通滤波最小距离
parse_argument (argc, argv, "-cx", C_x);//设置中心点
parse_argument (argc, argv, "-cy", C_y);
parse_argument (argc, argv, "-cz", C_z);
parse_argument (argc, argv, "-s", Sigma);//设置平滑成本的Sigma值
parse_argument (argc, argv, "-r", Radius);//设置背景惩罚权重的半径
parse_argument (argc, argv, "-non", NumberOfNeighbours);//算法构照图时需要查找的临近点数目
parse_argument (argc, argv, "-sw", SourceWeight);//设置输入参数方式
pcl::IndicesPtr indices (new std::vector <int>);//创建一组索引
if(Bool_Cuting)//判断是否需要直通滤波
{
pcl::PassThrough<pcl::PointXYZ> pass;//设置直通滤波器对象
pass.setInputCloud (cloud);//设置输入点云
pass.setFilterFieldName ("z");//设置指定过滤的维度
pass.setFilterLimits (near_cuting, far_cuting);//设置指定纬度过滤的范围
pass.filter (*indices);//执行滤波,保存滤波结果在上述索引中
}
pcl::MinCutSegmentation<pcl::PointXYZ> seg;//创建一个PointXYZ类型的最小分割对象
seg.setInputCloud (cloud);//设置输入点云
if(Bool_Cuting)seg.setIndices (indices);//如果设置输入点云的索引
pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new pcl::PointCloud<pcl::PointXYZ> ());//创建一个PointCloud <pcl::PointXYZRGB>共享指针并进行实例化
pcl::PointXYZ point;//定义中心点并赋值
point.x =C_x;//中心点坐标
point.y = C_y;
point.z = C_z;
foreground_points->points.push_back(point); //前景中心点
seg.setForegroundPoints (foreground_points);//输入前景点云(目标物体)的中心点
seg.setSigma (Sigma);//设置平滑成本的Sigma值
seg.setRadius (Radius);//设置背景惩罚权重的半径
seg.setNumberOfNeighbours (NumberOfNeighbours);//设置临近点数目
seg.setSourceWeight (SourceWeight);//设置前景惩罚权重,设置的越大则分割为前景的概率越大
std::vector <pcl::PointIndices> clusters;//定义一个点云索引类型的向量,存放分割结果
seg.extract (clusters);//获取分割的结果,分割结果保存在点云索引的向量中。
std::cout << "Maximum flow is " << seg.getMaxFlow () << std::endl;//计算并输出分割期间所计算出的流值
pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = seg.getColoredCloud ();//对前景点赋予红色,对背景点赋予白色。
pcl::visualization::PCLVisualizer viewer ("PCL min_cut_seg");
viewer.addPointCloud(colored_cloud);
viewer.addSphere(point,Radius,122,122,0,"sphere");
viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY,0.2,"sphere");
viewer.addCoordinateSystem();
while (!viewer.wasStopped ())
{
viewer.spin();
}//进行可视化
return (0);
}
3、可视化
白色的部分被认为是前景点
二、基于法线微分的分割
不太懂
1、分割部分代码
//创建一个对象存放DoN的结果
PointCloud<PointNormal>::Ptr doncloud (new pcl::PointCloud<PointNormal>);
copyPointCloud<PointXYZRGB, PointNormal>(*cloud, *doncloud);
cout << "Calculating DoN... " << endl;
// Create DoN operator
pcl::DifferenceOfNormalsEstimation<PointXYZRGB, PointNormal, PointNormal> don;
don.setInputCloud (cloud);
don.setNormalScaleLarge (normals_large_scale);
don.setNormalScaleSmall (normals_small_scale);
//检查计算特征向量的要求是否得到满足
if (!don.initCompute ())
{
std::cerr << "Error: Could not intialize DoN feature operator" << std::endl;
exit (EXIT_FAILURE);
}
// Compute DoN 计算DoN特征向量
don.computeFeature (*doncloud);//对输入点集,计算每一个点的DoN特征向量,并输出。结果保存至doncloud
2、完整代码(注释)
/**
* @file don_segmentation.cpp
* Difference of Normals Example for PCL Segmentation Tutorials.
*
* @author Yani Ioannou
* @date 2012-09-24
* @修改 2015-6-16
*/
#include <string>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/organized.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d_omp.h>//利用多线程计算法向量相关头文件
#include <pcl/filters/conditional_removal.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/segmentation/impl/extract_clusters.hpp>
#include <pcl/features/don.h>
// for visualization
#include <pcl/visualization/pcl_visualizer.h>
using namespace pcl;
using namespace std;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr getColoredCloud (pcl::PointCloud<pcl::PointXYZ>::Ptr input_, std::vector <pcl::PointIndices> clusters_,float r,float g,float b)
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud;
if (!clusters_.empty ())
{
colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
srand (static_cast<unsigned int> (time (0)));
std::vector<unsigned char> colors;
for (size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
{
colors.push_back (static_cast<unsigned char> (rand () % 256));
colors.push_back (static_cast<unsig