[CC]区域生长算法——点云分割
基于CC写的插件,利用PCL中算法实现:
void qLxPluginPCL::doRegionGrowing()
{
assert(m_app);
if (!m_app)
return; const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
size_t selNum = selectedEntities.size();
if (selNum!=)
{
m_app->dispToConsole("Please select two cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
} ccHObject* ent = selectedEntities[];
assert(ent);
if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))
{
m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
}
ccPointCloud* m_cloud = static_cast<ccPointCloud*>(ent);
pcl::PointCloud<PointXYZ>::Ptr pcl_t_cloud (new pcl::PointCloud<PointXYZ>);
ConvertccPointcloud_to_pclPointCloud(*m_cloud,*pcl_t_cloud); pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> > (new pcl::search::KdTree<pcl::PointXYZ>);
pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
normal_estimator.setSearchMethod (tree);
normal_estimator.setInputCloud (pcl_t_cloud);
normal_estimator.setKSearch ();
normal_estimator.compute (*normals); pcl::IndicesPtr indices (new std::vector <int>);
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (pcl_t_cloud);
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
pass.filter (*indices); pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
reg.setMinClusterSize ();
reg.setMaxClusterSize ();
reg.setSearchMethod (tree);
reg.setNumberOfNeighbours ();
reg.setInputCloud (pcl_t_cloud);
//reg.setIndices (indices);
reg.setInputNormals (normals);
reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
reg.setCurvatureThreshold (1.0); std::vector <pcl::PointIndices> clusters;
reg.extract (clusters); pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
int pointCount=colored_cloud->size();
ccPointCloud* ccCloud =new ccPointCloud();
if (!ccCloud->reserve(static_cast<unsigned>(pointCount)))
return ;
ccCloud->enableScalarField();
ccCloud->setName(QString("RegionGrowing"));
ccCloud->showColors(true); ccCloud->setPointSize();
for (size_t i = ; i < pointCount; ++i)
{
CCVector3 P(colored_cloud->at(i).x,colored_cloud->at(i).y,colored_cloud->at(i).z);
ccCloud->addPoint(P); } std::vector< pcl::PointIndices >::iterator i_segment;
srand (static_cast<unsigned int> (time ()));
std::vector<unsigned char> colors;
for (size_t i_segment = ; i_segment < clusters.size (); i_segment++)
{
colors.push_back (static_cast<unsigned char> (rand () % ));
colors.push_back (static_cast<unsigned char> (rand () % ));
colors.push_back (static_cast<unsigned char> (rand () % ));
} if (ccCloud->resizeTheRGBTable(true))
{
int next_color = ;
for (i_segment = clusters.begin (); i_segment != clusters.end (); i_segment++)
{
std::vector<int>::iterator i_point;
for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
{
int index;
index = *i_point;
ccColor::Rgb rgb=ccColor::Rgb( colors[ * next_color],colors[ * next_color + ],colors[ * next_color + ]);
ccCloud->setPointColor(index,rgb.rgb);
}
next_color++;
}
}
ccHObject* group = ;
if (!group)
group = new ccHObject(QString("RegionGrowing(%1)").arg(ent->getName()));
group->addChild(ccCloud);
group->setVisible(true);
m_app->addToDB(group);
}
具体实现参考RegionGrowing类:
template <typename PointT, typename NormalT> void
pcl::RegionGrowing<PointT, NormalT>::extract (std::vector <pcl::PointIndices>& clusters)
{
clusters_.clear ();
clusters.clear ();
point_neighbours_.clear ();
point_labels_.clear ();
num_pts_in_segment_.clear ();
number_of_segments_ = ; bool segmentation_is_possible = initCompute ();
if ( !segmentation_is_possible )
{
deinitCompute ();
return;
} segmentation_is_possible = prepareForSegmentation ();
if ( !segmentation_is_possible )
{
deinitCompute ();
return;
} findPointNeighbours ();
applySmoothRegionGrowingAlgorithm ();
assembleRegions (); clusters.resize (clusters_.size ());
std::vector<pcl::PointIndices>::iterator cluster_iter_input = clusters.begin ();
for (std::vector<pcl::PointIndices>::const_iterator cluster_iter = clusters_.begin (); cluster_iter != clusters_.end (); cluster_iter++)
{
if ((static_cast<int> (cluster_iter->indices.size ()) >= min_pts_per_cluster_) &&
(static_cast<int> (cluster_iter->indices.size ()) <= max_pts_per_cluster_))
{
*cluster_iter_input = *cluster_iter;
cluster_iter_input++;
}
} clusters_ = std::vector<pcl::PointIndices> (clusters.begin (), cluster_iter_input);
clusters.resize(clusters_.size()); deinitCompute ();
}
算法实现的关键多了一步种子点选取的过程,需要根据某一种属性排序。
template <typename PointT, typename NormalT> void
pcl::RegionGrowing<PointT, NormalT>::applySmoothRegionGrowingAlgorithm ()
{
int num_of_pts = static_cast<int> (indices_->size ());
point_labels_.resize (input_->points.size (), -); std::vector< std::pair<float, int> > point_residual;
std::pair<float, int> pair;
point_residual.resize (num_of_pts, pair); if (normal_flag_ == true)
{
for (int i_point = ; i_point < num_of_pts; i_point++)
{
int point_index = (*indices_)[i_point];
point_residual[i_point].first = normals_->points[point_index].curvature;
point_residual[i_point].second = point_index;
}
std::sort (point_residual.begin (), point_residual.end (), comparePair);
}
else
{
for (int i_point = ; i_point < num_of_pts; i_point++)
{
int point_index = (*indices_)[i_point];
point_residual[i_point].first = ;
point_residual[i_point].second = point_index;
}
}
int seed_counter = ;
int seed = point_residual[seed_counter].second; int segmented_pts_num = ;
int number_of_segments = ;
while (segmented_pts_num < num_of_pts)
{
int pts_in_segment;
pts_in_segment = growRegion (seed, number_of_segments);
segmented_pts_num += pts_in_segment;
num_pts_in_segment_.push_back (pts_in_segment);
number_of_segments++; //find next point that is not segmented yet
for (int i_seed = seed_counter + ; i_seed < num_of_pts; i_seed++)
{
int index = point_residual[i_seed].second;
if (point_labels_[index] == -)
{
seed = index;
break;
}
}
}
}
区域生长的主要流程:
template <typename PointT, typename NormalT> int
pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
{
std::queue<int> seeds;
seeds.push (initial_seed);
point_labels_[initial_seed] = segment_number;//第几个生长的区域 int num_pts_in_segment = ; while (!seeds.empty ())
{
int curr_seed;
curr_seed = seeds.front ();
seeds.pop (); size_t i_nghbr = ;
while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
{
int index = point_neighbours_[curr_seed][i_nghbr];
if (point_labels_[index] != -)//未标记
{
i_nghbr++;
continue;
} bool is_a_seed = false;
//判断近邻是否属于当前的标记类,是否可以作为新的种子点
bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed); if (belongs_to_segment == false)
{
i_nghbr++;
continue;
} point_labels_[index] = segment_number;//当前近邻属于标记类
num_pts_in_segment++; if (is_a_seed)
{
seeds.push (index);//加入新的种子点
} i_nghbr++;
}// next neighbour
}// next seed return (num_pts_in_segment);
}


