PCL: 根据几何规则的曲面剖分-贪婪法表面重建三角网格
点云场景中进行物体识别,使用全局特征的方法严重依赖于点云分割,难以适应杂乱场景。使用局部特征,即对点云进行提取类似于3D SURF、ROPS之类的局部特征,需要寻找离散点云块的局部显著性。
点云的基本局部显著性有某一点处的曲率。
一、几何尺寸
可表述为显著性曲率的曲率阈值与物体的几何大小有关。
典型三维模型Dragon和ball两个物体,ball也可以进行三维剖分,但其三维剖分没有任何几何意义,而deagon的三维剖分有特异性。
二、无规则三角化
参考PCL官方网站链接:Fast triangulation of unordered point clouds
代码:
#include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/features/normal_3d.h> #include <pcl/surface/gp3.h> int main (int argc, char** argv) { // Load input file into a PointCloud<T> with an appropriate type pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::PCLPointCloud2 cloud_blob; pcl::io::loadPCDFile ("bun0.pcd", cloud_blob); pcl::fromPCLPointCloud2 (cloud_blob, *cloud); //* the data should be available in cloud // Normal estimation* pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n; pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>); tree->setInputCloud (cloud); n.setInputCloud (cloud); n.setSearchMethod (tree); n.setKSearch (20); n.compute (*normals); //* normals should not contain the point normals + surface curvatures // Concatenate the XYZ and normal fields* pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>); pcl::concatenateFields (*cloud, *normals, *cloud_with_normals); //* cloud_with_normals = cloud + normals // Create search tree* pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>); tree2->setInputCloud (cloud_with_normals); // Initialize objects pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3; pcl::PolygonMesh triangles; // Set the maximum distance between connected points (maximum edge length) gp3.setSearchRadius (0.025); // Set typical values for the parameters gp3.setMu (2.5); gp3.setMaximumNearestNeighbors (100); gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees gp3.setMinimumAngle(M_PI/18); // 10 degrees gp3.setMaximumAngle(2*M_PI/3); // 120 degrees gp3.setNormalConsistency(false); // Get result gp3.setInputCloud (cloud_with_normals); gp3.setSearchMethod (tree2); gp3.reconstruct (triangles); // Additional vertex information std::vector<int> parts = gp3.getPartIDs(); std::vector<int> states = gp3.getPointStates(); // Finish return (0); }
图形效果: