[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 分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最 ...
随机推荐
- 基于类的命令行notebook的实现
在看一本书<PYTHON3 面向对象编程> 内容丰富,作作记录. notebook.py __author__ = 'chengang882' import datetime # Stor ...
- STM32F105解密STM32F105VB芯片解密STM32F105R8单片机破解多少钱?
STM32F105解密STM32F105VB芯片解密STM32F105R8单片机破解 STM32F105芯片Cortex-M3单片机解密: [凯基迪科技] STM32F105R8解密 | STM32F ...
- Linux 下MySql 重置密码
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...
- linux 查看Java 进程的内存使用情况
top -b -n 1 | grep java| awk '{print "PID:"$1",mem:"$6",CPU percent:"$ ...
- 2016 Multi-University Training Contest 1 C.Game
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submis ...
- phpunit学习 3:
16:17 2015/12/11phpunit学习 3:单元测试的大概步骤是:编写待测试类,编写测试用例类,编写测试类,测试.1.如果你有多个类,多个测试类的test类,那么可以编写一个AllTest ...
- i2c协议
i2c协议 http://blog.csdn.net/g_salamander/article/details/8016698 总线设备驱动模型 http://blog.csdn.net/u01395 ...
- java 正则表达式
1.首先是说明一些容易混淆的符号 \w Matches any word character. \W Matches any non-word character. 如果是在java中的话 ...
- <二>JDBC_通过ResultSet执行查询操作
一.ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果. 1. 调用 Statement 对象的 executeQuery(sql) 可以得到结果集. 2. ResultSet 返 ...
- ZK 页面间参数传递
1.execution.sendRedirect(url) 当使用方法execution.sendRedirect(url)进行页面跳转时,在url中添加参数:url?test=5: 跳转页面获取参数 ...