点云素材:bunny.txt
#include <pcl/features/normal_3d.h> #include <pcl/features/boundary.h> #include <pcl/visualization/pcl_visualizer.h> void CreateCloudFromTxt(const std::string& file_path, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) { std::ifstream fin(file_path.c_str()); std::string line; pcl::PointXYZ point; while (getline(fin, line)) { std::stringstream ss(line); ss >> point.x; ss >> point.y; ss >> point.z; cloud->push_back(point); } fin.close(); } void EstimateNormal(const pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals) { pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_est; normal_est.setInputCloud(cloud); // normal_est.setRadiusSearch(0.05); // 设置为分辨率的10倍时效果较好,邻域半径太小,噪声较大,估计的法线容易出错,而太大则估计速度较慢 normal_est.setKSearch(10); // 点云法向计算时,需要搜索的近邻点数目 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>); normal_est.setSearchMethod(kdtree); // 建立kdtree来进行近邻点集搜索 normal_est.compute(*normals); } void EstimateBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::Boundary>& boundaries) { pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_est; boundary_est.setInputCloud(cloud); boundary_est.setInputNormals(normals); // 边界估计依赖于法线 boundary_est.setKSearch(10); // 一般这里的数值越高,最终边界识别的精度越好 // boundary_est.setRadiusSearch(0.1); // 设置为分辨率的10倍时效果较好,太小则内部的很多点就都当成边界点了 boundary_est.setAngleThreshold(M_PI / 2); // 边界估计时的角度阈值,默认值为PI/2,可根据需要进行更改。 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>); boundary_est.setSearchMethod(kdtree); boundary_est.compute(boundaries); } void visualization(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary) { boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Boundaries")); // 添加需要显示的点云数据 viewer->addPointCloud<pcl::PointXYZ>(cloud, "bunny"); pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 255, 0, 0); viewer->addPointCloud<pcl::PointXYZ>(cloud_boundary, single_color, "boundaries"); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "boundaries"); while (!viewer->wasStopped()) { viewer->spinOnce(100); boost::this_thread::sleep(boost::posix_time::microseconds(100000)); } } int main(int argc, char**argv) { // 加载点云模型 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); CreateCloudFromTxt("/tmp/bunny.txt", cloud); // 计算法线 pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); EstimateNormal(cloud, normals); // 提取边缘 pcl::PointCloud<pcl::Boundary> boundaries; EstimateBoundary(cloud, normals, boundaries); // 输出边界点的个数 std::cout << "cloud size: " <<cloud->points.size() << std::endl; std::cout << "boundaries size: " <<boundaries.points.size() << std::endl; // 存储边界点云数据 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZ>); for(size_t i = 0; i < cloud->points.size(); ++i) { if(boundaries[i].boundary_point > 0) { cloud_boundary->push_back(cloud->points[i]); } } // 可视化点云边缘 visualization(cloud, cloud_boundary); return 0; } #include <pcl/features/normal_3d.h>