Fast triangulation of unordered point clouds

56人阅读 评论(1) 收藏 举报
分类:

转自:http://pointclouds.org/documentation/tutorials/greedy_projection.php

Fast triangulation of unordered point clouds

This tutorial explains how to run a greedy surface triangulation algorithm on aPointCloud with normals, to obtain a triangle mesh based on projections of thelocal neighborhoods. An example of the method’s output can be seen here:

Background: algorithm and parameters

The method works by maintaining a list of points from which the mesh can begrown (“fringe” points) and extending it until all possible points areconnected. It can deal with unorganized points, coming from one or multiplescans, and having multiple connected parts. It works best if the surface islocally smooth and there are smooth transitions between areas with differentpoint densities.

Triangulation is performed locally, by projecting the local neighborhood of apoint along the point’s normal, and connecting unconnected points. Thus, thefollowing parameters can be set:

  • setMaximumNearestNeighbors(unsigned) and setMu(double) control the size ofthe neighborhood. The former defines how many neighbors are searched for,while the latter specifies the maximum acceptable distance for a point to beconsidered, relative to the distance of the nearest point (in order to adjustto changing densities). Typical values are 50-100 and 2.5-3 (or 1.5 forgrids).
  • setSearchRadius(double) is practically the maximum edge length for everytriangle. This has to be set by the user such that to allow for the biggesttriangles that should be possible.
  • setMinimumAngle(double) and setMaximumAngle(double) are the minimum andmaximum angles in each triangle. While the first is not guaranteed, thesecond is. Typical values are 10 and 120 degrees (in radians).
  • setMaximumSurfaceAgle(double) and setNormalConsistency(bool) are meant todeal with the cases where there are sharp edges or corners and where twosides of a surface run very close to each other. To achieve this, points arenot connected to the current point if their normals deviate more than thespecified angle (note that most surface normal estimation methods producesmooth transitions between normal angles even at sharp edges). This angle iscomputed as the angle between the lines defined by the normals (disregardingthe normal’s direction) if the normal-consistency-flag is not set, as not allnormal estimation methods can guarantee consistently oriented normals.Typically, 45 degrees (in radians) and false works on most datasets.

Please see the example below, and you can consult the following paper and itsreferences for more details:


@InProceedings{Marton09ICRA,
  author    = {Zoltan Csaba Marton and Radu Bogdan Rusu and Michael Beetz},
  title     = {{On Fast Surface Reconstruction Methods for Large and Noisy Datasets}},
  booktitle = {Proceedings of the IEEE International Conference on Robotics and Automation (ICRA)},
  month     = {May 12-17},
  year      = {2009},
  address   = {Kobe, Japan},
}

The code

First, create a file, let’s say, greedy_projection.cpp in your favoriteeditor, and place the following code inside it:

#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>
#include <pcl/io/vtk_io.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 ("../data/test.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 (2.5);

  // 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();

  pcl::io::saveVTKFile("../data/testmesh.vtk", triangles);
  // Finish
  return (0);
}

The input file you can find at pcl/test/bun0.pcd

The explanation

Now, let’s break down the code piece by piece.

// 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

as the example PCD has only XYZ coordinates, we load it into aPointCloud<PointXYZ>.

// 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

the method requires normals, so they are estimated using the standard methodfrom PCL.

 // 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

Since coordinates and normals need to be in the same PointCloud, we create a PointNormal type point cloud.

  // 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;

The above lines deal with the initialization of the required objects.

// 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);

The above lines set the parameters, as explained above.

 // Get result
  gp3.setInputCloud (cloud_with_normals);
  gp3.setSearchMethod (tree2);
  gp3.reconstruct (triangles);

The lines above set the input objects and perform the actual triangulation.

// Additional vertex information
  std::vector<int> parts = gp3.getPartIDs();
  std::vector<int> states = gp3.getPointStates();

for each point, the ID of the containing connected component and its “state”(i.e. gp3.FREE, gp3.BOUNDARY or gp3.COMPLETED) can be retrieved.

Saving and viewing the result

You can view the smoothed cloud for example by saving into a VTK file by:

#include <pcl/io/vtk_io.h>
...
saveVTKFile ("mesh.vtk", triangles);

Compiling and running the program

Add the following lines to your CMakeLists.txt file:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(greedy_projection)

find_package(PCL 1.2 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (greedy_projection greedy_projection.cpp)
target_link_libraries (greedy_projection ${PCL_LIBRARIES})

After you have made the executable, you can run it. Simply do:

$ ./greedy_projection

查看评论

监视程序的编制

      监视程序,这个名字听起来似乎很陌生。它的用途主要是在后台监视系统中关键信息的改变,比如注册表的改变及硬盘上由于文件操作引起的改变等等。  也许有人会问了,编制这样的程序有什么价值呢?硬盘上...
  • yemagxy
  • yemagxy
  • 2001-05-04 22:09:00
  • 573

[论文解读] Vote3Deep: Fast Object Detection in 3D Point Clouds Using Efficient CNN

Vote3Deep: Fast Object Detection in 3D Point Clouds Using Efficient Convolutional Neural Network.
  • williamyi96
  • williamyi96
  • 2017-10-15 13:23:52
  • 469

On Fast Surface Reconstruction Methods for Large and Noisy Point Clouds

  • 2012年06月08日 16:50
  • 1.68MB
  • 下载

Fast Object Detection in 3D Point Clouds Using Convolutional Neural Networks

  • 2018年04月08日 16:04
  • 1.52MB
  • 下载

使用层次聚类的有组织点云的快速平面提取(续)

这是老师很久之前给的一篇paper,LZ还是有拖延症,到现在才想起来要把这篇paper的一些自己的思考或者说一些理解记录下来,如果有兴趣的,小伙伴可以看下原文“Fast Plane Extractio...
  • Felaim
  • Felaim
  • 2017-10-13 17:09:02
  • 348

聚类(下)

1.原型聚类 原型聚类亦称“基于原型的聚类”(prototype-based clustering),此类算法假设聚类结构能通过一组原型刻画,在现实聚类任务中常用。通常,算法先对原型进行初始化,然后对...
  • hellowuxia
  • hellowuxia
  • 2017-03-24 20:53:57
  • 978

triangulation method中的midpoint method and Linear triangulation method

参考地址:http://archimede.bibl.ulaval.ca/archimede/fichiers/25229/ch06.html midpoint method: 这是最直观的三维重建方...
  • snikerlii
  • snikerlii
  • 2017-09-06 20:17:06
  • 298

对3D离散点集进行三角划分 C++代码

  • 2011年10月17日 15:52
  • 1.06MB
  • 下载

对离散点集进行三角划分 C++代码

  • 2011年10月17日 15:50
  • 779KB
  • 下载
    个人资料
    持之以恒
    等级:
    访问量: 59万+
    积分: 7604
    排名: 3571
    最新评论