[CC]区域生长算法——点云分割的更多相关文章
- PCL—低层次视觉—点云分割(最小割算法)
1.点云分割的精度 在之前的两个章节里介绍了基于采样一致的点云分割和基于临近搜索的点云分割算法.基于采样一致的点云分割算法显然是意识流的,它只能割出大概的点云(可能是杯子的一部分,但杯把儿肯定没分割出 ...
- PCL—点云分割(最小割算法) 低层次点云处理
1.点云分割的精度 在之前的两个章节里介绍了基于采样一致的点云分割和基于临近搜索的点云分割算法.基于采样一致的点云分割算法显然是意识流的,它只能割出大概的点云(可能是杯子的一部分,但杯把儿肯定没分割出 ...
- [CC]手动点云分割
CloudCompare中手动点云分割功能ccGraphicalSegmentationTool, 点击应用按钮后将现有的点云分成segmented和remaining两个点云, //停用点云分割功能 ...
- PCL—低层次视觉—点云分割(基于凹凸性)
1.图像分割的两条思路 场景分割时机器视觉中的重要任务,尤其对家庭机器人而言,优秀的场景分割算法是实现复杂功能的基础.但是大家搞了几十年也还没搞定——不是我说的,是接下来要介绍的这篇论文说的.图像分割 ...
- PCL—低层次视觉—点云分割(超体聚类)
1.超体聚类——一种来自图像的分割方法 超体(supervoxel)是一种集合,集合的元素是“体”.与体素滤波器中的体类似,其本质是一个个的小方块.与之前提到的所有分割手段不同,超体聚类的目的并不是分 ...
- PCL—低层次视觉—点云分割(邻近信息)
分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最简单的分割方式就是在边界上找些居民问:"小伙子,你到底能不能上油管啊?”.然后把能上油管的居民坐标 ...
- PCL—点云分割(基于凹凸性) 低层次点云处理
博客转载自:http://www.cnblogs.com/ironstark/p/5027269.html 1.图像分割的两条思路 场景分割时机器视觉中的重要任务,尤其对家庭机器人而言,优秀的场景分割 ...
- PCL—点云分割(超体聚类) 低层次点云处理
博客转载自:http://www.cnblogs.com/ironstark/p/5013968.html 1.超体聚类——一种来自图像的分割方法 超体(supervoxel)是一种集合,集合的元素是 ...
- PCL—点云分割(邻近信息) 低层次点云处理
博客转载自:http://www.cnblogs.com/ironstark/p/5000147.html 分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最 ...
随机推荐
- outerHTML
1,获取html结构:当前节点下的代码: jQuery.html() 是获取当前节点下的html代码,并不包含当前节点本身的代码: 2,jQuery.prop("outerHTML" ...
- MySQL - 问题集 - "Got error 28 from storage engine"
数据库的临时目录空间不够,修改配置文件中的tmpdir,指向一个硬盘空间很大的目录即可. windows下,找到配置文件my.ini. [mysqld] tmpdir=D:/work/tool/mys ...
- 廖雪峰js教程笔记12 用DOM更新 innerHMTL 和修改css样式
拿到一个DOM节点后,我们可以对它进行更新. 可以直接修改节点的文本,方法有两种: 一种是修改innerHTML属性,这个方式非常强大,不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段 ...
- BZOJ 2844 albus就是要第一个出场 ——高斯消元 线性基
[题目分析] 高斯消元求线性基. 题目本身不难,但是两种维护线性基的方法引起了我的思考. void gauss(){ k=n; F(i,1,n){ F(j,i+1,n) if (a[j]>a[i ...
- java基础-继承
浏览以下内容前,请点击并阅读 声明 一个由其他类继承的类叫子类(也叫继承类,扩展类等),该类继承的类叫父类或超类.除了Object类意外,所有的类都有切仅有一个父类,如果一个类没有用extends关键 ...
- BZOJ4078 : [Wf2014]Metal Processing Plant
设$D(A)\leq D(B)$,从小到大枚举$D(A)$,双指针从大到小枚举$D(B)$. 那么对于权值不超过$D(A)$的边,可以忽略. 对于权值介于$(D(A),D(B)]$之间的边,需要满足那 ...
- ZeroMQ接口函数之 :zmq_curve – 安全的认证方式和保密方式
ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_curve zmq_curve(7) ØMQ Manual - ØMQ/4.1.0 Name zmq_curve ...
- cxf webservice简单应用
Server端 server部署到一个端口号为80的tomcat中 CXFController.java package com.lwj.controller; import java.io.IOEx ...
- C++中 引入虚基类的作用
当某类的部分或全部直接基类是从另一个基类共同派生而来时,这直接基类中,从上一级基类继承来的成员就拥有相同的名称,派生类的对象的这些同名成员在内存中同时拥有多个拷贝,同一个函数名有多个映射.可以使用作用 ...
- MyBatis实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...