.. _narf_keypoint_extraction:

How to extract NARF keypoint from a range image
-----------------------------------------------

This tutorial demonstrates how to extract NARF key points from a range image.
The executable enables us to load a point cloud from disc (or create it if not
given), extract interest points on it and visualize the result, both in an
image and a 3D viewer.

The code
--------

First, create a file called, let's say, ``narf_keypoint_extraction.cpp`` in your favorite
editor, and place the following code inside it:

.. literalinclude:: sources/narf_keypoint_extraction/narf_keypoint_extraction.cpp
   :language: cpp
   :linenos:


Explanation
-----------

In the beginning we do command line parsing, read a point cloud from disc (or
create it if not provided), create a range image and visualize it. All of these
steps are already covered in the previous tutorial `Range image visualization <http://www.pointclouds.org/documentation/tutorials/range_image_visualization.php#range-image-visualization>`_ .

The interesting part begins here:

.. code-block:: cpp

  ...
  pcl::RangeImageBorderExtractor range_image_border_extractor;
  pcl::NarfKeypoint narf_keypoint_detector (&range_image_border_extractor);
  narf_keypoint_detector.setRangeImage (&range_image);
  narf_keypoint_detector.getParameters ().support_size = support_size;
  //narf_keypoint_detector.getParameters ().add_points_on_straight_edges = true;
  //narf_keypoint_detector.getParameters ().distance_for_additional_points = 0.5;
  
  pcl::PointCloud<int> keypoint_indices;
  narf_keypoint_detector.compute (keypoint_indices);
  std::cout << "Found "<<keypoint_indices.points.size ()<<" key points.\n";
  ...

This creates a RangeImageBorderExtractor object, that is needed for the
interest point extraction. If you are interested in this you can have a look at
the Range Image Border Extraction tutorial. In this case we just use the
RangeImageBorderExtractor object with its default parameters. Then we create
the NarfKeypoint object, give it the RangeImageBorderExtractor object, the
range image and set the support size (the size of the sphere around a point
that includes points that are used for the determination of the interest
value). The commented out part contains some parameters that you can test out
if you want. Next we create the object where the indices of the determined
keypoints will be saved and compute them. In the last step we output the number
of found keypoints.

The remaining code just visualizes the results in a range image widget and also in a 3D viewer. 


Compiling and running the program
---------------------------------

Add the following lines to your CMakeLists.txt file:

.. literalinclude:: sources/narf_keypoint_extraction/CMakeLists.txt
   :language: cmake
   :linenos:

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

  $ ./narf_keypoint_extraction -m

This will use an autogenerated point cloud of a rectangle floating in space.
The key points are detected in the corners. The parameter -m is necessary,
since the area around the rectangle is unseen and therefore the system can not
detect it as a border. The option -m changes the unseen area to maximum range
readings, thereby enabling the system to use these borders.

You can also try it with a point cloud file from your hard drive::

  $ ./narf_keypoint_extraction <point_cloud.pcd>

The output should look similar to this:

.. image:: images/narf_keypoint_extraction.png

