Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/features/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ PCL_ADD_EXAMPLE(pcl_example_rift_estimation FILES example_rift_estimation.cpp

PCL_ADD_EXAMPLE(pcl_example_difference_of_normals FILES example_difference_of_normals.cpp
LINK_WITH pcl_common pcl_kdtree pcl_search pcl_features pcl_io pcl_segmentation pcl_sample_consensus)

PCL_ADD_EXAMPLE(pcl_example_good_descriptor FILES example_good_descriptor.cpp
LINK_WITH pcl_common pcl_features pcl_io pcl_sample_consensus)
152 changes: 152 additions & 0 deletions examples/features/example_good_descriptor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Software License Agreement (BSD License)
*
* Point Cloud Library (PCL) - www.pointclouds.org
* Copyright (c) 2017-, Open Perception, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the copyright holder(s) nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/

/** \brief GOOD: a Global Orthographic Object Descriptor for 3D object recognition and manipulation.
* GOOD descriptor has been designed to be robust, descriptive and efficient to compute and use.
* It has two outstanding characteristics:
*
* (1) Providing a good trade-off among :
* - descriptiveness,
* - robustness,
* - computation time,
* - memory usage.
*
* (2) Allowing concurrent object recognition and pose estimation for manipulation.
*
* \note This is an implementation of the GOOD descriptor which has been presented in the following papers:
*
* [1] Kasaei, S. Hamidreza, Ana Maria Tomé, Luís Seabra Lopes, Miguel Oliveira
* "GOOD: A global orthographic object descriptor for 3D object recognition and manipulation."
* Pattern Recognition Letters 83 (2016): 312-320.http://dx.doi.org/10.1016/j.patrec.2016.07.006
*
* [2] Kasaei, S. Hamidreza, Luís Seabra Lopes, Ana Maria Tomé, Miguel Oliveira
* "An orthographic descriptor for 3D object learning and recognition."
* 2016 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), Daejeon, 2016,
* pp. 4158-4163. doi: 10.1109/IROS.2016.7759612
*
* Please adequately refer to this work any time this code is being used by citing above papers.
* If you do publish a paper where GOOD descriptor helped your research, we encourage you to cite the above papers in your publications.
*
* \author Hamidreza Kasaei (Seyed.Hamidreza[at]ua[dot]pt)
*/

#include <pcl/features/good.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you include auto_io.h, you don't need to include pcd_io.handply_io.h`. Give it a try.

#include <boost/filesystem.hpp>
#include <pcl/io/auto_io.h>

typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT>::Ptr PointCloudIn;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you check some of our other implementations, it's customary to append Ptr to typedefs which correspond to pointers. See for instance the example in pcl::Feature you used to derive your class. Please follow the same convention.



int main(int argc, char* argv[])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacing

{

if (argc != 2)
{
std::cout << "\n Syntax is: example_good_descriptor <path/file_name.pcd>" << std::endl;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use std::cerr instead

return 0;
}

std::string object_path = argv[1];
pcl::PointCloud<PointT>::Ptr object (new pcl::PointCloud<PointT>);
if (pcl::io::load(object_path, *object)==-1)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spacing as commented in the tutorial.

{
std::cout << "\n file extension is not correct. Syntax is: example_good_descriptor <path/file_name.pcd> or example_good_descriptor <path/file_name.ply>" << std::endl;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

return -1;
}

std::vector<PointCloudIn> vector_of_projected_views;
PointCloudIn transformed_object (new pcl::PointCloud<PointT>);

Eigen::Matrix4f transformation;
pcl::PointXYZ center_of_bounding_box;
pcl::PointXYZ bounding_box_dimensions;
std::string order_of_projected_planes;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment to self: this smells, a string to indicate ordering...


// Setup the GOOD descriptor
const int number_of_bins = 5;
const unsigned int lengh_of_descriptor = 3 * number_of_bins * number_of_bins;
pcl::PointCloud<pcl::Histogram<lengh_of_descriptor> > object_description;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now here's a good time to start making use of your conveniently defined typedef.

using pcl::GOODEstimation<PointT, number_of_bins>::Descriptor;
pcl::PointCloud<Descriptor> object_description;

The idea is to teach your users to not care about the actual length of the underlying histogram, just to focus on the number of the bins (in the context of your descriptor).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍
Also there is a convention to name constants with capital letters, e.g. NUMBER_OF_BINS.



pcl::GOODEstimation<PointT, number_of_bins> test_GOOD_descriptor ;
test_GOOD_descriptor.setThreshold(0.0015);
// NOTE : GOOD descriptor can be setup in a line: pcl::GOODEstimation<PointT, number_of_bins> test_GOOD_descriptor (0.0015);
test_GOOD_descriptor.setInputCloud(object); // pass original point cloud
test_GOOD_descriptor.compute(object_description); // Actually compute the GOOD discriptor for the given object

// Printing GOOD_descriptor for the given point cloud
pcl::Histogram<lengh_of_descriptor> GOOD_descriptor = object_description.points[0];
std::cout <<"\n GOOD =" << GOOD_descriptor <<std::endl;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either

const pcl::Histogram<lengh_of_descriptor>& GOOD_descriptor = object_description.points[0];
std::cout <<"\n GOOD =" << GOOD_descriptor <<std::endl;

or simply

std::cout <<"\n GOOD =" << object_description.points[0] <<std::endl; 

Because you don't use that variable ever again, although I can understand you want to highlight to the user that, the descriptor is just that first point.


/*_________________________________________
| |
| Functionalities for Object Manipulation |
|__________________________________________| */
// The following functinalities of GOOD descriptor are usefull for manipulation tasks:

// Get objec point cloud in local reference frame
test_GOOD_descriptor.getTransformedObject (transformed_object);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment to self: Why is a descriptor applying a transformation? Consider removing this method from the class. Check later on.


// Get three orthographic projects and transformation matrix
test_GOOD_descriptor.getOrthographicProjections (vector_of_projected_views);
test_GOOD_descriptor.getTransformationMatrix (transformation);
std::cout << "\n transofrmation matrix =\n"<<transformation << std::endl;

// Get object bounding box information
test_GOOD_descriptor.getCenterOfObjectBoundingBox (center_of_bounding_box);
test_GOOD_descriptor.getObjectBoundingBoxDimensions(bounding_box_dimensions);
std::cout<<"\n center_of_bounding_box = " << center_of_bounding_box<<std::endl;
std::cout<<"\n bounding_box_dimensions = " << bounding_box_dimensions <<std::endl;

// Get the order of the three projected planes
test_GOOD_descriptor.getOrderOfProjectedPlanes(order_of_projected_planes);
std::cout << "\n order of projected planes = "<<order_of_projected_planes << std::endl;

// NOTE : Pass the following point cloud to a pcl::visualization::PCLVisualizer forVisualizing the
//transformed object, local reference fram and three orthographic projections

//pcl::PointCloud<PointT>::Ptr transformed_object_and_projected_views (new pcl::PointCloud<PointT>);
//*transformed_object_and_projected_views += *vector_of_projected_views.at(0);
//*transformed_object_and_projected_views += *vector_of_projected_views.at(1);
//*transformed_object_and_projected_views += *vector_of_projected_views.at(2);
//*transformed_object_and_projected_views += *transformed_object;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SeyedHamidreza will add visualization to the example at some point.

return 0;
}
6 changes: 5 additions & 1 deletion features/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(SUBSYS_NAME features)
set(SUBSYS_DESC "Point cloud features library")
set(SUBSYS_DEPS common search kdtree octree filters 2d)
set(SUBSYS_DEPS common sample_consensus search kdtree octree filters 2d)

@SergioRAgostinho SergioRAgostinho Jun 28, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment for myself:

  • filters also depends on sac, so in theory, no additional dependency is being added.
  • I'm starting to suspect that this was added due to the inclusion of auxiliary methods in the class which have nothing to do with the computation of the descriptor.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SergioRAgostinho I hope this new dependency won't break your CI job distribution :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filters also has it fortunately :phew:


set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
Expand Down Expand Up @@ -62,6 +62,8 @@ if(build)
"include/pcl/${SUBSYS_NAME}/usc.h"
"include/pcl/${SUBSYS_NAME}/boundary.h"
"include/pcl/${SUBSYS_NAME}/range_image_border_extractor.h"
"include/pcl/${SUBSYS_NAME}/range_image_border_extractor.h"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate line

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate line is still here :x

"include/pcl/${SUBSYS_NAME}/good.h"
)

set(impl_incs
Expand Down Expand Up @@ -110,6 +112,7 @@ if(build)
"include/pcl/${SUBSYS_NAME}/impl/usc.hpp"
"include/pcl/${SUBSYS_NAME}/impl/boundary.hpp"
"include/pcl/${SUBSYS_NAME}/impl/range_image_border_extractor.hpp"
"include/pcl/${SUBSYS_NAME}/impl/good.hpp"
)

set(srcs
Expand Down Expand Up @@ -150,6 +153,7 @@ if(build)
src/3dsc.cpp
src/usc.cpp
src/range_image_border_extractor.cpp
src/good.cpp
)

if(MSVC)
Expand Down
Loading