当前位置:   article > 正文

点云内边界提取_点云边界提取

点云边界提取

点云边界提取,使用concavehull提取凹多边形边界,内边界使用方框滤波来进行提取,方框滤波需要确定边界框的左上角和右下角的坐标,原理为:1. 先求整体点云的最大最小x,y即xmax,ymax,ymin,xmin。再去求取(xmax+xmin)/2 与(ymax+ymin)/2,  那么可以得到,左上角x1 = s所有(ymax+ymin)/2对应点的x值的最小值,y1=所有(xmax+xmin)/2对应点的y值的最小值。同理右下角x2 = s所有(ymax+ymin)/2对应点的x值的最大值,y2=所有(xmax+xmin)/2对应点的y值的最大值。(注意当比较点云数据的时候,需要用小数点后两位去比较)

  1. // 小数点取前两位
  2. double round(double num,int precision)
  3. {
  4. double factor = pow(10, precision);
  5. return round(num*factor)/factor;
  6. }
  7. // 凹凸边界
  8. bool Imgdeal::BD_contour(pcl_ptr &CyPort_cloud, pcl_ptr &cloud_in_box)
  9. {
  10. //------------------------ 1、RANSAC拟合平面 ---------------------------
  11. pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  12. pcl::PointIndices::Ptr inliers1(new pcl::PointIndices);
  13. pcl::SACSegmentation<pcl::PointXYZ> seg;
  14. seg.setOptimizeCoefficients(true);
  15. seg.setModelType(pcl::SACMODEL_PLANE);
  16. seg.setMethodType(pcl::SAC_RANSAC);
  17. seg.setDistanceThreshold(0.01);
  18. seg.setInputCloud(CyPort_cloud);
  19. seg.segment(*inliers1, *coefficients);
  20. //----------------------- 2、三维点云投影到平面上 ---------------------------
  21. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);
  22. pcl::ProjectInliers<pcl::PointXYZ> proj;
  23. proj.setModelType(pcl::SACMODEL_PLANE);
  24. proj.setInputCloud(CyPort_cloud);
  25. proj.setModelCoefficients(coefficients);
  26. proj.filter(*cloud_projected);
  27. std::cout << "投影后点的个数: " << cloud_projected->points.size() << std::endl;
  28. writer.write("../PointsCloud/cloud_projected.pcd", *cloud_projected);
  29. //------------------- 3、提取投影平面点云的凹多边形边界 -------------------
  30. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull(new pcl::PointCloud<pcl::PointXYZ>);
  31. pcl::ConcaveHull<pcl::PointXYZ> chull;
  32. chull.setInputCloud(cloud_projected);
  33. chull.setAlpha(0.08);
  34. chull.reconstruct(*cloud_hull);
  35. std::cout << "凹多边形的点数: " << cloud_hull->points.size() << std::endl;
  36. writer.write("../PointsCloud/cloud_hull.pcd", *cloud_hull);
  37. //-------------------- 4、区域滤波获取内边缘 ------------------------
  38. std::vector<double> x, y, z;
  39. for (auto &p : cloud_projected->points)
  40. {
  41. x.push_back(p.x);
  42. y.push_back(p.y);
  43. z.push_back(p.z);
  44. }
  45. // 1、z的最大和最小
  46. auto minPositionZ = min_element(z.begin(), z.end()); // 最大z值的地址(下标)
  47. std::vector<double>::iterator iter = find(z.begin(), z.end(), *minPositionZ);
  48. int index = std::distance(z.begin(), iter); // 获取 [first,last) 范围内包含元素的个数
  49. double Zmin= *iter;
  50. auto maxPositionZ = max_element(z.begin(), z.end()); // 最大z值的地址(下标)
  51. std::vector<double>::iterator iter1 = find(z.begin(), z.end(), *maxPositionZ);
  52. int index1 = std::distance(z.begin(), iter1); // 获取 [first,last) 范围内包含元素的个数
  53. double Zmax = *iter1;
  54. std::cout<<" Zmax:" << Zmax <<" Zmin:" << Zmin <<std::endl;
  55. // 2、x的最大和最小
  56. auto minPositionX = min_element(x.begin(), x.end()); // 最大z值的地址(下标)
  57. std::vector<double>::iterator iter2 = find(x.begin(), x.end(), *minPositionX);
  58. int index2 = std::distance(x.begin(), iter2); // 获取 [first,last) 范围内包含元素的个数
  59. double Xmin= *iter2;
  60. auto maxPositionX = max_element(x.begin(), x.end()); // 最大z值的地址(下标)
  61. std::vector<double>::iterator iter3 = find(x.begin(), x.end(), *maxPositionX);
  62. int index3 = std::distance(x.begin(), iter3); // 获取 [first,last) 范围内包含元素的个数
  63. double Xmax = *iter3;
  64. std::cout<<" Xmin:" << Xmin <<" Xmax:" << Xmax <<std::endl;
  65. // 3、y的最大和最小
  66. auto minPositionY = min_element(y.begin(), y.end()); // 最大z值的地址(下标)
  67. std::vector<double>::iterator iter4 = find(y.begin(), y.end(), *minPositionY);
  68. int index4 = std::distance(y.begin(), iter4); // 获取 [first,last) 范围内包含元素的个数
  69. double Ymin= *iter4;
  70. auto maxPositionY = max_element(y.begin(), y.end()); // 最大z值的地址(下标)
  71. std::vector<double>::iterator iter5 = find(y.begin(), y.end(), *maxPositionY);
  72. int index5 = std::distance(y.begin(), iter5); // 获取 [first,last) 范围内包含元素的个数
  73. double Ymax = *iter5;
  74. std::cout<<" Ymin:" << Ymin <<" Ymax:" << Ymax <<std::endl;
  75. double flag_x = ( Xmin + Xmax)/2;
  76. double flag_y = ( Ymax + Ymin)/2;
  77. double x1,x2,y1,y2;
  78. std::cout<<" round(flag_y,2):" << round(flag_y,2) <<std::endl;
  79. // 内边界的左上角和右下角的坐标
  80. // 1
  81. std::vector<double> vector_x;
  82. for (int i = 0; i < cloud_projected->size(); i++)
  83. {
  84. if(round(cloud_projected->points[i].y,2) == round(flag_y,2))
  85. {
  86. x1 = cloud_projected->points[i].x;
  87. vector_x.push_back(x1);
  88. }
  89. }
  90. // for(std::vector<double>::iterator it = vector_x.begin();it !=vector_x.end();it++)
  91. // {
  92. // std::cout<<"vector_x:___"<<*it<<std::endl;
  93. // }
  94. double in_xmax = *max_element(vector_x.begin(),vector_x.end());
  95. double in_xmin = *min_element(vector_x.begin(),vector_x.end());
  96. std::cout<<"vector_x:in_xmax___"<<in_xmax<<"_in_xmin_"<<in_xmin <<std::endl;
  97. // 2
  98. std::vector<double> vector_y;
  99. for (int i = 0; i < cloud_projected->size(); i++)
  100. {
  101. if(round(cloud_projected->points[i].x,2) == round(flag_x,2))
  102. {
  103. y1 = cloud_projected->points[i].y;
  104. vector_y.push_back(y1);
  105. }
  106. }
  107. // for(std::vector<double>::iterator it = vector_y.begin();it !=vector_y.end();it++)
  108. // {
  109. // std::cout<<"vector_y:___"<<*it<<std::endl;
  110. // }
  111. double in_ymax = *max_element(vector_y.begin(),vector_y.end());
  112. double in_ymin = *min_element(vector_y.begin(),vector_y.end());
  113. std::cout<<"vector_x:in_ymax"<<in_ymax<<"_in_ymin_"<<in_ymin <<std::endl;
  114. //---------------提取缸的边界------------------
  115. // ------------------------设置方框滤波的范围----------------------------------
  116. // 前三个值是坐标xyz的范围,第四个值是用来占位置的不用管
  117. Eigen::Vector4f min_pt = {(float)(in_xmin+0.05),(float)(in_ymin+0.05),(float)Zmin,0};
  118. Eigen::Vector4f max_pt = {(float)(in_xmax-0.05),(float)(in_ymax-0.05),(float)Zmax,0};
  119. // -----------------------获取位于方框内的点索引-------------------------------
  120. pcl::IndicesPtr indexes(new pcl::Indices());
  121. pcl::getPointsInBox(*cloud_hull, min_pt, max_pt, *indexes);
  122. // --------------------------取框内和框外点------------------------------------
  123. pcl::ExtractIndices<pcl::PointXYZ> extr;
  124. extr.setInputCloud(cloud_hull); // 设置输入点云
  125. extr.setIndices(indexes); // 设置索引
  126. extr.filter(*cloud_in_box); // 提取对应索引的点云
  127. cout << "方框内点的个数为:" << cloud_in_box->points.size() << endl;
  128. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out_box(new pcl::PointCloud<pcl::PointXYZ>);
  129. extr.setNegative(true); // 提取对应索引之外的点
  130. extr.filter(*cloud_out_box);
  131. cout << "方框外点的个数为:" << cloud_out_box->points.size() << endl;
  132. // ------------------------保存提取结果到本地文件夹---------------------------
  133. writer.write("../PointsCloud/cloud_in_box.pcd", *cloud_in_box);
  134. writer.write("../PointsCloud/cloud_out_box.pcd", *cloud_out_box);
  135. std::cerr << "滤波前有: " << cloud_in_box->size() << " 个点 " << std::endl;
  136. return true;
  137. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/764828
推荐阅读
相关标签
  

闽ICP备14008679号