diff --git a/doc/doxygen.conf b/doc/doxygen.conf index 347af2ef86bf4786d49b13d48c12146b0d001b01..a04f4ab79c848153fb2257baa5d872c25ec7cb11 100755 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -87,7 +87,8 @@ INPUT = ../src \ INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.h \ - *.cpp + *.cpp \ + *.hpp RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62001dd00fcee8efe221fab8876453c8e6ade803..664c569194d97a50480ccf26879fc5472ad01cd1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ INCLUDE_DIRECTORIES(.) # application source files SET(sources finddd_descriptor.cpp) # application header files -SET(headers finddd_descriptor.h) +SET(headers finddd_descriptor.hpp) # create the executable file ADD_EXECUTABLE(finddd_descriptor ${sources}) # link necessary libraries diff --git a/src/finddd_descriptor.cpp b/src/finddd_descriptor.cpp index dbed46ac86049c0df3e0f15fa418d43a7799fd08..eedbcfd3d8789748891bb6d64fced86ab9a61fe1 100755 --- a/src/finddd_descriptor.cpp +++ b/src/finddd_descriptor.cpp @@ -3,7 +3,12 @@ #define PI 3.1415926535 -// Get empty normal voting histogram +/** + * \param nb_bins Number of bins in a sub-descriptor. + * \return Empty voting vector. + * + * Get empty normal voting vector. + */ inline std::vector<float> get_bin_float_empty(int nb_bins) { std::vector<float> val_bins; @@ -11,7 +16,18 @@ inline std::vector<float> get_bin_float_empty(int nb_bins) return val_bins; } -// Get normal voting histogram *with* interpolation +/** + * \param x X coordinate of normal + * \param y Y coordinate of normal + * \param z Z coordinate of normal + * \param bin_centers_x Vector with X coordinate of normal centers + * \param bin_centers_y Vector with Y coordinate of normal centers + * \param bin_centers_z Vector with Z coordinate of normal centers + * \param radius_inf Inter-bin distance among the normal centers. + * \return Voting vector corresponding to input normal. + * + * Get normal voting histogram *with* interpolation. + */ inline std::vector<float> get_bin_float_interp_xyz(float x, float y, float z, std::vector<float> &bin_centers_x, std::vector<float> &bin_centers_y, std::vector<float> &bin_centers_z, float radius_inf) { int nb_bins=bin_centers_x.size(); @@ -31,7 +47,17 @@ inline std::vector<float> get_bin_float_interp_xyz(float x, float y, float z, st return val_bins; } -// Get normal voting histogram *without* interpolation +/** + * \param x X coordinate of normal + * \param y Y coordinate of normal + * \param z Z coordinate of normal + * \param bin_centers_x Vector with X coordinate of normal centers + * \param bin_centers_y Vector with Y coordinate of normal centers + * \param bin_centers_z Vector with Z coordinate of normal centers + * \return Voting vector corresponding to input normal. + * + * Get normal voting histogram *without* interpolation. + */ inline std::vector<float> get_bin_float_xyz(float x, float y, float z, std::vector<float> &bin_centers_x, std::vector<float> &bin_centers_y, std::vector<float> &bin_centers_z) { int nb_bins=bin_centers_x.size(); @@ -59,7 +85,13 @@ inline std::vector<float> get_bin_float_xyz(float x, float y, float z, std::vect return val_bins; } -// Compute pointcloud normals fast using integral images +/** + * /param pcl_normals Output cloud with 3D point normals computed using PCL library. + * /param cloud Input cloud with 3D points we want to compute normals for. + * + * Function to compute normal vectors fast taking advantage of the fact that the input point cloud is structured. + * Compute pointcloud normals fast using integral images. + */ void compute_normals_integral(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::PointCloud<pcl::PointXYZ>& cloud) { //compute normals @@ -72,7 +104,13 @@ void compute_normals_integral(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::Po //For debug: pcl::io::savePCDFileASCII("/tmp/cloud_pointnormals.pcd", pcl_normals); } -// Compute pointcloud normals without using integral images +/** + * /param pcl_normals Output cloud with 3D point normals computed using PCL library. + * /param cloud Input cloud with 3D points we want to compute normals for. + * + * This is a much slower function to compute normal vectors, apt for non-structured point clouds. + * Compute pointcloud normals *without* using integral images. + */ void compute_normals(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::PointCloud<pcl::PointXYZ>& cloud) { //compute normal @@ -85,25 +123,47 @@ void compute_normals(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::PointCloud< } /***************************************************************************************/ -// Simple Integral Images class +/** + * \brief Simple Integral Images class. + * Class to compute simple parallel integral images with floating point accumulators. + * Includes function to compute sum of sub-rectangle. + */ class IIf { public: + /** Vector of float* to store the parallel integral images in linear form.*/ std::vector<float*> ii_; + /** number of bins.*/ unsigned int bins_; + /** width of the integral image.*/ unsigned int width_; + /** height of the integral image.*/ unsigned int height_; + /** + * \param bins Number of bins/parallel integral images. + * \param width Width of the integral image. + * \param height Height of the integral image. + * + * Constructor for empty set of parallel integral image. + */ IIf(unsigned int bins, unsigned int width, unsigned int height):bins_(bins),width_(width),height_(height){ ii_.resize(bins); for(unsigned int i=0;i<bins;i++) ii_[i]=new float[width*height]; } + /** Destructor */ ~IIf(){ for(unsigned int i=0;i<this->bins_;i++) delete [] ii_[i]; } + + /** + * \param im Input vote matrix + * + * Function to construct the set of integral images given an input vote matrix. + */ void construct(std::vector<std::vector<float> > &im){ //0,0 case unsigned int u=0; @@ -151,7 +211,16 @@ public: } } - //get sum of rectangular sub-region + /** + * + * \param tu Top-left u coordinate. + * \param tv Top-left v coordinate. + * \param bu Bottom-right u coordinate. + * \param bv Bottom-right v coordinate. + * \return Vector with sum of the sub-region. + * + * Get sum for each parallel integral image for a rectangular sub-region. + */ std::vector<float> get_sub_rect(unsigned int tu, unsigned int tv, unsigned int bu, unsigned int bv) { std::vector<float> ret(this->bins_); @@ -201,7 +270,7 @@ FindddAlgorithm::FindddAlgorithm(FindddConfig new_cfg) this->set_centroids_file(new_cfg.centroids_file); this->update_centroids(); this->set_positions_file(new_cfg.positions_file); - this->normalize_desc_ = new_cfg.normalize_desc; // * 0 - No norm // * 1 - L1 // * 2 - L2 // * 3 - sqrt + L2 + this->normalize_desc_ = new_cfg.normalize_desc; // * 0 - No norm // * 1 - L1 // * 2 - L2 // * 3 - sqrt + L2 this->use_soft_voting_ = new_cfg.use_soft_voting; this->verbose_level_ = new_cfg.verbose_level; this->update_pca_matrix(new_cfg.pca_file); @@ -363,13 +432,22 @@ void FindddAlgorithm::compute_ndescs_integral_spatial_interpolation(pcl::PointCl std::cout<<"Computed "<<descriptor_set.num<<" descriptors, in "<<(clock()-start)/(float)CLOCKS_PER_SEC<< "s"<<std::endl; } -//method parameters help +/** Method parameters help. + */ void about() { std::cout<<"Usage:\n finddd_descriptor -pcd <file_path> -centroids_file <centroids_path> -descfile <output_descfile_path> [-use_soft_voting <bool>] [-sample_each <step>] [-normalize_desc] [-desc_patch_radius <radius>] [-num_spatial_bins <num_bins_per_side>] [-positions_file <positions_file_path>] [-keep_nan] [-pca_file <file_path>]"<<std::endl; std::cout<<"Parameters:\n -pcd <filename> Input pcd file path.\n -use_soft_voting <bool> Disable soft-voting.\n -sample_each <num_pix> Density of descriptor sampling.\n -normalize_desc <norm> 0=none 1=L1 2=L2 3=sqrt+L2.\n -desc_patch_radius <num_pix> Radius of the local patch.\n -num_spatial_bins <num_bins> Number of local bins per side (sqrt of total bins).\n -centroids_file <filename> Input centroid file path.\n -positions_file <filename> Input locations file path.\n -descfile <filename> Output descriptor file path.\n -pca_file <filename> PCA matrix filename\n"; } +/** + * \param argc Standard argc, number of arguments. + * \param argv Standard argv, arguments in vector of char pointers. + * \param new_conf Output configuration object with parameters according to arguments. + * \return Boolean, true if all parameters valid. + * + * Function to parse command-line arguments. + */ bool parse_args(int argc, char* argv[], FindddConfig& new_conf) { bool valid_args=true; @@ -424,7 +502,13 @@ bool parse_args(int argc, char* argv[], FindddConfig& new_conf) return false; } -//save descs in fvec format (see the yael library for more details. https://gforge.inria.fr/projects/yael/) +/** + * \param pf File pointer where to save the data. + * \param point Descriptor to be saved. + * + * Function to write a descriptor to a file pointer in fvec format (see the yael library for more details: https://gforge.inria.fr/projects/yael/) + * Save descs in fvec format. + */ void write_point_fvec(FILE *pf, const Descriptor &point) { int dim=point.descriptor.size(); @@ -451,7 +535,13 @@ void write_point_fvec(FILE *pf, const Descriptor &point) } } -//save valid descriptors to disk +/** + * \param output_file Filename where descriptors will be saved. + * \param descriptor_set Descriptor set to be saved. + * \param conf Configureation parameters of the descriptors. + * Function to save to disc a set of descriptors computed in a range image. The conf parameter is used to check if descriptors corresponding to NaN 3D points have to be saved or discarded. + * Save valid descriptors to disk. + */ void write_feats(std::string &output_file, DescriptorSet &descriptor_set, FindddConfig &conf) { FILE* pf=fopen(output_file.c_str(),"wb"); @@ -471,7 +561,6 @@ void write_feats(std::string &output_file, DescriptorSet &descriptor_set, Finddd fclose(pf); } - int main(int argc, char* argv[]) { // parse arguments diff --git a/src/finddd_descriptor.hpp b/src/finddd_descriptor.hpp index 372b88994426635be3273c31d0c280bac17aa546..ee4e2a889161bd95db15ceb0747e27fe04ae8ae4 100644 --- a/src/finddd_descriptor.hpp +++ b/src/finddd_descriptor.hpp @@ -25,7 +25,7 @@ inline std::string to_string (const T& t) return ss.str(); } -/** \brief Class for 3D point +/** \brief Class for 3D point. * Very simple class to hold 3D point position information. */ class P3D @@ -40,34 +40,46 @@ public: }; -/** \brief Class to hold one FINDDD descriptor +/** \brief Class to hold one FINDDD descriptor. * This class holds each one of the FINDDD descriptors in a set. * Descriptor data is stored in a vector<float>. */ class Descriptor { public: + /** X-coordinate of the descriptor in image. */ int u; + /** Y-coordinate of the descriptor in image. */ int v; + /** Orientation of the descriptor in image (not used yet). */ float orientation; + /** Corresponding 3D coordinates of the descriptor. */ P3D point3d; + /** Descriptor vector. */ std::vector<float> descriptor; }; -/** \brief Class to hold FINDDD computation parameters +/** \brief Class to hold FINDDD computation parameters. * This class holds a set (vector) of FINDDD descriptors as well as - * parameters of the descriptors and the set and sizes of the original + * parameters of the descriptors in the set and sizes of the original * range image. */ class DescriptorSet { public: + /** Number of orientation bins of each sub-descriptor. */ int num_orient_bins; + /** Number of spatial bins per side of the full descriptor region (sqrt of total). */ int num_spa_bins; + /** Number of descriptors. */ int num; + /** Number of dimensions of the descriptor. */ int len; + /** Width of the original range image. */ int width; + /** Height of the original range image. */ int height; + /** Vector with computed descriptor. */ std::vector<Descriptor> descriptors; DescriptorSet() @@ -82,26 +94,43 @@ public: }; -/** \brief Class to hold FINDDD computation parameters +/** \brief Class to hold FINDDD computation parameters. * This class holds all parameters related to FINDDD computation, and is * used to update the FindddAlgorithm class with user-defined parameters. */ class FindddConfig { public: + /** Num of spatial subdivisions. */ int num_spatial_bins; + /** Side of the patch in pixels. */ int desc_patch_radius; - //int patch_radius; + /** Step in pixels between descriptors. */ int sample_each; + /** File with the normal centroids. */ std::string centroids_file; + /** File with the (u,v) positions where descriptors have to be computed (overrides "sample_each"). */ std::string positions_file; + /** Normalization of new descriptors: + 0 - No norm + 1 - L1 + 2 - L2 + 3 - sqrt + L2 + */ int normalize_desc; + /** Whether to use soft-voting or direct assignment. */ int use_soft_voting; + /** Input pcd file where descriptors have to be computed. */ std::string pcd_file; + /** Output file in "fvec" format containing the computed descriptors. */ std::string geofvecs_file; + /** Whether to keep NaN points or discard them. */ int keep_nan_points; + /** Name of a file containing the mean and the PCA matrix to automatically compress the computed descriptors. If not specified no compression is done. */ std::string pca_file; + /** Verbosity level. */ int verbose_level; + FindddConfig() { verbose_level=1; @@ -119,7 +148,7 @@ public: } }; -/** \brief Main class to compute FINDDD descriptors +/** \brief Main class to compute FINDDD descriptors. * This class contains all the methods necessary to compute FINDDD * descriptors for a range image. */ @@ -130,52 +159,72 @@ protected: // private attributes and methods uint nt_; - // [descriptor attributes] + /** Vector containing the X coordinate of normal centroids. */ std::vector<float> orient_bin_centers_x_; + /** Vector containing the Y coordinate of normal centroids. */ std::vector<float> orient_bin_centers_y_; + /** Vector containing the Z coordinate of normal centroids. */ std::vector<float> orient_bin_centers_z_; + /** Vector containing the U coordinate of points where descriptors have to be computed. */ std::vector<int> desc_compute_positionsX_; + /** Vector containing the V coordinate of points where descriptors have to be computed. */ std::vector<int> desc_compute_positionsY_; + /** Inter-bin distance, to compute soft-votes*/ float radius_inf_; + /** Number of orientation bins in each sub-descriptor. */ uint desc_num_orient_bins_; + /** Number of spatial bins per side of the full descriptor region (sqrt of total). */ uint desc_num_side_spatial_bins_; + /** Total size of the descriptors. */ uint desc_num_total_bins_; + /** Radius of area used to compute descriptor. */ uint desc_patch_radius_; + /** Filename of the normal centroids. */ std::string centroids_file_; + /** Filename of the file with positions where descriptors have to be computed (if specidied overrides "sample_each"). */ std::string positions_file_; + /** Name of file with mean and PCA matrix to compress descriptors on the fly. If not specified no compression is done. */ std::string pca_file_; + /** Normalization of new descriptors: + 0 - No norm + 1 - L1 + 2 - L2 + 3 - sqrt + L2 + */ uint normalize_desc_; + /** Whether to use soft-voting or direct assignment. */ uint use_soft_voting_; + /** Level of verbosity. */ int verbose_level_; - - // [descriptor sampling attributes] + /** Step in pixels between descriptors. */ uint sample_each_; + /** Margin to skip around the image. Currently this variable is unused. */ uint margin_; // [PCA stuff] + /** Variable holding the PCA matrix for on the fly compression. */ std::vector< std::vector<float> > pca_matrix_; + /** Mean of descriptors for PCA compression. */ std::vector<float> pca_mean_; public: - /** - * \brief constructor - * - * In this constructor parameters related to the specific driver can be - * initalized. Those parameters can be also set in the openDriver() function. - * Attributes from the main node driver class IriBaseDriver such as loop_rate, - * may be also overload here. - */ FindddAlgorithm(); + /** + * \brief constructor. + * + * Constructor that takes a FindddConfig object as input parameter. + * + */ FindddAlgorithm(FindddConfig conf); - /** - * \brief Set total descriptor bins - * - * Given the current parameters, this function computes the total - * number of bins of the descriptor. - * - */ + /** + * \brief Set total descriptor bins. + * + * Given the current parameters, this function computes the total + * number of bins of the descriptor. + * + */ inline int compute_total_bins() { this->desc_num_total_bins_ = this->desc_num_side_spatial_bins_ * this->desc_num_side_spatial_bins_ * this->orient_bin_centers_x_.size(); @@ -183,8 +232,9 @@ protected: } /** - * \brief Set number of spatial bins (side) - * + * \brief Set number of spatial bins (side). + * \param nb Number of spatial bins per side of the descriptor support area. + * \return New number of spatial bins per size (same as input). * This function allows to change the number of spatial bins of * the descriptor, and triggers all actions dependant on them. * @@ -198,8 +248,9 @@ protected: /** - * \brief Set patch radius - * + * \brief Set patch radius. + * \param r Radius of the descriptor support region. + * \return New radius of descriptor support region (same as input). * This function allows to change the patch radius of the * descriptor, and triggers all actions dependant on them. * @@ -213,7 +264,8 @@ protected: /** * \brief Set sample each - * + * \param s Step at which descriptors have to be computed. + * \return New step at which descriptors have to be computed (same as input). * Function used to change the spacing between each sampled * position of the grid for descriptor computation. * @@ -225,8 +277,8 @@ protected: } /** - * \brief Update PCA matrix - * + * \brief Update PCA matrix. + * \param new_pca_matrix_file File with the PCA matrix and mean vector. * Update the PCA matrix used to project the computed * descriptors. The function expects a string pointing * to a plain text file with the mean vector followed by @@ -299,8 +351,11 @@ protected: } /** - * \brief Project descriptor using PCA - * + * \brief Project descriptor using PCA. + * \param v Descriptor to compress. + * \param PCA PCA matrix. + * \param mean Mean vector to center descriptor vector. + * \return Compressed descriptor vector. * Project a newly computed descriptor using the PCA * matrix passed as parameter. This function is automatically * executed if "pca_file_" is not NULL. @@ -323,8 +378,8 @@ protected: } /** - * \brief Set centroids file - * + * \brief Set centroids file. + * \param new_centroids_file File containing the normal centroids. * Function used to load the bin centers from a file * */ @@ -334,6 +389,13 @@ protected: this->update_centroids(); } + /** + * \brief Load set of normal centers. + * + * Update centroids with contents of the file pointed by the centroids_file_ variable. + * TODO Not much checking is done to guarantee that the file is consistent! + * + */ inline void update_centroids() { std::string path = this->centroids_file_.c_str(); @@ -355,7 +417,6 @@ protected: ifs >> x; ifs >> y; ifs >> z; - //ROS_INFO("%f %f %f", x,y,z); if(ifs.good()) { this->orient_bin_centers_x_.push_back(x); @@ -373,10 +434,11 @@ protected: } /** - * \brief Set positions file - * + * \brief Set positions file. + * \param new_positions_file * Function used to load the positions of the image where descriptors * will be computed from a list in a file. + * TODO Not much checking is done to guarantee that the file is consistent! * */ inline void set_positions_file(std::string new_positions_file) @@ -386,7 +448,7 @@ protected: this->desc_compute_positionsX_.clear(); this->desc_compute_positionsY_.clear(); - if(this->positions_file_=="") + if(this->positions_file_=="") // No positions file specified. { if(this->verbose_level_>=2) std::cout<<"Generating positions with 'sample_each' param."<<std::endl; @@ -416,10 +478,10 @@ protected: } /** - * \brief Determine vote influence cutoff + * \brief Determine vote influence cutoff. * * Function to compute minimum distance between bin 0 and the rest of bins, - * for vote interpolation. + * for vote interpolation. */ inline void compute_radius_inf() { @@ -443,14 +505,15 @@ protected: } /** - * \brief compute all descriptors with spatial bin support of image using an integral image - * + * \brief compute all descriptors with spatial bin support of image using an integral image. + * \param cloud input structured point cloud loaded from pcd file. + * \param descriptor_set Output computed descriptors. * Main interface to compute normal descriptors with spatial support from a point cloud */ void compute_ndescs_integral_spatial_interpolation(pcl::PointCloud<pcl::PointXYZ>& cloud, DescriptorSet &descriptor_set); /** - * \brief Destructor + * \brief Destructor. * * This destructor is called when the object is about to be destroyed. *