点云聚类与区域边界估计
Posted lovebay
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点云聚类与区域边界估计相关的知识,希望对你有一定的参考价值。
点云聚类与区域边界估计
为对有一定特征和规律的点云数据进行聚类划分,文章提出了一种将空间与特性融合的聚类方法,并在聚类的基础上进行了区域边界的检测(这是上一边文章提到的方法),具体算法思路如下:
(1)点云预处理,抽希、去燥等。
(2)不可划分区域剔除;
(3)下面就是把剩余区域进行聚类划分,选取x最大的面作为搜索种子面开始,进行邻近半径搜索,设半径为R,当在半径R内搜索到n个三角面后,比较这些三角面与加权平均mid_d的差值,设置阈值delta_d, 若间距差值小于阈值delta_d,则将所搜到的三角面进行一个聚类custer的融合,否则,则不融合;然后新进来的面有作为种子面,进行上面继续搜索,并计算新的加权平均间距mid_d。这样迭代下去,直到所有的所有聚类划分完成。
示意图
(4)通过第三步可以得到很多聚类结果custers,遍历所有聚类custers,设置最小点数或面积阈值A3,剔除面积小于A3的聚类custer;对每个custer进行三角面融合以及边界检测。
(5)对第四步的检测边界,进行锯齿处理,主要采用边界平滑处理,有个平滑力度阈值dis_threshold,作为区域边界;返回这些区域边界数据。
(注:主要第三步是把两步划分,进行一步划分聚类)
部分代码:
int Division( std::vector<PointType>& in_points, std::vector<PCTTM_TriangleFace>& face_vect, std::vector<double>& distance_vect, std::vector<PointType>& face_center_points2, std::vector<std::vector<int>>& region_vector, const double& d_threshold, const int& num_threshold) { if (in_points.size()<3 || face_vect.size()==0|| distance_vect.size()==0) { std::cout << "in_points.size()<3 || face_vect.size()==0|| distance_vect.size()==0" << std::endl; return -1; } std::vector<PointType> face_center_points; //std::vector<point3f_rgba> face_center_points2; //计算三角面几何中心 std::vector<double> distance_vect2; //剔除灰色 std::vector<int> out_index(face_vect.size()); for (size_t i = 0; i < face_vect.size(); i++) { PointType pt2 = calculateFaceCenter(in_points[face_vect[i].p_index_0], in_points[face_vect[i].p_index_1], in_points[face_vect[i].p_index_2]); int d_index = static_cast<int>(10.0*d_threshold / 5.0); int index = static_cast<int>(10.0*distance_vect[i] / 5.0); if (distance_vect[i] <= d_threshold) { face_center_points2.push_back(pt2); distance_vect2.push_back(distance_vect[i]); } else { out_index[i] = -1; } face_center_points.push_back(pt2); } /*****************离散点的区域划分*************************/ KDT::KDTree tree; tree.setInputPointCloud(face_center_points2); tree.setNumOfLeafData(100); tree.buildKDTree(); double density = 0.0; if (caculateDensity(face_center_points2, density) == -1) { std::cout << "caculateDensity() failed !!! " << std::endl; return -1; } const double delta_threshold = 1.49999; //0.3-3.0 const float searchRadius = 3.0*density; //点云平均密度的1-3倍 //std::vector<std::vector<int>> region_vector; std::vector<int> index_(face_center_points2.size()); for (size_t i = 0; i < face_center_points2.size(); i++) { if (index_[i] == -1) { continue; } std::vector<int> region_; double mid_d = 0.0; /*****************迭代循环搜索************************/ region_.push_back(i); index_[i] = -1; int t = 0; mid_d = distance_vect2[i]; while (t < region_.size()) { //mid_d = distance_vect2[region_[t]]; const PointType searchPoint2 = face_center_points2[region_[t]]; std::vector<size_t> searchIndex2; std::vector<float> searchDistance2; double dis = 0.0; int num = 0; if (tree.runKNNSearchRadius(searchPoint2, searchRadius, searchIndex2, searchDistance2) > 1) { for (size_t n = 0; n < searchIndex2.size(); n++) { if (index_[searchIndex2[n]] != -1 && abs(distance_vect2[searchIndex2[n]] - mid_d) < delta_threshold) { region_.push_back(searchIndex2[n]); index_[searchIndex2[n]] = -1; dis += distance_vect2[searchIndex2[n]]; num++; } } } mid_d = (dis + mid_d*(region_.size() - num)) / region_.size(); t++; } //存取大于 的分域 if (region_.size() > num_threshold) { region_vector.push_back(region_); } } return 0; }
效果:
以上是关于点云聚类与区域边界估计的主要内容,如果未能解决你的问题,请参考以下文章