基于颜色的区域生长分割:
基于颜色的区域生长分割原理上和基于曲率,法线的分割方法是一致的,只不过比较目标换成了颜色。可以认为,同一个颜色且挨得近,是一类的可能性很大,比较适合用于室内场景分割。
尤其是复杂室内场景,颜色分割可以轻松的将连续的场景点云变成不同的物体。哪怕是高低不平的地面,设法用采样一致分割器抽掉平面,颜色分割算法对不同的颜色的物体实现分割。
算法主要分为两步:
(1)分割,当前种子点和领域点之间色差小于色差阀值的 视为一个聚类。
(2)合并,聚类之间的色差小于色差阀值和并为一个聚类 ,且当前聚类中点的数量小于聚类点数量的与最近的聚类 合并在一起。
RGB的距离:
基于颜色的区域生长分割:
基于颜色的区域生长分割原理上和基于曲率,法线的分割方法是一致的,只不过比较目标换成了颜色。可以认为,同一个颜色且挨得近,是一类的可能性很大,比较适合用于室内场景分割。尤其是复杂室内场景,颜色分割可以轻松的将连续的场·景点云变成不同的物体。哪怕是高低不平的地面,设法用采样一致分割器抽掉平面,颜色分割算法对不同的颜色的物体实现分割。
#include <iostream>
#include <vector>//容器
#include <pcl/point_types.h>//支持点类型
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>//kdtree
#include <pcl/visualization/cloud_viewer.h>//pcl可视化
#include <pcl/filters/passthrough.h>//直通滤波器
#include <pcl/segmentation/region_growing_rgb.h>//区域增长
//console模块
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
#include <pcl/features/normal_3d.h>//法线估计
#include <pcl/visualization/pcl_visualizer.h>//pcl可视化
using namespace pcl::console;
int
main (int argc, char** argv)
{
if(argc<2)
{
std::cout<<".exe xx.pcd -b_n 0 -kn 50 -st_n 30 -ct_n 0.05 -bc 0 -fc 10 -nc 0 -dt 10 -ct 6 -rt 5 -mt 600" <<endl;
return 0;
}
time_t start,end,diff[5],option;
start = time(0);
bool Bool_Cuting=false,b_n=false;//创建bool型变量
int MinClusterSize=600,//设置聚类的大小为600
KN_normal=50;//法线估计
float far_cuting=10,//直通滤波可接受的范围的最大值
near_cuting=0,//直通滤波可接受的范围的最小值
DistanceThreshold=10.0,//设置距离阈值为10
ColorThreshold=6,//设置点与点之间的颜色容差为6
RegionColorThreshold=5,//设置区域之间的容差为5
SmoothnessThreshold=30.0,//设置平滑阈值为30
CurvatureThreshold=0.05;//设置曲率阈值为0.05
parse_argument (argc, argv, "-b_n", b_n);
parse_argument (argc, argv, "-kn", KN_normal);//法线估计
parse_argument (argc, argv, "-st_n", SmoothnessThreshold);//平滑阈值
parse_argument (argc, argv, "-ct_n", CurvatureThreshold);//曲率阈值
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, "-dt", DistanceThreshold);//距离阈值
parse_argument (argc, argv, "-ct", ColorThreshold);//颜色容差
parse_argument (argc, argv, "-rt", RegionColorThreshold);//区域之间的容差
parse_argument (argc, argv, "-mt", MinClusterSize);//最小点云集切割
//frist step load the point cloud 输入点云数据
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);//创建cloud指针
if ( pcl::io::loadPCDFile <pcl::PointXYZRGB> (argv[1], *cloud) == -1)
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
end = time(0);
diff[0] = difftime (end, start);
PCL_INFO ("\Loading pcd file takes(seconds): %d\n", diff[0]); //计算下载点云文件所花费的时间
pcl::search::Search <pcl::PointXYZRGB>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZRGB> > (new pcl::search::KdTree<pcl::PointXYZRGB>);
//Noraml estimation step(1 parameter)
//创建共享指针
pcl::search::Search<pcl::PointXYZRGB>::Ptr tree1 = boost::shared_ptr<pcl::search::Search<pcl::PointXYZRGB> > (new pcl::search::KdTree<pcl::PointXYZRGB>);
pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> normal_estimator;//法线估计 创建法线估计对象
normal_estimator.setSearchMethod (tree);//设置搜索方式
normal_estimator.setInputCloud (cloud);//设置输入点云
normal_estimator.setKSearch (KN_normal);//点云法向计算时,需要搜索的近邻点大小为50
normal_estimator.compute (*normals); //开始进行法向计算
end = time(0);
diff[1] = difftime (end, start)-diff[0];
PCL_INFO ("\Estimating normal takes(seconds): %d\n", diff[1]); //输出法线估计所用时间
//Optional step: cutting away the clutter scene too far away from camera
//可选步骤:切掉离相机太远的杂乱场景
pcl::IndicesPtr indices (new std::vector <int>);
if(Bool_Cuting)//是否通过z轴范围对待处理数据进行裁剪
{
pcl::PassThrough<pcl::PointXYZRGB> pass;//创建直通滤波器对象
pass.setInputCloud (cloud);//设置输入点云
pass.setFilterFieldName ("z");//过滤掉z轴范围的点云
pass.setFilterLimits (near_cuting, far_cuting);//直通滤波可以接受的范围为(0,10)
pass.filter (*indices);
}
// Region growing RGB
//颜色分割
pcl::RegionGrowingRGB<pcl::PointXYZRGB> reg;//创建颜色分割对象reg
reg.setInputCloud (cloud);
if(Bool_Cuting)reg.setIndices (indices);
reg.setSearchMethod (tree);
reg.setDistanceThreshold (DistanceThreshold);
reg.setPointColorThreshold (ColorThreshold);
reg.setRegionColorThreshold (RegionColorThreshold);
reg.setMinClusterSize (MinClusterSize);
if(b_n)
{
reg.setSmoothModeFlag(true);
reg.setCurvatureTestFlag(true);
reg.setInputNormals (normals);
reg.setSmoothnessThreshold (SmoothnessThreshold / 180.0 * M_PI);//设置平滑阈值
reg.setCurvatureThreshold (CurvatureThreshold);
}
std::vector <pcl::PointIndices> clusters;
reg.extract (clusters);//
//计算分割时间
end = time(0);
diff[2] = difftime (end, start)-diff[0]-diff[1];
PCL_INFO ("\RGB region growing takes(seconds): %d\n", diff[2]);
pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
pcl::visualization::CloudViewer viewer ("基于颜色的区域生长算法实现点云分割");
viewer.showCloud (colored_cloud);
/*pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("圆柱面平面分割"));*/
while (!viewer.wasStopped())
{
/*viewer.spinOnce();*/
}
return (0);
}
CMakeLists文件如下所示:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(color_based_region_growing_segmentation)
find_package(PCL 1.5 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (color_based_region_growing_segmentation color_based_region_growing_segmentation.cpp)
target_link_libraries (color_based_region_growing_segmentation ${PCL_LIBRARIES})
Ubuntu20.04下的执行命令行为:
./region_growing_rgb_segmentation /home/liqiang/Music/6/color_based_region_growing_segmentation/source/two_human.pcd -b_n 0 -kn 50 -st_n 30 -ct_n 0.05
输出结果为:
Loading pcd file takes(seconds): 1
timating normal takes(seconds): 0
RGB region growing takes(seconds): 18
执行效果如下图所示: