402 lines
25 KiB
HTML
402 lines
25 KiB
HTML
|
|
|
|||
|
|
|
|||
|
|
<!DOCTYPE html>
|
|||
|
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
|||
|
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
|||
|
|
<head>
|
|||
|
|
<meta charset="utf-8">
|
|||
|
|
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
|
|||
|
|
<title>Point Feature Histograms (PFH) descriptors — Point Cloud Library 1.12.0 documentation</title>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<script type="text/javascript" src="_static/js/modernizr.min.js"></script>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
|||
|
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
|||
|
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
|||
|
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
|||
|
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
|||
|
|
|
|||
|
|
<script type="text/javascript" src="_static/js/theme.js"></script>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
|
|||
|
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
|||
|
|
<link rel="index" title="Index" href="genindex.html" />
|
|||
|
|
<link rel="search" title="Search" href="search.html" />
|
|||
|
|
</head>
|
|||
|
|
|
|||
|
|
<body class="wy-body-for-nav">
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div class="wy-grid-for-nav">
|
|||
|
|
|
|||
|
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
|||
|
|
<div class="wy-side-scroll">
|
|||
|
|
<div class="wy-side-nav-search" >
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<a href="index.html" class="icon icon-home"> Point Cloud Library
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
</a>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div class="version">
|
|||
|
|
1.12.0
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div role="search">
|
|||
|
|
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
|
|||
|
|
<input type="text" name="q" placeholder="Search docs" />
|
|||
|
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
|
<input type="hidden" name="area" value="default" />
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<!-- Local TOC -->
|
|||
|
|
<div class="local-toc"><ul>
|
|||
|
|
<li><a class="reference internal" href="#">Point Feature Histograms (PFH) descriptors</a></li>
|
|||
|
|
<li><a class="reference internal" href="#theoretical-primer">Theoretical primer</a></li>
|
|||
|
|
<li><a class="reference internal" href="#estimating-pfh-features">Estimating PFH features</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
|||
|
|
|
|||
|
|
|
|||
|
|
<nav class="wy-nav-top" aria-label="top navigation">
|
|||
|
|
|
|||
|
|
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
|||
|
|
<a href="index.html">Point Cloud Library</a>
|
|||
|
|
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div class="wy-nav-content">
|
|||
|
|
|
|||
|
|
<div class="rst-content">
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div role="navigation" aria-label="breadcrumbs navigation">
|
|||
|
|
|
|||
|
|
<ul class="wy-breadcrumbs">
|
|||
|
|
|
|||
|
|
<li><a href="index.html">Docs</a> »</li>
|
|||
|
|
|
|||
|
|
<li>Point Feature Histograms (PFH) descriptors</li>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<li class="wy-breadcrumbs-aside">
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
</li>
|
|||
|
|
|
|||
|
|
</ul>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<hr/>
|
|||
|
|
</div>
|
|||
|
|
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
|||
|
|
<div itemprop="articleBody">
|
|||
|
|
|
|||
|
|
<div class="section" id="point-feature-histograms-pfh-descriptors">
|
|||
|
|
<span id="pfh-estimation"></span><h1>Point Feature Histograms (PFH) descriptors</h1>
|
|||
|
|
<p>As point feature representations go, surface normals and curvature estimates
|
|||
|
|
are somewhat basic in their representations of the geometry around a specific
|
|||
|
|
point. Though extremely fast and easy to compute, they cannot capture too much
|
|||
|
|
detail, as they approximate the geometry of a point’s k-neighborhood with only
|
|||
|
|
a few values. As a direct consequence, most scenes will contain many points
|
|||
|
|
with the same or very similar feature values, thus reducing their informative
|
|||
|
|
characteristics.</p>
|
|||
|
|
<p>This tutorial introduces a family of 3D feature descriptors coined PFH (Point
|
|||
|
|
Feature Histograms) for simplicity, presents their theoretical advantages and
|
|||
|
|
discusses implementation details from PCL’s perspective. As a prerequisite,
|
|||
|
|
please go ahead and read the <a class="reference internal" href="normal_estimation.html#normal-estimation"><span class="std std-ref">Estimating Surface Normals in a PointCloud</span></a> tutorial first, as PFH
|
|||
|
|
signatures rely on both xyz 3D data as well as surface normals.</p>
|
|||
|
|
</div>
|
|||
|
|
<div class="section" id="theoretical-primer">
|
|||
|
|
<h1>Theoretical primer</h1>
|
|||
|
|
<p>The goal of the PFH formulation is to encode a point’s k-neighborhood
|
|||
|
|
geometrical properties by generalizing the mean curvature around the point
|
|||
|
|
using a multi-dimensional histogram of values. This highly dimensional
|
|||
|
|
hyperspace provides an informative signature for the feature representation, is
|
|||
|
|
invariant to the 6D pose of the underlying surface, and copes very well with
|
|||
|
|
different sampling densities or noise levels present in the neighborhood.</p>
|
|||
|
|
<p>A Point Feature Histogram representation is based on the relationships between
|
|||
|
|
the points in the k-neighborhood and their estimated surface normals. Simply
|
|||
|
|
put, it attempts to capture as best as possible the sampled surface variations
|
|||
|
|
by taking into account all the interactions between the directions of the
|
|||
|
|
estimated normals. <strong>The resultant hyperspace is thus dependent on the quality of
|
|||
|
|
the surface normal estimations at each point.</strong></p>
|
|||
|
|
<p>The figure below presents an influence region diagram of the PFH computation
|
|||
|
|
for a query point (<img class="math" src="_images/math/1557bf30f68d8d9460f124be9bad1e7739a98601.png" alt="p_q"/>), marked with red and placed in the middle of a
|
|||
|
|
circle (sphere in 3D) with radius <strong>r</strong>, and all its <strong>k</strong> neighbors (points
|
|||
|
|
with distances smaller than the radius <strong>r</strong>) are fully interconnected in a
|
|||
|
|
mesh. The final PFH descriptor is computed as a histogram of relationships
|
|||
|
|
between all pairs of points in the neighborhood, and thus has a computational
|
|||
|
|
complexity of <img class="math" src="_images/math/8862ee4098dec790a4e4b45e61e06aec3c31a84f.png" alt="O(k^2)"/>.</p>
|
|||
|
|
<img alt="_images/pfh_diagram.png" class="align-center" src="_images/pfh_diagram.png" />
|
|||
|
|
<p>To compute the relative difference between two points <img class="math" src="_images/math/24b68632b58b3294cc8f170cef67b2dd9510e981.png" alt="p_i"/> and
|
|||
|
|
<img class="math" src="_images/math/1190488800b0c07da55d5e0ad0670b6057326799.png" alt="p_j"/> and their associated normals <img class="math" src="_images/math/4fbb0705523f8fdd2c3c5f55e4f8c4a9a46f18a6.png" alt="n_i"/> and <img class="math" src="_images/math/335c8f497d0ef19e9563a0c5afaa7075cc8b934f.png" alt="n_j"/>, we
|
|||
|
|
define a fixed coordinate frame at one of the points (see the figure below).</p>
|
|||
|
|
<div class="math">
|
|||
|
|
<p><img src="_images/math/3e4246b085f695d74072d1be058cf8283ed94655.png" alt="{\mathsf u} =& \boldsymbol{n}_s \\
|
|||
|
|
{\mathsf v} =& {\mathsf u} \times \frac{(\boldsymbol{p}_t-\boldsymbol{p}_s)}{{\|\boldsymbol{p}_t-\boldsymbol{p}_s\|}_{2}} \\
|
|||
|
|
{\mathsf w} =& {\mathsf u} \times {\mathsf v}"/></p>
|
|||
|
|
</div><img alt="_images/pfh_frame.png" class="align-center" src="_images/pfh_frame.png" />
|
|||
|
|
<p>Using the above <strong>uvw</strong> frame, the difference between the two normals
|
|||
|
|
<img class="math" src="_images/math/d199132dcb19f0f36399dc29e10254152ab2ebbb.png" alt="n_s"/> and <img class="math" src="_images/math/5537db0936ff9cbc45558f392e1f3a35977ccfac.png" alt="n_t"/> can be expressed as a set of angular features as
|
|||
|
|
follows:</p>
|
|||
|
|
<div class="math">
|
|||
|
|
<p><img src="_images/math/477bd704365b5b567c59680f376bb72176a593fe.png" alt="\alpha &= {\mathsf v} \cdot \boldsymbol{n}_t \\
|
|||
|
|
\phi &= {\mathsf u} \cdot \frac{(\boldsymbol{p}_t - \boldsymbol{p}_s)}{d}\\
|
|||
|
|
\theta &= \arctan ({\mathsf w} \cdot \boldsymbol{n}_t, {\mathsf u} \cdot \boldsymbol{n}_t) \\"/></p>
|
|||
|
|
</div><p>where <strong>d</strong> is the Euclidean distance between the two points
|
|||
|
|
<img class="math" src="_images/math/2fd6abe0ca103b0d25edfadd05e2c891f71c422e.png" alt="\boldsymbol{p}_s"/> and <img class="math" src="_images/math/7d124ff00e84ac8a1004937d907356a2dbe5cecc.png" alt="\boldsymbol{p}_t"/>,
|
|||
|
|
<img class="math" src="_images/math/6ad49a3f75eefdaec677226c90f97163c0b0e5a9.png" alt="d={\|\boldsymbol{p}_t-\boldsymbol{p}_s\|}_2"/>. The quadruplet
|
|||
|
|
<img class="math" src="_images/math/f43f1a8d80bece6c18b82afb73528cbda3f308ae.png" alt="\langle\alpha, \phi, \theta, d\rangle"/> is computed for each pair of two
|
|||
|
|
points in k-neighborhood, therefore reducing the 12 values (xyz and normal
|
|||
|
|
information) of the two points and their normals to 4.</p>
|
|||
|
|
<p>To estimate a PFH quadruplet for a pair of points, use:</p>
|
|||
|
|
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">computePairFeatures</span> <span class="p">(</span><span class="k">const</span> <span class="n">Eigen</span><span class="o">::</span><span class="n">Vector4f</span> <span class="o">&</span><span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">Eigen</span><span class="o">::</span><span class="n">Vector4f</span> <span class="o">&</span><span class="n">n1</span><span class="p">,</span>
|
|||
|
|
<span class="k">const</span> <span class="n">Eigen</span><span class="o">::</span><span class="n">Vector4f</span> <span class="o">&</span><span class="n">p2</span><span class="p">,</span> <span class="k">const</span> <span class="n">Eigen</span><span class="o">::</span><span class="n">Vector4f</span> <span class="o">&</span><span class="n">n2</span><span class="p">,</span>
|
|||
|
|
<span class="kt">float</span> <span class="o">&</span><span class="n">f1</span><span class="p">,</span> <span class="kt">float</span> <span class="o">&</span><span class="n">f2</span><span class="p">,</span> <span class="kt">float</span> <span class="o">&</span><span class="n">f3</span><span class="p">,</span> <span class="kt">float</span> <span class="o">&</span><span class="n">f4</span><span class="p">);</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>See the API documentation for additional details.</p>
|
|||
|
|
<p>To create the final PFH representation for the query point, the set of all
|
|||
|
|
quadruplets is binned into a histogram. The binning process divides each
|
|||
|
|
feature’s value range into <strong>b</strong> subdivisions, and counts the number of
|
|||
|
|
occurrences in each subinterval. Since three out of the four features presented
|
|||
|
|
above are measures of the angles between normals, their values can easily be
|
|||
|
|
normalized to the same interval on the trigonometric circle. A binning example
|
|||
|
|
is to divide each feature interval into the same number of equal parts, and
|
|||
|
|
therefore create a histogram with <img class="math" src="_images/math/f905139f98abe36c5de73786c4c9e8911864f6e9.png" alt="b^4"/> bins in a fully correlated space.
|
|||
|
|
In this space, a histogram bin increment corresponds to a point having certain
|
|||
|
|
values for all its 4 features. The figure below presents examples of Point
|
|||
|
|
Feature Histograms representations for different points in a cloud.</p>
|
|||
|
|
<p>In some cases, the fourth feature, <strong>d</strong>, does not present an extreme
|
|||
|
|
significance for 2.5D datasets, usually acquired in robotics, as the distance
|
|||
|
|
between neighboring points increases from the viewpoint. Therefore, omitting
|
|||
|
|
<strong>d</strong> for scans where the local point density influences this feature dimension
|
|||
|
|
has proved to be beneficial.</p>
|
|||
|
|
<img alt="_images/example_pfhs.jpg" class="align-center" src="_images/example_pfhs.jpg" />
|
|||
|
|
<div class="admonition note">
|
|||
|
|
<p class="first admonition-title">Note</p>
|
|||
|
|
<p class="last">For more information and mathematical derivations, including an analysis of PFH signatures for different surface geometries please see <a class="reference internal" href="how_features_work.html#rusudissertation" id="id1">[RusuDissertation]</a>.</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="section" id="estimating-pfh-features">
|
|||
|
|
<h1>Estimating PFH features</h1>
|
|||
|
|
<p>Point Feature Histograms are implemented in PCL as part of the <a class="reference external" href="http://docs.pointclouds.org/trunk/a02944.html">pcl_features</a> library.</p>
|
|||
|
|
<p>The default PFH implementation uses 5 binning subdivisions (e.g., each of the
|
|||
|
|
four feature values will use this many bins from its value interval), and does
|
|||
|
|
not include the distances (as explained above – although the
|
|||
|
|
<strong>computePairFeatures</strong> method can be called by the user to obtain the
|
|||
|
|
distances too, if desired) which results in a 125-byte array (<img class="math" src="_images/math/4222ce6070b04c6b2afef24c87e6ac442266790f.png" alt="5^3"/>) of
|
|||
|
|
float values. These are stored in a <strong>pcl::PFHSignature125</strong> point type.</p>
|
|||
|
|
<p>The following code snippet will estimate a set of PFH features for all the
|
|||
|
|
points in the input dataset.</p>
|
|||
|
|
<div class="highlight-cpp notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
|||
|
|
2
|
|||
|
|
3
|
|||
|
|
4
|
|||
|
|
5
|
|||
|
|
6
|
|||
|
|
7
|
|||
|
|
8
|
|||
|
|
9
|
|||
|
|
10
|
|||
|
|
11
|
|||
|
|
12
|
|||
|
|
13
|
|||
|
|
14
|
|||
|
|
15
|
|||
|
|
16
|
|||
|
|
17
|
|||
|
|
18
|
|||
|
|
19
|
|||
|
|
20
|
|||
|
|
21
|
|||
|
|
22
|
|||
|
|
23
|
|||
|
|
24
|
|||
|
|
25
|
|||
|
|
26
|
|||
|
|
27
|
|||
|
|
28
|
|||
|
|
29
|
|||
|
|
30
|
|||
|
|
31
|
|||
|
|
32
|
|||
|
|
33
|
|||
|
|
34</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><pcl/point_types.h></span><span class="cp"></span>
|
|||
|
|
<span class="cp">#include</span> <span class="cpf"><pcl/features/pfh.h></span><span class="cp"></span>
|
|||
|
|
|
|||
|
|
<span class="p">{</span>
|
|||
|
|
<span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PointXYZ</span><span class="o">>::</span><span class="n">Ptr</span> <span class="n">cloud</span> <span class="p">(</span><span class="k">new</span> <span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PointXYZ</span><span class="o">></span><span class="p">);</span>
|
|||
|
|
<span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">Normal</span><span class="o">>::</span><span class="n">Ptr</span> <span class="n">normals</span> <span class="p">(</span><span class="k">new</span> <span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">Normal</span><span class="o">></span> <span class="p">());</span>
|
|||
|
|
|
|||
|
|
<span class="p">...</span> <span class="n">read</span><span class="p">,</span> <span class="n">pass</span> <span class="n">in</span> <span class="n">or</span> <span class="n">create</span> <span class="n">a</span> <span class="n">point</span> <span class="n">cloud</span> <span class="n">with</span> <span class="n">normals</span> <span class="p">...</span>
|
|||
|
|
<span class="p">...</span> <span class="p">(</span><span class="nl">note</span><span class="p">:</span> <span class="n">you</span> <span class="n">can</span> <span class="n">create</span> <span class="n">a</span> <span class="n">single</span> <span class="n">PointCloud</span><span class="o"><</span><span class="n">PointNormal</span><span class="o">></span> <span class="k">if</span> <span class="n">you</span> <span class="n">want</span><span class="p">)</span> <span class="p">...</span>
|
|||
|
|
|
|||
|
|
<span class="c1">// Create the PFH estimation class, and pass the input dataset+normals to it</span>
|
|||
|
|
<span class="n">pcl</span><span class="o">::</span><span class="n">PFHEstimation</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PointXYZ</span><span class="p">,</span> <span class="n">pcl</span><span class="o">::</span><span class="n">Normal</span><span class="p">,</span> <span class="n">pcl</span><span class="o">::</span><span class="n">PFHSignature125</span><span class="o">></span> <span class="n">pfh</span><span class="p">;</span>
|
|||
|
|
<span class="n">pfh</span><span class="p">.</span><span class="n">setInputCloud</span> <span class="p">(</span><span class="n">cloud</span><span class="p">);</span>
|
|||
|
|
<span class="n">pfh</span><span class="p">.</span><span class="n">setInputNormals</span> <span class="p">(</span><span class="n">normals</span><span class="p">);</span>
|
|||
|
|
<span class="c1">// alternatively, if cloud is of tpe PointNormal, do pfh.setInputNormals (cloud);</span>
|
|||
|
|
|
|||
|
|
<span class="c1">// Create an empty kdtree representation, and pass it to the PFH estimation object.</span>
|
|||
|
|
<span class="c1">// Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).</span>
|
|||
|
|
<span class="n">pcl</span><span class="o">::</span><span class="n">search</span><span class="o">::</span><span class="n">KdTree</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PointXYZ</span><span class="o">>::</span><span class="n">Ptr</span> <span class="n">tree</span> <span class="p">(</span><span class="k">new</span> <span class="n">pcl</span><span class="o">::</span><span class="n">search</span><span class="o">::</span><span class="n">KdTree</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PointXYZ</span><span class="o">></span> <span class="p">());</span>
|
|||
|
|
<span class="c1">//pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<pcl::PointXYZ> ()); -- older call for PCL 1.5-</span>
|
|||
|
|
<span class="n">pfh</span><span class="p">.</span><span class="n">setSearchMethod</span> <span class="p">(</span><span class="n">tree</span><span class="p">);</span>
|
|||
|
|
|
|||
|
|
<span class="c1">// Output datasets</span>
|
|||
|
|
<span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PFHSignature125</span><span class="o">>::</span><span class="n">Ptr</span> <span class="n">pfhs</span> <span class="p">(</span><span class="k">new</span> <span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">PFHSignature125</span><span class="o">></span> <span class="p">());</span>
|
|||
|
|
|
|||
|
|
<span class="c1">// Use all neighbors in a sphere of radius 5cm</span>
|
|||
|
|
<span class="c1">// IMPORTANT: the radius used here has to be larger than the radius used to estimate the surface normals!!!</span>
|
|||
|
|
<span class="n">pfh</span><span class="p">.</span><span class="n">setRadiusSearch</span> <span class="p">(</span><span class="mf">0.05</span><span class="p">);</span>
|
|||
|
|
|
|||
|
|
<span class="c1">// Compute the features</span>
|
|||
|
|
<span class="n">pfh</span><span class="p">.</span><span class="n">compute</span> <span class="p">(</span><span class="o">*</span><span class="n">pfhs</span><span class="p">);</span>
|
|||
|
|
|
|||
|
|
<span class="c1">// pfhs->size () should have the same size as the input cloud->size ()*</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</td></tr></table></div>
|
|||
|
|
<p>The actual <strong>compute</strong> call from the <strong>PFHEstimation</strong> class does nothing internally but:</p>
|
|||
|
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">each</span> <span class="n">point</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">cloud</span> <span class="n">P</span>
|
|||
|
|
|
|||
|
|
<span class="mf">1.</span> <span class="n">get</span> <span class="n">the</span> <span class="n">nearest</span> <span class="n">neighbors</span> <span class="n">of</span> <span class="n">p</span>
|
|||
|
|
|
|||
|
|
<span class="mf">2.</span> <span class="k">for</span> <span class="n">each</span> <span class="n">pair</span> <span class="n">of</span> <span class="n">neighbors</span><span class="p">,</span> <span class="n">compute</span> <span class="n">the</span> <span class="n">three</span> <span class="n">angular</span> <span class="n">values</span>
|
|||
|
|
|
|||
|
|
<span class="mf">3.</span> <span class="nb">bin</span> <span class="nb">all</span> <span class="n">the</span> <span class="n">results</span> <span class="ow">in</span> <span class="n">an</span> <span class="n">output</span> <span class="n">histogram</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>To compute a single PFH representation from a k-neighborhood, use:</p>
|
|||
|
|
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">computePointPFHSignature</span> <span class="p">(</span><span class="k">const</span> <span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">PointInT</span><span class="o">></span> <span class="o">&</span><span class="n">cloud</span><span class="p">,</span>
|
|||
|
|
<span class="k">const</span> <span class="n">pcl</span><span class="o">::</span><span class="n">PointCloud</span><span class="o"><</span><span class="n">PointNT</span><span class="o">></span> <span class="o">&</span><span class="n">normals</span><span class="p">,</span>
|
|||
|
|
<span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="o">&</span><span class="n">indices</span><span class="p">,</span>
|
|||
|
|
<span class="kt">int</span> <span class="n">nr_split</span><span class="p">,</span>
|
|||
|
|
<span class="n">Eigen</span><span class="o">::</span><span class="n">VectorXf</span> <span class="o">&</span><span class="n">pfh_histogram</span><span class="p">);</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>Where <em>cloud</em> is the input point cloud that contains the points, <em>normals</em> is
|
|||
|
|
the input point cloud that contains the normals (could be equal to cloud if
|
|||
|
|
<em>PointInT=PointNT=PointNormal</em>), <em>indices</em> represents the set of k-nearest
|
|||
|
|
neighbors from <em>cloud</em>, <em>nr_split</em> is the number of subdivisions to use for the
|
|||
|
|
binning process for each feature interval, and <em>pfh_histogram</em> is the output
|
|||
|
|
resultant histogram as an array of float values.</p>
|
|||
|
|
<div class="admonition note">
|
|||
|
|
<p class="first admonition-title">Note</p>
|
|||
|
|
<p>For efficiency reasons, the <strong>compute</strong> method in <strong>PFHEstimation</strong> does not check if the normals contain NaN or infinite values.
|
|||
|
|
Passing such values to <strong>compute()</strong> will result in undefined output.
|
|||
|
|
It is advisable to check the normals, at least during the design of the processing chain or when setting the parameters.
|
|||
|
|
This can be done by inserting the following code before the call to <strong>compute()</strong>:</p>
|
|||
|
|
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">normals</span><span class="o">-></span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
|||
|
|
<span class="p">{</span>
|
|||
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pcl</span><span class="o">::</span><span class="n">isFinite</span><span class="o"><</span><span class="n">pcl</span><span class="o">::</span><span class="n">Normal</span><span class="o">></span><span class="p">((</span><span class="o">*</span><span class="n">normals</span><span class="p">)[</span><span class="n">i</span><span class="p">]))</span>
|
|||
|
|
<span class="p">{</span>
|
|||
|
|
<span class="n">PCL_WARN</span><span class="p">(</span><span class="s">"normals[%d] is not finite</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
<span class="p">}</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p class="last">In production code, preprocessing steps and parameters should be set so that normals are finite or raise an error.</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
<footer>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<hr/>
|
|||
|
|
|
|||
|
|
<div role="contentinfo">
|
|||
|
|
<p>
|
|||
|
|
© Copyright
|
|||
|
|
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
|||
|
|
|
|||
|
|
</footer>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<script type="text/javascript">
|
|||
|
|
jQuery(function () {
|
|||
|
|
SphinxRtdTheme.Navigation.enable(true);
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
</body>
|
|||
|
|
</html>
|